zenstackhq / zenstack

Fullstack TypeScript toolkit that enhances Prisma ORM with flexible Authorization layer for RBAC/ABAC/PBAC/ReBAC, offering auto-generated type-safe APIs and frontend hooks.
https://zenstack.dev
MIT License
2.01k stars 85 forks source link

[Feature Request] ESM support #969

Open ymc9 opened 7 months ago

ymc9 commented 7 months ago

Reported by VT01 on discord.

import { ZenStackMiddleware } from '@zenstackhq/server/express';
Error:
SyntaxError: Named export 'ZenStackMiddleware' not found. The requested module '@zenstackhq/server/express' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@zenstackhq/server/express';
const { ZenStackMiddleware } = pkg;

Node.js v20.11.0

my tsconfig.json:

"compilerOptions": { "target": "esnext", "module": "NodeNext", "moduleResolution": "NodeNext", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "outDir": "./dist", "noUncheckedIndexedAccess": true, "lib": [ "ESNext" ], }

package.json fields that probably causes the mistake (however I need it): "type": "module"

tmax22 commented 5 months ago

we got this error

import { ZenStackMiddleware } from "@zenstackhq/server/express";
         ^

SyntaxError: The requested module '@zenstackhq/server/express' does not provide an export named 'ZenStackMiddleware'
    at ModuleJob._instantiate (node:internal/modules/esm/module_job:132:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:214:5)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at <anonymous> (/home/tmax/development/try-mehadrin/packages/mehadrin-express/src/server.ts:8:17)

Node.js v20.11.1

so we can't use zenstack if our backend uses "type":"module" in package.json? any workarounds until v2.0.0? by the way I think this should be considered a first priority bug and not v2 milestone as es modules are the way to go even in backend environments in 2024

workaround for now

for now, we were able to import it using:

import { createRequire } from "module";
const require = createRequire(import.meta.url);
const { ZenStackMiddleware } = require("@zenstackhq/server/express");

you would also need "moduleResolution": "NodeNext" in tsconfig.json:

{
  "compilerOptions": {
    "module": "NodeNext",
    "esModuleInterop": true,
    "target": "esnext",
    "noImplicitAny": true,
    "moduleResolution": "NodeNext",
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "skipLibCheck": true,
    "strict": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}
sidharthv96 commented 3 months ago

Same issue for generated Zod schemas as well.

import { ModelUpdateScalarSchema } from "@zenstackhq/runtime/zod/models";
        ^^^^^^^^^^^^^^^^^^^^^
SyntaxError: Named export 'ModelUpdateScalarSchema' not found. The requested module '@zenstackhq/runtime/zod/models' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@zenstackhq/runtime/zod/models';
const { ModelUpdateScalarSchema } = pkg;
ymc9 commented 3 months ago

we got this error

import { ZenStackMiddleware } from "@zenstackhq/server/express";
         ^

SyntaxError: The requested module '@zenstackhq/server/express' does not provide an export named 'ZenStackMiddleware'
    at ModuleJob._instantiate (node:internal/modules/esm/module_job:132:21)
    at async ModuleJob.run (node:internal/modules/esm/module_job:214:5)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at <anonymous> (/home/tmax/development/try-mehadrin/packages/mehadrin-express/src/server.ts:8:17)

Node.js v20.11.1

so we can't use zenstack if our backend uses "type":"module" in package.json? any workarounds until v2.0.0? by the way I think this should be considered a first priority bug and not v2 milestone as es modules are the way to go even in backend environments in 2024

workaround for now

for now, we were able to import it using:

import { createRequire } from "module";
const require = createRequire(import.meta.url);
const { ZenStackMiddleware } = require("@zenstackhq/server/express");

you would also need "moduleResolution": "NodeNext" in tsconfig.json:

{
  "compilerOptions": {
    "module": "NodeNext",
    "esModuleInterop": true,
    "target": "esnext",
    "noImplicitAny": true,
    "moduleResolution": "NodeNext",
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "skipLibCheck": true,
    "strict": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}

Hi @tmax22 , sorry I missed this comment. Is this still an issue for you with v2?

ymc9 commented 3 months ago

Same issue for generated Zod schemas as well.

import { ModelUpdateScalarSchema } from "@zenstackhq/runtime/zod/models";
        ^^^^^^^^^^^^^^^^^^^^^
SyntaxError: Named export 'ModelUpdateScalarSchema' not found. The requested module '@zenstackhq/runtime/zod/models' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@zenstackhq/runtime/zod/models';
const { ModelUpdateScalarSchema } = pkg;

Hi @sidharthv96 , did you get this when compiling generated trpc code? Is this still with a sveltekit project?

sidharthv96 commented 3 months ago

Sveltekit itself. I was using zod to validate our REST payload. It works fine locally, but fails to build in CI, when using a different adapter.

And we are on v2

tmax22 commented 3 months ago

actually, in v2, import { ZenStackMiddleware } from '@zenstackhq/server/express'; works just fine for me

genu commented 2 months ago

Running into this myself as well, I'm on zenstack version: 2.2.4:


import { SomeSchema } from 'node_modules/@zenstackhq/runtime/zod/models.js';
         ^^^^^^^^^^^
  SyntaxError: The requested module 'node_modules/@zenstackhq/runtime/zod/models.js' does not provide an export named 'SomeSchema'
  at ModuleJob._instantiate (node:internal/modules/esm/module_job:134:21)
  at async ModuleJob.run (node:internal/modules/esm/module_job:217:5)
  at async ModuleLoader.import (node:internal/modules/esm/loader:323:24)
  at async loadESM (node:internal/process/esm_loader:28:7)
  at async handleMainPromise (node:internal/modules/run_main:120:12)
  ``
genu commented 2 months ago

A workaround, is to change the location where the zod generates the schemas; have it generate in your project the rather than node_modules

Mileage may vary, as you can run into other issues when you generate the zod schema in your own project as now those generated files are subject type checking