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.07k stars 88 forks source link

zenstack generate fails with pnpm #560

Closed lewebsimple closed 1 year ago

lewebsimple commented 1 year ago

Description and expected behavior Generating with zenstack generate fails in Nuxt 3 project when using pnpm (works fine with npm).

Environment (please complete the following information):

Additional context I'm trying to setup ZenStack in a Nuxt project using tRPC but I'm stumbling on the following error when generating the initial client with pnpm:

⠋ Running plugin ZodError compiling generated code:
node_modules/.pnpm/@zenstackhq+runtime@1.0.0-beta.6_@prisma+client@4.16.2/node_modules/.zenstack/zod/input/UserInput.schema.ts:23:26 - error TS2742: The inferred type of 'UserInputSchema' cannot be named without a reference to '.pnpm/@prisma+client@4.16.2_prisma@4.16.2/node_modules/.prisma/client'. This is likely not portable. A type annotation is necessary.

23             export const UserInputSchema = {
                            ~~~~~~~~~~~~~~~
node_modules/.pnpm/@zenstackhq+runtime@1.0.0-beta.6_@prisma+client@4.16.2/node_modules/.zenstack/zod/input/UserInput.schema.ts:23:26 - error TS2742: The inferred type of 'UserInputSchema' cannot be named without a reference to '.pnpm/@prisma+client@4.16.2_prisma@4.16.2/node_modules/@prisma/client/runtime'. This is likely not portable. A type annotation is necessary.

23             export const UserInputSchema = {
                            ~~~~~~~~~~~~~~~
node_modules/.pnpm/@zenstackhq+runtime@1.0.0-beta.6_@prisma+client@4.16.2/node_modules/.zenstack/zod/objects/UserArgs.schema.ts:11:15 - error TS2742: The inferred type of 'UserArgsObjectSchema' cannot be named without a reference to '.pnpm/@prisma+client@4.16.2_prisma@4.16.2/node_modules/@prisma/client/runtime'. This is likely not portable. A type annotation is necessary.

11  export const UserArgsObjectSchema = Schema
                 ~~~~~~~~~~~~~~~~~~~~
node_modules/.pnpm/@zenstackhq+runtime@1.0.0-beta.6_@prisma+client@4.16.2/node_modules/.zenstack/zod/objects/UserSelect.schema.ts:11:15 - error TS2742: The inferred type of 'UserSelectObjectSchema' cannot be named without a reference to '.pnpm/@prisma+client@4.16.2_prisma@4.16.2/node_modules/@prisma/client/runtime'. This is likely not portable. A type annotation is necessary.

11  export const UserSelectObjectSchema = Schema
                 ~~~~~~~~~~~~~~~~~~~~~~

This is likely due to the way Nuxt handles tsconfig.json

NeoN0x commented 1 year ago

Hello,

Same issue with a simpler project, and pnpm, but without Nuxt/any dependency, neither tsconfig.json, when trying zenstack generate, after zenstack init

⠋ Running plugin ZodError compiling generated code:
../node_modules/.pnpm/@zenstackhq+runtime@1.0.0-beta.3_@prisma+client@4.16.2/node_modules/.zenstack/zod/input/PostInput.schema.ts:22:26 - error TS2742: The inferred type of 'PostInputSchema' cannot be named without a reference to '.pnpm/@prisma+client@4.16.2_prisma@4.16.2/node_modules/.prisma/client'. This is likely not portable. A type annotation is necessary.

22             export const PostInputSchema = {
                            ~~~~~~~~~~~~~~~
../node_modules/.pnpm/@zenstackhq+runtime@1.0.0-beta.3_@prisma+client@4.16.2/node_modules/.zenstack/zod/input/PostInput.schema.ts:22:26 - error TS2742: The inferred type of 'PostInputSchema' cannot be named without a reference to '.pnpm/@prisma+client@4.16.2_prisma@4.16.2/node_modules/@prisma/client/runtime'. This is likely not portable. A type annotation is necessary.

(... more error like that)
ymc9 commented 1 year ago

Thanks for reporting this! I'll look into it and share my finding soon.

ymc9 commented 1 year ago

Hi @lewebsimple @NeoN0x , it turns out that tsc is confused by the symlink structure generated by pnpm due to ZenStack's peer dependency on "@prisma/client". I think it's safe to just remove that peer dependency, and the problem should just go away.

I'll make a fix in the upcoming release.

ymc9 commented 1 year ago

Fixed in release 1.0.0-beta.7.

NeoN0x commented 1 year ago

Thanks a lot for your prompt answer & fix.

I'm experimenting with pnpm/pnpm workspace, and just installed zenstack "zenstack": "1.0.0-beta.7" and prisma with pnpm, and having the sample default model (schema.zmodel with User and Post).

However, I'm still having the issue :

$ pnpm zenstack generate
⌛️ ZenStack CLI v1.0.0-beta.7, running plugins
✔ Running plugin Prisma
✔ Running plugin Model Metadata
✔ Running plugin Access Policy
⠋ Running plugin ZodError compiling generated code:
../node_modules/.pnpm/@zenstackhq+runtime@1.0.0-beta.7/node_modules/.zenstack/zod/input/PostInput.schema.ts:22:26 - error TS2742: The inferred type of 'PostInputSchema' cannot be named without a reference to '.pnpm/@prisma+client@4.16.2_prisma@4.16.2/node_modules/.prisma/client'. This is likely not portable. A type annotation is necessary.

22             export const PostInputSchema = {
                            ~~~~~~~~~~~~~~~
../node_modules/.pnpm/@zenstackhq+runtime@1.0.0-beta.7/node_modules/.zenstack/zod/input/PostInput.schema.ts:22:26 - error TS2742: The inferred type of 'PostInputSchema' cannot be named without a reference to '.pnpm/@prisma+client@4.16.2_prisma@4.16.2/node_modules/@prisma/client/runtime'. This is likely not portable. A type annotation is necessary.

22             export const PostInputSchema = {
                            ~~~~~~~~~~~~~~~
(lot of error like that)

But it seems that this is specifically linked to workspace.

By not using workspace, it does not have the error.

My pnpm-workspace.yaml

packages:
  - 'db/**'
  - 'back/**'
  - 'front/**'
  # exclude packages that are inside test directories
  - '!**/src/test/**'

I'm very new to monorepo things, and after googling it (https://typescript.tv/errors/includes/ts2xxx/ts2742) it is something that might be related (quoted: In a monorepository the error TS2742 can show up when you are using a package that has not set a “main” property in its “package.json” file. Sometimes it also happens that there is a “types” property which does not point to the correct typings. Make sure both paths are present and relative:)

If this is not fixable, what do you advise, should Switch back to npm/yarn workspaces ?

ymc9 commented 1 year ago

Hey @NeoN0x , thanks for confirming this! I just tried pnpm workspace and do see the same problems. I thought explicit type annotation could be avoided, but it seems tsc just can't figure out the correct resolutions in some cases. Pnpm is cool but it's symbolic link mechanism has many edge cases :(.

Let me add those annotations and I think the problems should just go away. Will publish a new version soon.

lewebsimple commented 1 year ago

The fix in 1.0.0-beta.7 works flawlessly in the same Nuxt projet that previously didn't work.

Thanks 🎉

update well ... it installs correctly but the generated tRPC routers can't import named exports from @zenstackhq/runtime/zod/input because they are CJS. It seems the following might work:

import zodInput from '@zenstackhq/runtime/zod/input';
const { UserInputSchema, PostInputSchema } = zodInput;

instead of import { UserInputSchema, PostInputSchema } from '@zenstackhq/runtime/zod/input';

ymc9 commented 1 year ago

Hi @NeoN0x , I've added type annotation to the generated Zod schemas and pushed a new "beta.8" release. Could you check if it's working in your project now? Thanks!

NeoN0x commented 1 year ago

Hi @ymc9 ,

I set up the beta.7 to have the exact issue, then only changed to beta.8 and worked perfectly !

Thanks a lot for your dedication ;)

--

For what it worth, further my previous exploration, I managed to use pnpm workspace + beta.7 with the following setting in the schema.zmodel

plugin zod {
  provider = '@core/zod'
  output = 'zod'
}

So I think somehow the issue with using the node_module and conflicted somewhere in the symlink and specifying the output make it clear.

I understand that edge case are very complexe to manage for library like zenstack. I'm also impressed by the by the fix 574 and how it makes this more robust.

ymc9 commented 1 year ago

Awesome! So happy it's working now.

Yes, you're right. If the zod plugin's output location is hoisted outside "node_modules" the problem doesn't happen. Having the default configuration to work flawlessly will probably reduce some friction.

Thanks for catching this issue. Feel free to join discord if you haven't 😄: https://go.zenstack.dev/chat