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

[BUG] Types generated when using `@default(auth().id)` are not compatible with third party libraryes #1440

Closed nahtnam closed 5 months ago

nahtnam commented 5 months ago

Description and expected behavior

https://github.com/nahtnam/zenstack-default-auth-bug

To reproduce, clone this repo and run:

npm install
npx zenstack generate
npx tsc --noEmit

To prove this is related to @default, you can remove it from this line: https://github.com/nahtnam/zenstack-default-auth-bug/blob/main/schema.zmodel#L38

Then regenerate zenstack and check the types

Also to prove that this is not a bug with the repo, you can change this line to directly use the prisma client and typescript will not complain: https://github.com/nahtnam/zenstack-default-auth-bug/blob/main/src/app/admin/%5B%5B...nextadmin%5D%5D/page.tsx#L20

Screenshots

Type 'import("/zenstack-default-auth-bug/node_modules/.zenstack/.logical-prisma-client/index-fixed").PrismaClient<import("/zenstack-default-auth-bug/node_modules/.zenstack/.logical-prisma-client/index-fixed").Prisma.PrismaClientOptions, never, import("/zen...' is not assignable to type 'import("/zenstack-default-auth-bug/node_modules/.prisma/client/index").PrismaClient<import("/zenstack-default-auth-bug/node_modules/.prisma/client/index").Prisma.PrismaClientOptions, never, import("/zenstack-default-auth-bug/node_module...'.
  Types of property '$transaction' are incompatible.
    Type '{ <P extends import("/zenstack-default-auth-bug/node_modules/.zenstack/.logical-prisma-client/index-fixed").Prisma.PrismaPromise<any>[]>(arg: [...P], options?: { ...; } | undefined): Promise<...>; <R>(fn: (prisma: Omit<...>) => Promise<...>, options?: { ...; } | undefined): Promise<...>; }' is not assignable to type '{ <P extends import("/zenstack-default-auth-bug/node_modules/.prisma/client/index").Prisma.PrismaPromise<any>[]>(arg: [...P], options?: { isolationLevel?: import("/zenstack-default-auth-bug/node_modules/.prisma/client/index").Prisma.TransactionIsolationLevel | un...'.
      Types of parameters 'arg' and 'fn' are incompatible.
        Type '(prisma: Omit<PrismaClient<PrismaClientOptions, never, DefaultArgs>, "$connect" | "$disconnect" | "$on" | "$transaction" | "$use" | "$extends">) => Promise<...>' is not assignable to type 'any[]'.

20     prisma: db,
       ~~~~~~

  node_modules/@premieroctet/next-admin/dist/utils/props.d.ts:11:5
    11     prisma: PrismaClient;
           ~~~~~~
    The expected type comes from property 'prisma' which is declared here on type 'Omit<GetPropsFromParamsParams, "isAppDir">'

Found 1 error in src/app/admin/[[...nextadmin]]/page.tsx:20

Environment (please complete the following information):

Additional context N/A

ymc9 commented 5 months ago

Hi @nahtnam , thanks for filing this.

I checked the code and it seems next-admin has a hard-coded dependency to @prisma/client and doesn't allow customize its typing. Have you tried casting the enhanced prismaclient back to PrismaClient type and see if it works?

When using auth() in @default(), the only difference between zenstack-enhanced client and the original client's typing is the optionality of that field. It probably won't makes a real difference I suppose.

nahtnam commented 5 months ago

Awesome, that seemed to do the trick! Do you know if there will ever be a case in the future where the change is not so type safe? Where type casting might cause issues?

In this case it's totally fine like you said because the types that the next-admin library uses is stricter