Skip to content

Commit

Permalink
restore missing prisma docs
Browse files Browse the repository at this point in the history
  • Loading branch information
hayes committed Dec 16, 2024
1 parent cb6bb47 commit d08974f
Show file tree
Hide file tree
Showing 9 changed files with 504 additions and 0 deletions.
125 changes: 125 additions & 0 deletions website/content/docs/plugins/prisma/indirect-relations.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
title: Indirect relations
description: Indirect relations and join tables
---
## Selecting fields from a nested GraphQL field

By default, the `nestedSelection` function will return selections based on the type of the current
field. `nestedSelection` can also be used to get a selection from a field nested deeper inside other
fields. This is useful if the field returns a type that is not a `prismaObject`, but a field nested
inside the returned type is.

```typescript
const PostRef = builder.prismaObject('Post', {
fields: (t) => ({
title: t.exposeString('title'),
content: t.exposeString('content'),
author: t.relation('author'),
}),
});

const PostPreview = builder.objectRef<Post>('PostPreview').implement({
fields: (t) => ({
post: t.field({
type: PostRef,
resolve: (post) => post,
}),
preview: t.string({
nullable: true,
resolve: (post) => post.content?.slice(10),
}),
}),
});

builder.prismaObject('User', {
fields: (t) => ({
id: t.exposeID('id'),
postPreviews: t.field({
select: (args, ctx, nestedSelection) => ({
posts: nestedSelection(
{
// limit the number of postPreviews to load
take: 2,
},
// Look at the selections in postPreviews.post to determine what relations/fields to select
['post'],
// (optional) If the field returns a union or interface, you can pass a typeName to get selections for a specific object type
'Post',
),
}),
type: [PostPreview],
resolve: (user) => user.posts,
}),
}),
});
```

## Indirect relations (eg. Join tables)

If you want to define a GraphQL field that directly exposes data from a nested relationship (many to
many relations using a custom join table is a common example of this) you can use the
`nestedSelection` function passed to `select`.

Given a prisma schema like the following:

```
model Post {
id Int @id @default(autoincrement())
title String
content String
media PostMedia[]
}
model Media {
id Int @id @default(autoincrement())
url String
posts PostMedia[]
uploadedBy User @relation(fields: [uploadedById], references: [id])
uploadedById Int
}
model PostMedia {
id Int @id @default(autoincrement())
post Post @relation(fields: [postId], references: [id])
media Media @relation(fields: [mediaId], references: [id])
postId Int
mediaId Int
}
```

You can define a media field that can pre-load the correct relations based on the graphql query:

```typescript
const PostDraft = builder.prismaObject('Post', {
fields: (t) => ({
title: t.exposeString('title'),
media: t.field({
select: (args, ctx, nestedSelection) => ({
media: {
select: {
// This will look at what fields are queried on Media
// and automatically select uploadedBy if that relation is requested
media: nestedSelection(
// This arument is the default query for the media relation
// It could be something like: `{ select: { id: true } }` instead
true,
),
},
},
}),
type: [Media],
resolve: (post) => post.media.map(({ media }) => media),
}),
}),
});

const Media = builder.prismaObject('Media', {
select: {
id: true,
},
fields: (t) => ({
url: t.exposeString('url'),
uploadedBy: t.relation('uploadedBy'),
}),
});
```
46 changes: 46 additions & 0 deletions website/content/docs/plugins/prisma/interfaces.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
title: Interfaces
description: Creating interfaces for prisma models that can be shared by variants
---

`builder.prismaInterface` works just like builder.prismaObject and can be used to define either the
primary type or a variant for a model.

The following example creates a `User` interface, and 2 variants Admin and Member. The `resolveType`
method returns the typenames as strings to avoid issues with circular references.

```typescript
builder.prismaInterface('User', {
name: 'User',
fields: (t) => ({
id: t.exposeID('id'),
email: t.exposeString('email'),
}),
resolveType: (user) => {
return user.isAdmin ? 'Admin' : 'Member';
},
});

builder.prismaObject('User', {
variant: 'Admin',
interfaces: [User],
fields: (t) => ({
isAdmin: t.exposeBoolean('isAdmin'),
}),
});

builder.prismaObject('User', {
variant: 'Member',
interfaces: [User],
fields: (t) => ({
bio: t.exposeString('bio'),
}),
});
```

When using select mode, it's recommended to add selections to both the interface and the object
types that implement them. Selections are not inherited and will fallback to the default selection
which includes all scalar columns.

You will not be able to extend an interface for a different prisma model, doing so will result in an
error at build time.
4 changes: 4 additions & 0 deletions website/content/docs/plugins/prisma/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
"setup",
"objects",
"relations",
"selections",
"relay",
"connections",
"variants",
"indirect-relations",
"interfaces",
"prisma-utils",
"without-a-plugin",
"..."
Expand Down
9 changes: 9 additions & 0 deletions website/content/docs/plugins/prisma/objects.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,12 @@ take advantage of more efficient queries.
The `query` object will contain an object with `include` or `select` options to pre-load data needed
to resolve nested parts of the current query. The included/selected fields are based on which fields
are being queried, and the options provided when defining those fields and types.


## Extending prisma objects

The normal `builder.objectField(s)` methods can be used to extend prisma objects, but do not support
using selections, or exposing fields not in the default selection. To use these features, you can
use

`builder.prismaObjectField` or `builder.prismaObjectFields` instead.
22 changes: 22 additions & 0 deletions website/content/docs/plugins/prisma/relations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,25 @@ builder.prismaObject('User', {
}),
});
```

### relationCount

Prisma supports querying for
[relation counts](https://www.prisma.io/docs/concepts/components/prisma-client/aggregation-grouping-summarizing#count-relations)
which allow including counts for relations along side other `includes`. Before prisma 4.2.0, this
does not support any filters on the counts, but can give a total count for a relation. Starting from
prisma 4.2.0, filters on relation count are available under the `filteredRelationCount` preview
feature flag.

```typescript
builder.prismaObject('User', {
fields: (t) => ({
id: t.exposeID('id'),
postCount: t.relationCount('posts', {
where: {
published: true,
},
}),
}),
});
```
1 change: 1 addition & 0 deletions website/content/docs/plugins/prisma/relay.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,4 @@ builder.prismaNode('Post', {
}),
});
```

Loading

0 comments on commit d08974f

Please sign in to comment.