diff --git a/docs/guides/authentication/clerk.md b/docs/guides/authentication/clerk.md index efc1beae..889c5d4f 100644 --- a/docs/guides/authentication/clerk.md +++ b/docs/guides/authentication/clerk.md @@ -17,16 +17,15 @@ First, follow Clerk's [quick start guides](https://clerk.com/docs/quickstarts/ov ### Adjust your ZModel -Since Clerk manages both user authentication and storage, you don't need to store users in your database anymore. However, since the `auth()` function is resolved to the `User` model in ZModel, you still need to define it in your schema. The trick here is to mark the `User` model as ignored so Prisma doesn't map it to a database table. +Since Clerk manages both user authentication and storage, you don't need to store users in your database anymore. However, you still need to provide a type that the `auth()` function can resolve to. Instead of using a regular model, we can declare a `type` instead: -You can include any field you want in the `User` model, as long as you provide the same set of fields in the context object used for creating the enhanced Prisma client. +You can include any field you want in the `User` type, as long as you provide the same set of fields in the context object used for creating the enhanced Prisma client. The following code shows an example blog post schema: ```zmodel -model User { +type User { id String @id - @@ignore } model Post { @@ -45,7 +44,7 @@ model Post { } ``` -If you choose to [synchronize user data to your database](https://clerk.com/docs/users/sync-data-to-your-backend), you can model the `User` model as a regular Prisma model without putting the `@@ignore` attribute there. +If you choose to [synchronize user data to your database](https://clerk.com/docs/users/sync-data-to-your-backend), you can define `User` as a regular `model` since it's then backed by a database table. ### Create an enhanced Prisma client @@ -63,10 +62,10 @@ import { auth } from "@clerk/nextjs/server"; import { prisma } from '../lib/db'; async function getPrisma() { - const authObject = auth(); + const authObject = await auth(); // create a wrapper of Prisma client that enforces access policy return enhance(prisma, { - user: authObject ? { id: authObject.userId } : undefined, + user: authObject.userId ? { id: authObject.userId } : undefined, }); } ``` diff --git a/docs/guides/client-extensions.md b/docs/guides/client-extensions.md index e77b5eec..401ba8f7 100644 --- a/docs/guides/client-extensions.md +++ b/docs/guides/client-extensions.md @@ -5,7 +5,7 @@ sidebar_position: 11 # Using With Prisma Client Extensions -[Prisma Client Extension](https://www.prisma.io/docs/orm/prisma-client/client-extensions) is a mechanism for extending the interface and functionality of Prisma Client. This guide introduces two ways of using ZenStack with client extensions and their implications. +[Prisma Client Extension](https://www.prisma.io/docs/orm/prisma-client/client-extensions) is a mechanism for extending the interface and functionality of Prisma Client. We'll use the following ZModel as a reference throughout this guide: @@ -98,11 +98,11 @@ Currently there's a limitation that computed fields are not governed by field-le ## Installing extensions to an enhanced Prisma Client -Such a setup DOES NOT WORK as you would expect in most cases, so it should generally be avoided. For example, +Since v2.9.0, installing client extensions to an enhanced Prisma Client should generate the same result as doing it the opposite way - i.e., call `enhance` on an extended Prisma Client, as explained in the previous section. ```ts -const enhanced = enhance(prisma); -const db = enhanced.$extends({ +const db = enhance(prisma); +const extended = db.$extends({ model: { post: { async getFeeds() { @@ -113,26 +113,6 @@ const db = enhanced.$extends({ }, }); -const feeds = await db.post.getFeeds(); -``` - -The `getFeeds()` call will return all posts (both published and unpublished ones). This is due to how Prisma internally implements the client extensions. Although you're calling `$extends` on an enhanced client, inside the extension, the context (returned by `Prisma.getExtensionContext(this)`) bypasses ZenStack and directly calls into the original Prisma client. - -You can refactor the code to make it work by explicitly referencing the enhanced client in the extension: - -```ts -const enhanced = enhance(prisma); -const db = enhanced.$extends({ - model: { - post: { - async getFeeds() { - return enhanced.post.findMany(); - }, - }, - }, -}); - -const feeds = await db.post.getFeeds(); +const feeds = await extended.post.getFeeds(); +// `feeds` will only contain published posts ``` - -It may or may not be practical, depending on the structure of your code base. diff --git a/docs/guides/typing-json.md b/docs/guides/typing-json.md index 949e8355..2ddca5ccb 100644 --- a/docs/guides/typing-json.md +++ b/docs/guides/typing-json.md @@ -93,7 +93,7 @@ await db.user.create({ // profile: { // name: string; // age: number; -// address: { +// address?: { // state: string; // city: string; // zip: string; diff --git a/docs/reference/plugins/openapi.mdx b/docs/reference/plugins/openapi.mdx index 71bbe56f..a16816e4 100644 --- a/docs/reference/plugins/openapi.mdx +++ b/docs/reference/plugins/openapi.mdx @@ -15,17 +15,18 @@ npm install --save-dev @zenstackhq/openapi ### Options -| Name | Type | Description | Required | Default | -| --------------- | ------ | ----------------------------------------------------------------------------- | -------- | ---------------------- | -| output | String | Output file path (with suffix .yaml or .json, relative to the path of ZModel) | Yes | | -| flavor | String | API flavor: "rpc" or "rest". See [here](../server-adapters/api-handlers/) for more details. | No | rpc | -| specVersion | String | OpenAPI specification version | No | 3.1.0 | -| title | String | API title | No | ZenStack Generated API | -| version | String | API version | No | 1.0.0 | -| prefix | String | API path prefix, e.g., '/api' | No | | -| description | String | API description | No | | -| summary | String | API summary | No | | -| securitySchemes | Object | Security schemes for the API. See [here](#security-schemes) for more details. | No | | +| Name | Type | Description | Required | Default | +| ---------------- | ------- | ----------------------------------------------------------------------------- | -------- | ---------------------- | +| output | String | Output file path (with suffix .yaml or .json, relative to the path of ZModel) | Yes | | +| flavor | String | API flavor: "rpc" or "rest". See [here](../server-adapters/api-handlers/) for more details. | No | rpc | +| specVersion | String | OpenAPI specification version | No | 3.1.0 | +| title | String | API title | No | ZenStack Generated API | +| version | String | API version | No | 1.0.0 | +| prefix | String | API path prefix, e.g., '/api' | No | | +| description | String | API description | No | | +| summary | String | API summary | No | | +| securitySchemes | Object | Security schemes for the API. See [here](#security-schemes) for more details. | No | | +| omitInputDetails | Boolean | **Only valid for "rpc" flavor.** If true, the output spec will not contain detailed structures for query/mutation input fields like `where`, `select`, `data`, etc. These fields will be typed as generic objects. Use this option to reduce the size of the generated spec. | No | false | #### API flavor diff --git a/docs/reference/plugins/tanstack-query.mdx b/docs/reference/plugins/tanstack-query.mdx index 79508b27..ced7caf7 100644 --- a/docs/reference/plugins/tanstack-query.mdx +++ b/docs/reference/plugins/tanstack-query.mdx @@ -30,11 +30,12 @@ npm install --save-dev @zenstackhq/tanstack-query ### Options -| Name | Type | Description | Required | Default | -| ------- | ------ | ------------------------------------------------------- | -------- | ------- | -| output | String | Output directory (relative to the path of ZModel) | Yes | | -| target | String | Target framework to generate for. Choose from "react", "vue", and "svelte". | Yes | | -| version | String | Version of TanStack Query to generate for. Choose from "v4" and "v5". | No | v5 | +| Name | Type | Description | Required | Default | +| -------- | ------- | ------------------------------------------------------- | -------- | ------- | +| output | String | Output directory (relative to the path of ZModel) | Yes | | +| target | String | Target framework to generate for. Choose from "react", "vue", and "svelte". | Yes | | +| version | String | Version of TanStack Query to generate for. Choose from "v4" and "v5". | No | v5 | +| portable | Boolean | Include TypeScript types needed to compile the generated code in the output directory. Useful when you output into another project that doesn't reference Prisma and ZenStack. You'll still need to install the "@zenstackhq/tanstack-query" package in that project. | No | false | ### Hooks Signature diff --git a/docs/the-complete-guide/part1/4-access-policy/4.3-current-user.md b/docs/the-complete-guide/part1/4-access-policy/4.3-current-user.md index 4c2ee237..cbc341ad 100644 --- a/docs/the-complete-guide/part1/4-access-policy/4.3-current-user.md +++ b/docs/the-complete-guide/part1/4-access-policy/4.3-current-user.md @@ -46,22 +46,18 @@ model MyUser { :::info What if I don't store users in the database? -If you use an external authentication service like Clerk or Supabase Auth, you can choose not to store users in the database, since the auth services are already doing this for you. However, in ZModel, the `auth()` function call always needs to be resolved to an auth model. +If you use an external authentication service like Clerk or Supabase Auth, you can choose not to store users in the database, since the auth services are already doing this for you. However, in ZModel, the `auth()` function call always needs to be resolved to a typing. -The trick here is to still define an auth model, but mark it with the `@@ignore` attribute so that it's excluded from the generated PrismaClient. +The solution is to use a `type` instead of a `model` to define the shape of `auth()`. A `type` can contain fields as models do, the it's not mapped to a database table, and only serves the purpose of typing. ```zmodel -model User { +type User { id String @id ... - - @@ignore } ``` -Also, when you generate Prisma migrations, make sure to remove the code generated for the `User` model. - -Since the `User` model is not mapped to a database table, you shouldn't have other models to have relations to it. Instead, you can store the user id provided by the authentication service in your models, which is like a "foreign key" but pointing to an external system. +Since `User` is not mapped to a database table, you can't have other models to have relations to it. Instead, you can store the user id provided by the authentication service in your models, which is like a "foreign key" but pointing to an external system. :::