Skip to content

Commit

Permalink
docs: release v2.9.0 (#389)
Browse files Browse the repository at this point in the history
  • Loading branch information
ymc9 authored Nov 18, 2024
1 parent dacdddd commit 25ce01c
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 58 deletions.
13 changes: 6 additions & 7 deletions docs/guides/authentication/clerk.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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

Expand All @@ -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,
});
}
```
Expand Down
32 changes: 6 additions & 26 deletions docs/guides/client-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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() {
Expand All @@ -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.
2 changes: 1 addition & 1 deletion docs/guides/typing-json.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ await db.user.create({
// profile: {
// name: string;
// age: number;
// address: {
// address?: {
// state: string;
// city: string;
// zip: string;
Expand Down
23 changes: 12 additions & 11 deletions docs/reference/plugins/openapi.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
11 changes: 6 additions & 5 deletions docs/reference/plugins/tanstack-query.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.

:::

Expand Down

0 comments on commit 25ce01c

Please sign in to comment.