PluginsPrisma Next

Setup

npm install --save @pothos/plugin-prisma-next

Setup

The plugin needs your prisma-next contract at type-check time and at runtime. Both come from the same JSON file emitted by prisma-next contract emit.

Generate your contract

Run prisma-next's contract emit step against your schema. The output is a JSON file plus a .d.ts carrying the contract type. Check the prisma-next docs for the up-to-date command — this plugin treats the contract as the source of truth for model names, relation names, column types, and FK metadata.

prisma-next contract emit

Set up the builder

import SchemaBuilder from '@pothos/core';
import RelayPlugin from '@pothos/plugin-relay';
import prismaNextPlugin from '@pothos/plugin-prisma-next';
import sqlite from '@prisma-next/sqlite/runtime';

import contractJson from './prisma/contract.json' with { type: 'json' };
import type { Contract } from './prisma/contract';

// Connect the orm-client.
const client = sqlite<Contract>({
  contractJson,
  path: './app.db',
});
await client.connect();

const builder = new SchemaBuilder<{
  // Threads the contract through every plugin method — model names,
  // relation names, column names, and row shapes are inferred from it.
  PrismaNextContract: Contract;
  Context: { db: typeof client };
}>({
  plugins: [RelayPlugin, prismaNextPlugin],
  relay: {},
  prismaNext: {
    contract: contractJson as Contract,
  },
});

If you forget to set PrismaNextContract on SchemaTypes, autocomplete will point at a sentinel string explaining what to configure. The plugin's helper types collapse without a contract.

Plugin options

Set on builder.options.prismaNext:

prismaNext: {
  contract,                    // required
  defaultConnectionSize: 20,   // default `first:` for all connections
  maxConnectionSize: 100,      // hard cap on connection page size
  skipDeferredFragments: true, // ignore `@defer` fragments in the
                               // preload (default: true)
}

defaultConnectionSize / maxConnectionSize flow through both t.prismaConnection and t.relatedConnection. They're overridden by per-field defaultSize / maxSize options when those are set.

Loading the orm-client per request

The example above uses a single shared client. You can also keep the client in context if you need per-request isolation (e.g. one connection pool per tenant):

const builder = new SchemaBuilder<{
  PrismaNextContract: Contract;
  Context: { db: ReturnType<typeof sqlite<Contract>> };
}>({
  plugins: [prismaNextPlugin],
  prismaNext: { contract: contractJson as Contract },
});

// Resolvers reach the client via `ctx.db.orm.<Model>`:
builder.queryType({
  fields: (t) => ({
    users: t.prismaField({
      type: ['User'],
      resolve: (_root, _args, ctx) => ctx.db.orm.User,
    }),
  }),
});