Prisma Generator Pothos Codegen
![Group 1](https://github.com/Cauen/prisma-generator-pothos-codegen/assets/8796757/19f6cdbe-44f5-40ac-8b9b-326c49c1c281)
A prisma generator plugin that auto-generates Pothos GraphQL input types and crud operations (all queries and mutations).
Easily convert a prisma schema into a full graphql CRUD API.
On prisma generate
we create:
- All input types for
Create
, Find
, Update
, Sort
and Delete
operations (to be used as args in fields). - (Optional): Create all
Objects
, Queries
and Mutations
base files (to create customizable resolvers). - (Optional): Execute all these base files without customization to create a default CRUD.
Table of Contents
Getting Started
Install
Using yarn
yarn add -D prisma-generator-pothos-codegen
or using npm
npm install --save-dev prisma-generator-pothos-codegen
Peer dependencies
The package has been developed and tested up to the following peer dependencies (see updated example):
"@pothos/core": "^3.41.0",
"@pothos/plugin-prisma": "^3.65.0",
"@prisma/client": "^5.15.1",
"prisma": "^5.15.1",
Using higher versions may break something. In these cases, please open a new issue.
Set Up
Add the generator to your schema.prisma
generator client {
provider = "prisma-client-js"
}
generator pothos {
provider = "prisma-pothos-types"
}
generator pothosCrud {
provider = "prisma-generator-pothos-codegen"
generatorConfigPath = "./pothos.config.js"
// You may also set the `generatorConfigPath` via the `POTHOS_CRUD_CONFIG_PATH` environment variable.
// The environment variable will override the path hardcoded here.
}
/// This is a user!
model User {
/// This is an id!
id String @id
}
Add scalar types to the builder
import { Scalars } from 'prisma-generator-pothos-codegen';
import { Prisma } from '.prisma/client';
export const builder = new SchemaBuilder<{
PrismaTypes: PrismaTypes;
Scalars: Scalars<Prisma.Decimal, Prisma.InputJsonValue | null, Prisma.InputJsonValue>;
}>({
});
Create a configuration file (optional)
module.exports = {
inputs: {
outputFilePath: './src/graphql/__generated__/inputs.ts',
},
crud: {
outputDir: './src/graphql/__generated__/',
inputsImporter: `import * as Inputs from '@graphql/__generated__/inputs';`,
resolverImports: `import prisma from '@lib/prisma';`,
prismaCaller: 'prisma',
},
global: {
},
};
Click to see all configuration options
{
inputs?: {
simple?: boolean;
prismaImporter?: string;
outputFilePath?: string;
excludeScalars?: string[];
replacer?: Replacer<'inputs'>;
mapIdFieldsToGraphqlId?: false | 'WhereUniqueInputs';
};
crud?: {
disabled?: boolean;
inputsImporter?: string;
prismaImporter?: string;
prismaCaller?: string;
resolverImports?: string;
outputDir?: string;
replacer?: Replacer<'crud'>;
generateAutocrud?: boolean;
excludeResolversContain?: string[];
excludeResolversExact?: string[];
includeResolversContain?: string[];
includeResolversExact?: string[];
deleteOutputDirBeforeGenerate?: boolean;
exportEverythingInObjectsDotTs?: boolean;
mapIdFieldsToGraphqlId?: false | 'Objects';
underscoreBetweenObjectVariableNames?: false | 'Objects';
};
global?: {
replacer?: Replacer;
builderLocation?: string;
beforeGenerate?: (dmmf: DMMF.Document) => void;
afterGenerate?: (dmmf: DMMF.Document) => void;
};
}
Run the generator
yarn prisma generate
or
npx prisma generate
Usage
Inputs
You can use @Pothos.omit()
function calls in your prisma schema field descriptions to control which fields are used in the generated input types.
@Pothos.omit()
Omits the field from all inputs@Pothos.omit(create)
Omits field from the create input@Pothos.omit(orderBy, where, update)
Omits field from the orderBy, where, and update inputs, but not the create input
The available options are create
, update
, where
, and orderBy
.
model User {
/// @Pothos.omit(create, update)
id String @id @default(uuid())
email String
/// @Pothos.omit()
password String
}
You can also augment/derive new inputs from the generated inputs.ts
file.
import { Prisma } from '@prisma/client';
import { UserUpdateInputFields } from '@/graphql/__generated__/inputs';
export const UserUpdateInputCustom = builder
.inputRef<Prisma.UserUpdateInput & { customArg: string }>('UserUpdateInputCustom')
.implement({
fields: (t) => ({
...UserUpdateInputFields(t),
customArg: t.field({ required: true, type: 'String' }),
}),
});
Objects
import { UserObject } from '@/graphql/__generated__/User';
import { builder } from '@/graphql/builder';
builder.prismaObject('User', UserObject);
builder.prismaObject('User', {
...UserObject,
fields: (t) => {
const { password: _password, email: emailAddress, ...fields } = UserObject.fields(t);
const sessionsField = UserSessionsFieldObject(t);
return {
...fields,
emailAddress,
sessions: t.relation('sessions', {
...sessionsField,
args: { ...sessionsField.args, customArg: t.arg({ type: 'String', required: false }) },
authScopes: { admin: true },
}),
customField: t.field({ type: 'String', resolve: () => 'Hello world!' }),
};
},
});
Queries and Mutations
import { findManyUserQuery, findManyUserQueryObject } from '@/graphql/__generated__/User';
import { builder } from '@/graphql/builder';
builder.queryFields(findManyUserQuery);
builder.queryFields((t) => {
const field = findManyUserQueryObject(t);
return {
findManyUser: t.prismaField({
...field,
args: { ...field.args, customArg: t.arg({ type: 'String', required: false }) },
resolve: async (query, root, args, context, info) => {
const { customArg } = args;
console.log(customArg);
return field.resolve(query, root, args, context, info);
},
authScopes: { admin: true },
}),
};
});
Auto define all objects
, queries
and mutations
(crud operations)
First, make sure that options.crud.generateAutocrud
isn't set to false
import {
generateAllCrud,
generateAllObjects,
generateAllQueries,
generateAllMutations
} from '@/graphql/__generated__/autocrud.ts',
import { builder } from '@/graphql/builder';
generateAllCrud()
generateAllObjects()
generateAllQueries()
generateAllMutations()
generateAllObjects({ include: ["User", "Profile", 'Comment'] })
generateAllQueries({ exclude: ["Comment"] })
generateAllMutations({ exclude: ["User"] })
builder.queryType({});
builder.mutationType({});
export const schema = builder.toSchema({});
Generated queries:
- count
- findFirst
- findMany
- findUnique
Generated mutations:
- createMany
- createOne
- deleteMany
- deleteOne
- updateMany
- updateOne
- upsertOne
Examples
Check for the example for a running sample
![image](https://user-images.githubusercontent.com/8796757/222917186-9a88f5e9-27c6-44b5-8653-fa9efb0aa255.png)
Disclosures
Models with only relations
- We create a custom scalar
NEVER
that avoids this error: Input Object type FollowUpdateManyMutationInput must define one or more fields.
from Graphql. if you have models that are relations-only. Like N-N fields without no relation fields
or id-only models, we set field _
of some operations to this scalar. If you fill this fake property, the operation will result in a error.
BigInt rename
- As
BigInt
is reserved, we export Bigint
for the BigInt scalar.