A prisma generator that generate input types for Pothos. And optionally generate all crud.
npm install prisma-generator-pothos-codegenA 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.
- Getting Started
* Install
* Peer dependencies
* Set Up
+ Add the generator to your schema.prisma
+ Add scalar types to the builder
+ Create a configuration file (optional)
+ Run the generator
- Usage
* Inputs
* Objects
* Queries and Mutations
* Auto define all objects, queries and mutations (crud operations)
* Examples
- Disclosures
* Models with only relations
* BigInt rename
Using yarn
``sh`
yarn add -D prisma-generator-pothos-codegen
or using npm
`sh`
npm install --save-dev prisma-generator-pothos-codegen
The package has been developed and tested up to the following peer dependencies (see updated example):
``
"@pothos/core": "^4.0.2",
"@pothos/plugin-prisma": "^4.0.3"",
"@prisma/client": "^5.15.1",
"prisma": "^5.15.1",
Using higher versions may break something. In these cases, please open a new issue.
#### Add the generator to your schema.prisma
`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
`ts
import { Scalars } from 'prisma-generator-pothos-codegen';
import { Prisma } from '.prisma/client';
export const builder = new SchemaBuilder<{
// ... Context, plugins? ...
PrismaTypes: PrismaTypes; // required for @pothos/plugin-prisma integration (which is required)
Scalars: Scalars
}>({
// Other builder config
});
`
#### Create a configuration file (optional)
`js
// ./pothos.config.js
/* @type {import('prisma-generator-pothos-codegen').Config} /
module.exports = {
inputs: {
outputFilePath: './src/graphql/__generated__/inputs.ts',
},
crud: {
outputDir: './src/graphql/__generated__/',
inputsImporter: import * as Inputs from '@graphql/__generated__/inputs';,import prisma from '@lib/prisma';
resolverImports: ,`
prismaCaller: 'prisma',
},
global: {
},
};
Click to see all configuration options
`tsfalse
{
/* Input type generation config /
inputs?: {
/* Create simpler inputs for easier customization and ~65% less generated code. Default: /"import { Prisma } from '.prisma/client';"
simple?: boolean;
/* How to import the Prisma namespace. Default: /'./generated/inputs.ts'
prismaImporter?: string;
/* Path to generate the inputs file to from project root. Default: /false
outputFilePath?: string;
/* List of excluded scalars from generated output /
excludeScalars?: string[];
/* A function to replace generated source. Combined with global replacer config /
replacer?: Replacer<'inputs'>;
/** Map all Prisma fields with "@id" attribute to Graphql "ID" Scalar.
*
ATTENTION: Mapping non String requires a conversion inside resolver, once GraphQl ID Input are coerced to String by definition. Default: false /
mapIdFieldsToGraphqlId?: false | 'WhereUniqueInputs';
};
/* CRUD generation config /
crud?: {
/* Disable generaton of crud. Default: /"import as Inputs from '../inputs';"
disabled?: boolean;
/* How to import the inputs. Default */"import { Prisma } from '.prisma/client';"
inputsImporter?: string;
/* How to import the Prisma namespace at the objects.ts file. Default . Please use "resolverImports" to import prismaClient at resolvers. /'_context.prisma'
prismaImporter?: string;
/* How to call the prisma client. Default /''
prismaCaller?: string;
/* Any additional imports you might want to add to the resolvers (e.g. your prisma client). Default: /'./generated'
resolverImports?: string;
/* Directory to generate crud code into from project root. Default: /autocrud.ts
outputDir?: string;
/* A function to replace generated source. Combined with global replacer config /
replacer?: Replacer<'crud'>;
/* A boolean to enable/disable generation of which can be imported in schema root to auto generate all crud objects, queries and mutations. Default: true /UserName
generateAutocrud?: boolean;
/* An array of parts of resolver names to be excluded from generation. Ie: ["User"] Default: [] /
excludeResolversContain?: string[];
/* An array of resolver names to be excluded from generation. Ie: ["upsertOneComment"] Default: [] /
excludeResolversExact?: string[];
/* An array of parts of resolver names to be included from generation (to bypass exclude contain). Ie: if exclude ["User"], include ["UserReputation"] Default: [] /
includeResolversContain?: string[];
/* An array of resolver names to be included from generation (to bypass exclude contain). Ie: if exclude ["User"], include ["UserReputation"] Default: [] /
includeResolversExact?: string[];
/* Caution: This delete the whole folder (Only use if the folder only has auto generated contents). A boolean to delete output dir before generate. Default: False /
deleteOutputDirBeforeGenerate?: boolean;
/* Export all crud queries/mutations/objects in objects.ts at root dir. Default: true /
exportEverythingInObjectsDotTs?: boolean;
/* Map all Prisma fields with "@id" attribute to Graphql "ID" Scalar. Default: 'Objects' /
mapIdFieldsToGraphqlId?: false | 'Objects';
/* Change the generated variables from object.base.ts from something like to User_Name. This avoids generated duplicated names in some cases. See issue #58. Default: false /id
underscoreBetweenObjectVariableNames?: false | 'Objects';
/* Generate a virtual field for models that don't have a simple id field (e.g. composite primary keys like consultingId_agendaItemId, other "id" fiends or unique fields like email). The generated field returns a string concatenation of the primary key fields. Default: false /`
generatePrimaryKeyId?: boolean;
};
/* Global config /
global?: {
/* A function to replace generated source /
replacer?: Replacer;
/* Location of builder to replace in all files. Relative to package root. ie: './src/schema/builder'. Default: './builder' /
builderLocation?: string;
/* Run function before generate /
beforeGenerate?: (dmmf: DMMF.Document) => void;
/* Run function after generate /
afterGenerate?: (dmmf: DMMF.Document) => void;
};
}
#### Run the generator
`sh`
yarn prisma generate
or
`sh`
npx prisma generate
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.
`prisma`
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.
`ts
// ./src/graphql/User/inputs.ts
import { Prisma } from '@prisma/client';
// Import generated input fields definition
import { UserUpdateInputFields } from '@/graphql/__generated__/inputs';
// Note: you can't use builder.inputType to generate this new input`
export const UserUpdateInputCustom = builder
.inputRef
.implement({
fields: (t) => ({
...UserUpdateInputFields(t),
customArg: t.field({ required: true, type: 'String' }),
}),
});
`ts
// ./src/graphql/User/object.ts
import { UserObject } from '@/graphql/__generated__/User';
import { builder } from '@/graphql/builder'; // Pothos schema builder
// Use the Object export to accept all default generated query code
builder.prismaObject('User', UserObject);
// Or modify it as you wish
builder.prismaObject('User', {
...UserObject,
fields: (t) => {
// Type-safely omit and rename fields
const { password: _password, email: emailAddress, ...fields } = UserObject.fields(t);
const sessionsField = UserSessionsFieldObject(t);
return {
...fields,
// Renamed field
emailAddress,
// Edit and extend field
sessions: t.relation('sessions', {
...sessionsField,
args: { ...sessionsField.args, customArg: t.arg({ type: 'String', required: false }) },
authScopes: { admin: true },
}),
// Add custom fields
customField: t.field({ type: 'String', resolve: () => 'Hello world!' }),
};
},
});
`
`ts
// ./src/graphql/User/query.ts
import { findManyUserQuery, findManyUserQueryObject } from '@/graphql/__generated__/User';
import { builder } from '@/graphql/builder'; // Pothos schema builder
// Use the Query exports to accept all default generated query code
builder.queryFields(findManyUserQuery);
// Use the QueryObject exports to override or add to the generated code
builder.queryFields((t) => {
const field = findManyUserQueryObject(t);
return {
findManyUser: t.prismaField({
// Inherit all the generated properties
...field,
// Modify the args and use custom arg in a custom resolver
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);
},
// Add an custom extension
authScopes: { admin: true },
}),
};
});
`
First, make sure that options.crud.generateAutocrud isn't set to false
`ts
// ./src/schema/index.ts (import autocrud.ts)
import {
generateAllCrud,
generateAllObjects,
generateAllQueries,
generateAllMutations
} from '@/graphql/__generated__/autocrud.ts',
import { builder } from '@/graphql/builder'; // Pothos schema builder
// (option 1) generate all objects, queries and mutations
generateAllCrud()
// (option 2) or create them separately
generateAllObjects()
generateAllQueries()
generateAllMutations()
// (option 3) or limit crud generation
generateAllObjects({ include: ["User", "Profile", 'Comment'] })
generateAllQueries({ exclude: ["Comment"] })
generateAllMutations({ exclude: ["User"] })
// Defining schema roots
builder.queryType({});
builder.mutationType({});
export const schema = builder.toSchema({});
`
Generated queries:
- count
- findFirst
- findMany
- findUnique
Generated mutations:
- createMany
- createOne
- deleteMany
- deleteOne
- updateMany
- updateOne
- upsertOne
Check for the example for a running sample
- 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.
- As BigInt is reserved, we export Bigint` for the BigInt scalar.