Skip to content

Instantly share code, notes, and snippets.

@benedyktdryl
Forked from deckchairlabs/filters.js
Created March 7, 2022 22:46
Show Gist options
  • Save benedyktdryl/271ebf6abd0e0f2b36efaf19501222a7 to your computer and use it in GitHub Desktop.
Save benedyktdryl/271ebf6abd0e0f2b36efaf19501222a7 to your computer and use it in GitHub Desktop.
Prisma Custom Generator
#!/usr/bin/env node
const path = require('path')
const generatorHelper = require('@prisma/generator-helper')
const { Project, StructureKind, VariableDeclarationKind } = require('ts-morph')
generatorHelper.generatorHandler({
onManifest(config) {
return {
prettyName: 'Filters',
defaultOutput: path.resolve(__dirname, 'filters'),
requiresGenerators: ['nexus-prisma'],
}
},
onGenerate(options) {
const project = new Project({
skipAddingFilesFromTsConfig: true,
})
const outputPath = options.generator.output.value
const enums = options.dmmf.datamodel.enums
const models = options.dmmf.datamodel.models
const indexSource = project.createSourceFile(
`${outputPath}/index.ts`,
{
statements: [
{
kind: StructureKind.ImportDeclaration,
namedImports: ['Prisma'],
moduleSpecifier: '@prisma/client',
},
{
kind: StructureKind.ImportDeclaration,
namedImports: ['enumType', 'inputObjectType'],
moduleSpecifier: 'nexus',
},
],
},
{
overwrite: true,
}
)
if (models.length > 0) {
indexSource.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: 'SortOrderEnum',
initializer(writer) {
writer
.write('enumType(')
.indent(1)
.inlineBlock(() => {
writer.writeLine(`name: 'SortOrder',`)
writer.writeLine('members: Prisma.SortOrder')
})
.write(')')
.newLine()
},
},
],
})
indexSource.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: 'IDFilterInputType',
initializer(writer) {
writer
.write('inputObjectType(')
.indent(1)
.inlineBlock(() => {
writer.writeLine(`name: 'IDFilterInput',`)
writer.write('definition(t)')
writer.block(() => {
writer.writeLine(`t.id('equals')`)
writer.writeLine(`t.list.id('in')`)
writer.writeLine(`t.list.id('notIn')`)
writer.writeLine(`t.id('lt')`)
writer.writeLine(`t.id('lte')`)
writer.writeLine(`t.id('gt')`)
writer.writeLine(`t.id('gte')`)
writer.writeLine(
`t.field('not', { type: 'IDFilterInput' })`
)
})
})
.write(')')
.newLine()
},
},
],
})
indexSource.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: 'StringFilterInputType',
initializer(writer) {
writer
.write('inputObjectType(')
.indent(1)
.inlineBlock(() => {
writer.writeLine(`name: 'StringFilterInput',`)
writer.write('definition(t)')
writer.block(() => {
writer.writeLine(`t.string('equals')`)
writer.writeLine(`t.string('contains')`)
writer.writeLine(`t.string('startsWith')`)
writer.writeLine(`t.string('endsWith')`)
writer.writeLine(`t.list.string('in')`)
writer.writeLine(`t.list.string('notIn')`)
writer.writeLine(`t.string('lt')`)
writer.writeLine(`t.string('lte')`)
writer.writeLine(`t.string('gt')`)
writer.writeLine(`t.string('gte')`)
writer.writeLine(
`t.field('not', { type: 'StringFilterInput' })`
)
})
})
.write(')')
.newLine()
},
},
],
})
indexSource.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: 'DateTimeFilterInputType',
initializer(writer) {
writer
.write('inputObjectType(')
.indent(1)
.inlineBlock(() => {
writer.writeLine(`name: 'DateTimeFilterInput',`)
writer.write('definition(t)')
writer.block(() => {
writer.writeLine(`t.field('equals', { type: 'DateTime' })`)
writer.writeLine(`t.list.field('in', { type: 'DateTime' })`)
writer.writeLine(
`t.list.field('notIn', { type: 'DateTime' })`
)
writer.writeLine(`t.field('lt', { type: 'DateTime' })`)
writer.writeLine(`t.field('lte', { type: 'DateTime' })`)
writer.writeLine(`t.field('gt', { type: 'DateTime' })`)
writer.writeLine(`t.field('gte', { type: 'DateTime' })`)
writer.writeLine(
`t.field('not', { type: 'DateTimeFilterInput' })`
)
})
})
.write(')')
.newLine()
},
},
],
})
indexSource.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: 'IntFilterInputType',
initializer(writer) {
writer
.write('inputObjectType(')
.indent(1)
.inlineBlock(() => {
writer.writeLine(`name: 'IntFilterInput',`)
writer.write('definition(t)')
writer.block(() => {
writer.writeLine(`t.int('equals')`)
writer.writeLine(`t.list.int('in')`)
writer.writeLine(`t.list.int('notIn')`)
writer.writeLine(`t.int('lt')`)
writer.writeLine(`t.int('lte')`)
writer.writeLine(`t.int('gt')`)
writer.writeLine(`t.int('gte')`)
writer.writeLine(
`t.field('not', { type: 'IntFilterInput' })`
)
})
})
.write(')')
.newLine()
},
},
],
})
indexSource.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: 'BooleanFilterInputType',
initializer(writer) {
writer
.write('inputObjectType(')
.indent(1)
.inlineBlock(() => {
writer.writeLine(`name: 'BooleanFilterInput',`)
writer.write('definition(t)')
writer.block(() => {
writer.writeLine(`t.boolean('equals')`)
writer.writeLine(
`t.field('not', { type: 'BooleanFilterInput' })`
)
})
})
.write(')')
.newLine()
},
},
],
})
models.forEach((model) => {
indexSource.addExportDeclaration({
moduleSpecifier: `./${model.name}`,
namespaceExport: model.name,
})
const whereUniqueInputTypeName = `${model.name}WhereUniqueInput`
const whereInputTypeName = `${model.name}WhereInput`
const orderByInputTypeName = `${model.name}OrderByInput`
const modelRelationFilterName = `${model.name}RelationFilterInput`
const modelListRelationFilterName = `${model.name}ListRelationFilterInput`
const sourceFile = project.createSourceFile(
`${outputPath}/${model.name}.ts`,
{
statements: [
{
kind: StructureKind.ImportDeclaration,
namedImports: ['inputObjectType'],
moduleSpecifier: 'nexus',
},
],
},
{
overwrite: true,
}
)
sourceFile.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: `${whereUniqueInputTypeName}Type`,
initializer(writer) {
writer
.write('inputObjectType(')
.inlineBlock(() => {
writer.writeLine(`name: '${whereUniqueInputTypeName}',`)
writer.writeLine('definition(t)')
writer.inlineBlock(() => {
writer.writeLine(`t.nonNull.id('id')`)
})
})
.write(')')
.newLine()
},
},
],
})
sourceFile.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: `${whereInputTypeName}Type`,
initializer(writer) {
writer
.write('inputObjectType(')
.inlineBlock(() => {
writer.writeLine(`name: '${whereInputTypeName}',`)
writer.writeLine('definition(t)')
writer.inlineBlock(() => {
model.fields.forEach((field) => {
if (field.kind === 'scalar') {
if (
field.name === 'id' ||
field.name.endsWith('Id')
) {
writer.write(`t.field('${field.name}',`)
writer
.inlineBlock(() => {
writer.writeLine(`type: 'IDFilterInput'`)
})
.write(')')
.newLine()
} else {
writer.write(`t.field('${field.name}',`)
writer
.inlineBlock(() => {
writer.writeLine(
`type: '${field.type}FilterInput'`
)
})
.write(')')
.newLine()
}
} else if (field.kind === 'object') {
if (field.isList) {
writer
.write(`t.field('${field.name}',`)
.inlineBlock(() => {
writer.writeLine(
`type: '${field.type}ListRelationFilterInput'`
)
})
.write(')')
.newLine()
} else {
writer
.write(`t.field('${field.name}',`)
.inlineBlock(() => {
writer.writeLine(
`type: '${field.type}RelationFilterInput'`
)
})
.write(')')
.newLine()
}
} else if (field.kind === 'enum') {
writer
.write(`t.field('${field.name}',`)
.inlineBlock(() => {
writer.writeLine(
`type: '${field.type}EnumFilterInput'`
)
})
.write(')')
.newLine()
}
})
writer.writeLine(
`t.list.field('AND', { type: '${whereInputTypeName}' })`
)
writer.writeLine(
`t.list.field('OR', { type: '${whereInputTypeName}' })`
)
writer.writeLine(
`t.list.field('NOT', { type: '${whereInputTypeName}' })`
)
})
})
.write(')')
.newLine()
},
},
],
})
sourceFile.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: `${modelRelationFilterName}Type`,
initializer(writer) {
writer
.write('inputObjectType(')
.inlineBlock(() => {
writer.writeLine(`name: '${modelRelationFilterName}',`)
writer.writeLine('definition(t)')
writer.inlineBlock(() => {
writer.writeLine(
`t.field('is', { type: '${whereInputTypeName}' })`
)
writer.writeLine(
`t.field('isNot', { type: '${whereInputTypeName}' })`
)
})
})
.write(')')
.newLine()
},
},
],
})
sourceFile.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: `${modelListRelationFilterName}Type`,
initializer(writer) {
writer
.write('inputObjectType(')
.inlineBlock(() => {
writer.writeLine(`name: '${modelListRelationFilterName}',`)
writer.writeLine('definition(t)')
writer.inlineBlock(() => {
writer.writeLine(
`t.field('every', { type: '${whereInputTypeName}' })`
)
writer.writeLine(
`t.field('some', { type: '${whereInputTypeName}' })`
)
writer.writeLine(
`t.field('none', { type: '${whereInputTypeName}' })`
)
})
})
.write(')')
.newLine()
},
},
],
})
sourceFile.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: `${orderByInputTypeName}Type`,
initializer(writer) {
writer
.write('inputObjectType(')
.inlineBlock(() => {
writer.writeLine(`name: '${orderByInputTypeName}',`)
writer.writeLine('definition(t)')
writer.inlineBlock(() => {
model.fields.forEach((field) => {
if (field.kind === 'scalar' || field.kind === 'enum') {
writer.writeLine(
`t.field('${field.name}', { type: 'SortOrder' })`
)
} else if (field.kind === 'object') {
const relatedModel = models.find(
(model) => model.name === field.type
)
if (relatedModel) {
writer.writeLine(
`t.field('${field.name}', { type: '${relatedModel.name}OrderByInput' })`
)
}
}
})
})
})
.write(')')
.newLine()
},
},
],
})
sourceFile.formatText({
indentSize: 2,
convertTabsToSpaces: true,
semicolons: 'remove',
})
})
if (enums.length > 0) {
enums.forEach((enumModel) => {
indexSource.addVariableStatement({
declarationKind: VariableDeclarationKind.Const,
isExported: true,
declarations: [
{
name: `${enumModel.name}EnumFilterInputType`,
initializer(writer) {
writer
.write('inputObjectType(')
.indent(1)
.inlineBlock(() => {
writer.writeLine(
`name: '${enumModel.name}EnumFilterInput',`
)
writer.write('definition(t)')
writer.block(() => {
writer.writeLine(
`t.field('equals', { type: '${enumModel.name}' })`
)
writer.writeLine(
`t.list.field('in', { type: '${enumModel.name}' })`
)
writer.writeLine(
`t.list.field('notIn', { type: '${enumModel.name}' })`
)
writer.writeLine(
`t.field('lt', { type: '${enumModel.name}' })`
)
writer.writeLine(
`t.field('lte', { type: '${enumModel.name}' })`
)
writer.writeLine(
`t.field('gt', { type: '${enumModel.name}' })`
)
writer.writeLine(
`t.field('gte', { type: '${enumModel.name}' })`
)
writer.writeLine(
`t.field('not', { type: '${enumModel.name}EnumFilterInput' })`
)
})
})
.write(')')
.newLine()
},
},
],
})
})
}
indexSource.formatText({
indentSize: 2,
convertTabsToSpaces: true,
semicolons: 'remove',
})
}
project.save()
},
})
generator prisma_client {
provider = "prisma-client-js"
previewFeatures = ["orderByRelation"]
}
// Add your custom generator
generator filters {
provider = "./prisma/filters.js"
output = "./api/src/generated/filters"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment