Setup
npm install --save @pothos/plugin-prisma
Setup
This plugin requires a little more setup than other plugins because it integrates with the prisma to generate some types that help the plugin better understand your prisma schema. Previous versions of this plugin used to infer all required types from the prisma client itself, but this resulted in a poor dev experience because the complex types slowed down editors, and some more advanced use cases could not be typed correctly.
Add a the pothos
generator to your prisma schema
generator pothos {
provider = "prisma-pothos-types"
}
Now the types Pothos uses will be generated whenever you re-generate your prisma client. Run the following command to re-generate the client and create the new types:
npx prisma generate
additional options:
clientOutput
: Where the generated code will import the PrismaClient from. The default is the full path of wherever the client is generated. If you are checking in the generated file, using@prisma/client
is a good option.output
: Where to write the generated types
Example with more options:
generator pothos {
provider = "prisma-pothos-types"
clientOutput = "@prisma/client"
output = "./pothos-types.ts"
}
When using the new prisma-client
generator, the clientOutput
option should match the output
option of the prisma-client
generator:
generator client {
provider = "prisma-client"
output = "./prisma-client"
}
generator pothos {
provider = "prisma-pothos-types"
clientOutput = "./prisma-client"
output = "./pothos-types.ts"
}
Set up the builder
import SchemaBuilder from '@pothos/core';
import { PrismaClient } from '@prisma/client';
import PrismaPlugin from '@pothos/plugin-prisma';
// This is the default location for the generator, but this can be
// customized as described above.
// Using a type only import will help avoid issues with undeclared
// exports in esm mode
import type PrismaTypes from '@pothos/plugin-prisma/generated';
const prisma = new PrismaClient({});
const builder = new SchemaBuilder<{
PrismaTypes: PrismaTypes;
}>({
plugins: [PrismaPlugin],
prisma: {
client: prisma,
// defaults to false, uses /// comments from prisma schema as descriptions
// for object types, relations and exposed fields.
// descriptions can be omitted by setting description to false
exposeDescriptions: boolean | { models: boolean, fields: boolean },
// use where clause from prismaRelatedConnection for totalCount (defaults to true)
filterConnectionTotalCount: true,
// warn when not using a query parameter correctly
onUnusedQuery: process.env.NODE_ENV === 'production' ? null : 'warn',
},
});
It is strongly recommended NOT to put your prisma client into Context
. This will result in slower
type-checking and a laggy developer experience in VSCode. See
this issue for more details.
You can also load or create the prisma client dynamically for each request. This can be used to periodically re-create clients or create read-only clients for certain types of users.
import SchemaBuilder from '@pothos/core';
import { PrismaClient, Prisma } from '@prisma/client';
import PrismaPlugin from '@pothos/plugin-prisma';
import type PrismaTypes from '@pothos/plugin-prisma/generated';
const prisma = new PrismaClient({});
const readOnlyPrisma = new PrismaClient({
datasources: {
db: {
url: process.env.READ_ONLY_REPLICA_URL,
},
},
});
const builder = new SchemaBuilder<{
Context: { user: { isAdmin: boolean } };
PrismaTypes: PrismaTypes;
}>({
plugins: [PrismaPlugin],
prisma: {
client: (ctx) => (ctx.user.isAdmin ? prisma : readOnlyPrisma),
// Because the prisma client is loaded dynamically, we need to explicitly provide the some information about the prisma schema
dmmf: Prisma.dmmf,
},
});
Edge run-times
When prisma is built for edge run-times like cloudflare workers, the prisma client no-longer exposes the dmmf datamodel Pothos uses when building the schema. To work around this, you can have the pothos generator generate the datamodel instead:
generator pothos {
provider = "prisma-pothos-types"
clientOutput = "@prisma/client"
output = "./pothos-types.ts"
generateDatamodel = true
documentation = false
}
When using the generateDatamodel
option, the prisma client will add a getDatamodel
function in
the generated output. When using this option, you should be using a .ts
file rather than a .d.ts
file for the output.
When setting up the builder, you can now use the getDatamodel
function:
import SchemaBuilder from '@pothos/core';
import { PrismaClient, Prisma } from '@prisma/client';
import PrismaPlugin from '@pothos/plugin-prisma';
import type PrismaTypes from '@pothos/plugin-prisma/generated';
import { getDatamodel } from '@pothos/plugin-prisma/generated';
const prisma = new PrismaClient({});
const builder = new SchemaBuilder<{
Context: { user: { isAdmin: boolean } };
PrismaTypes: PrismaTypes;
}>({
plugins: [PrismaPlugin],
prisma: {
client: prisma,
dmmf: getDatamodel(),
},
});
Detecting unused query arguments
Forgetting to spread the query
argument from t.prismaField
or t.prismaConnection
into your
prisma query can result in inefficient queries, or even missing data. To help catch these issues,
the plugin can warn you when you are not using the query argument correctly.
the onUnusedQuery
option can be set to warn
or error
to enable this feature. When set to
warn
it will log a warning to the console if Pothos detects that you have not properly used the
query in your resolver. Similarly if you set the option to error
it will throw an error instead.
You can also pass a function which will receive the info
object which can be used to log or throw
your own error.
This check is fairly naive and works by wrapping the properties on the query with a getter that sets
a flag if the property is accessed. If no properties are accessed on the query object before the
resolver returns, it will trigger the onUnusedQuery
condition.
It's recommended to enable this check in development to more quickly find potential issues.