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.17k stars 89 forks source link

[Feature Request] Support for non-model types #783

Open ymc9 opened 1 year ago

ymc9 commented 1 year ago

We can introduce a pure "type" construct into ZModel to complement the "model" construct. Contrary to "model", "type"s are not mapped to database tables and are purely for type-checking purposes.

Here are some scenarios that can be enabled by type:

  1. Strong-typed JSON field #784

    type Profile {
        bio String
        avatar String
    }
    
    model User {
        ...
        profile Profile @json
    }
  2. Type-checking for plugin options #613

    Today, plugin options are just plain arbitrary properties, and there's no parse-time checking at all. With the "type" construct, plugins can define their own options type, and users can enjoy parse-time error reporting and IDE auto-completion.

  3. More flexible auth() typing

    Today, the typing of auth() function is confined to the User model. To use something out of it, you'll have to use a hack: define a field in User but mark it as @ignore. With "type" construct, one can use a type (completely decoupled from database tables) to back auth().

    type MyAuth {
        ...
        @@auth()
    }
  4. Foundation for modeling non-database entities

    To support modeling entities residing in other systems (3rd-party APIs, e.g., a stripe payment). Related to #563

  5. Enable reusing attributes at the field level

    Propsed by Erik from Discord:

    type Slug extends String @db.VarChar(50) @regex('^[0-9a-zA-Z_]{4,50}$') @default(cuid()) @unique
    
    model Post {
      slug Slug
    }

Other notes:

AmruthPillai commented 5 months ago

Wouldn't it be wise to use another keyword other than type as Prisma might have plans on using the same keyword for relational databases, but for a different construct? Something like abstract auth { } or even auth User { } comes to mind.