UNPKG

@stryke/prisma-trpc-generator

Version:

A fork of the prisma-trpc-generator code to work in ESM with Prisma v6.

1 lines 19 kB
{"version":3,"file":"model-helpers.mjs","names":[],"sources":["../../src/zod/model-helpers.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/stryke\n Documentation: https://docs.stormsoftware.com/projects/stryke\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type {\n DMMF,\n EnvValue,\n GeneratorOptions\n} from \"@prisma/generator-helper\";\nimport { lowerCaseFirst } from \"@stryke/string-format/lower-case-first\";\nimport path from \"node:path\";\nimport type {\n CodeBlockWriter,\n ImportDeclarationStructure,\n SourceFile\n} from \"ts-morph\";\nimport { StructureKind, VariableDeclarationKind } from \"ts-morph\";\nimport type { Config } from \"../config\";\nimport { getPrismaInternals } from \"../utils/get-prisma-internals\";\nimport { getJSDocs, getZodDocElements } from \"./docs-helpers\";\n\nexport function checkModelHasModelRelation(model: DMMF.Model) {\n const { fields: modelFields } = model;\n for (const modelField of modelFields) {\n const isRelationField = checkIsModelRelationField(modelField);\n if (isRelationField) {\n return true;\n }\n }\n return false;\n}\n\nexport function checkModelHasManyModelRelation(model: DMMF.Model) {\n const { fields: modelFields } = model;\n for (const modelField of modelFields) {\n const isManyRelationField = checkIsManyModelRelationField(modelField);\n if (isManyRelationField) {\n return true;\n }\n }\n return false;\n}\n\nexport function checkIsModelRelationField(modelField: DMMF.Field) {\n const { kind, relationName } = modelField;\n\n return kind === \"object\" && !!relationName;\n}\n\nexport function checkIsManyModelRelationField(modelField: DMMF.Field) {\n return checkIsModelRelationField(modelField) && modelField.isList;\n}\n\nexport function findModelByName(models: DMMF.Model[], modelName: string) {\n return models.find(({ name }) => name === modelName);\n}\n\nexport const writeArray = (\n writer: CodeBlockWriter,\n array: string[],\n newLine = true\n) => array.forEach(line => writer.write(line).conditionalNewLine(newLine));\n\nexport const useModelNames = ({\n modelCase,\n modelSuffix,\n relationModel\n}: Config) => {\n const formatModelName = (name: string, prefix = \"\") => {\n if (modelCase === \"camelCase\") {\n name = name.slice(0, 1).toLowerCase() + name.slice(1);\n }\n return `${prefix}${name}${modelSuffix}`;\n };\n\n return {\n modelName: (name: string) =>\n formatModelName(name, relationModel === \"default\" ? \"_\" : \"\"),\n relatedModelName: (\n name: string | DMMF.SchemaEnum | DMMF.OutputType | DMMF.SchemaArg\n ) =>\n formatModelName(\n relationModel === \"default\"\n ? name.toString()\n : `Related${name.toString()}`\n )\n };\n};\n\nexport const dotSlash = (input: string) => {\n const converted = input\n .replace(/^\\\\\\\\\\?\\\\/, \"\")\n .replace(/\\\\/g, \"/\")\n .replace(/\\/{2,}/g, \"/\");\n\n if (converted.includes(`/node_modules/`))\n return converted.split(`/node_modules/`).slice(-1)[0];\n\n if (converted.startsWith(`../`)) return converted;\n\n return `./${converted}`;\n};\n\nexport const chunk = <T extends any[]>(input: T, size: number): T[] => {\n return input.reduce((arr, item, idx) => {\n return idx % size === 0\n ? [...arr, [item]]\n : [...(arr as T).slice(0, -1), [...(arr as T).slice(-1)[0], item]];\n }, []);\n};\n\nexport const needsRelatedModel = (model: DMMF.Model, config: Config) =>\n model.fields.some(field => field.kind === \"object\") &&\n config.relationModel !== false;\n\nexport const writeImportsForModel = async (\n model: DMMF.Model,\n sourceFile: SourceFile,\n config: Config,\n options: GeneratorOptions\n) => {\n const internals = await getPrismaInternals();\n\n const outputPath = internals.parseEnvValue(\n options.generator.output as EnvValue\n );\n\n const { relatedModelName } = useModelNames(config);\n const importList: ImportDeclarationStructure[] = [\n {\n kind: StructureKind.ImportDeclaration,\n namespaceImport: \"z\",\n moduleSpecifier: \"zod\"\n }\n ];\n\n if (config.imports) {\n importList.push({\n kind: StructureKind.ImportDeclaration,\n namespaceImport: \"imports\",\n moduleSpecifier: dotSlash(\n path.relative(\n outputPath,\n path.resolve(path.dirname(options.schemaPath), config.imports)\n )\n )!\n });\n }\n\n if (config.useDecimalJs && model.fields.some(f => f.type === \"Decimal\")) {\n importList.push({\n kind: StructureKind.ImportDeclaration,\n namedImports: [\"Decimal\"],\n moduleSpecifier: \"decimal.js\"\n });\n }\n\n const enumFields = model.fields.filter(f => f.kind === \"enum\");\n const relationFields = model.fields.filter(f => f.kind === \"object\");\n\n const clientPath = options.otherGenerators.find(\n each => each.provider.value === \"prisma-client-js\"\n )!.output!.value!;\n\n const relativePath = path.relative(outputPath, clientPath);\n\n if (enumFields.length > 0) {\n importList.push({\n kind: StructureKind.ImportDeclaration,\n isTypeOnly: enumFields.length === 0,\n moduleSpecifier: dotSlash(relativePath)!,\n namedImports: enumFields.map(f => f.type)\n });\n }\n\n if (config.relationModel !== false && relationFields.length > 0) {\n const filteredFields = relationFields.filter(f => f.type !== model.name);\n\n if (filteredFields.length > 0) {\n importList.push({\n kind: StructureKind.ImportDeclaration,\n moduleSpecifier: \"./index\",\n namedImports: Array.from(\n new Set(\n filteredFields.flatMap(f => [`${f.type}`, relatedModelName(f.type)])\n )\n )\n });\n }\n }\n\n sourceFile.addImportDeclarations(importList);\n};\n\nexport const computeCustomSchema = (docString: string) => {\n return getZodDocElements(docString)\n .find(modifier => modifier.startsWith(\"custom(\"))\n ?.slice(7)\n .slice(0, -1);\n};\n\nexport const computeModifiers = (docString: string) => {\n return getZodDocElements(docString).filter(\n each => !each.startsWith(\"custom(\")\n );\n};\n\nexport const getZodConstructor = (\n field: DMMF.Field,\n getRelatedModelName = (\n name: string | DMMF.SchemaEnum | DMMF.OutputType | DMMF.SchemaArg\n ) => name.toString()\n) => {\n let zodType = \"z.unknown()\";\n const extraModifiers: string[] = [\"\"];\n if (field.kind === \"scalar\") {\n switch (field.type) {\n case \"String\":\n zodType = \"z.string()\";\n break;\n case \"Int\":\n zodType = \"z.number()\";\n extraModifiers.push(\"int()\");\n break;\n case \"BigInt\":\n zodType = \"z.bigint()\";\n break;\n case \"DateTime\":\n zodType = \"z.date()\";\n break;\n case \"Float\":\n zodType = \"z.number()\";\n break;\n case \"Decimal\":\n zodType = \"z.number()\";\n break;\n case \"Json\":\n zodType = \"jsonSchema\";\n break;\n case \"Boolean\":\n zodType = \"z.boolean()\";\n break;\n // TODO: Proper type for bytes fields\n case \"Bytes\":\n zodType = \"z.unknown()\";\n break;\n }\n } else if (field.kind === \"enum\") {\n zodType = `z.nativeEnum(${field.type})`;\n } else if (field.kind === \"object\") {\n zodType = getRelatedModelName(field.type);\n }\n\n if (field.isList) extraModifiers.push(\"array()\");\n if (field.documentation) {\n zodType = computeCustomSchema(field.documentation) ?? zodType;\n extraModifiers.push(...computeModifiers(field.documentation));\n }\n if (!field.isRequired && field.type !== \"Json\")\n extraModifiers.push(\"nullish()\");\n // if (field.hasDefaultValue) extraModifiers.push('optional()')\n\n return `${zodType}${extraModifiers.join(\".\")}`;\n};\n\nexport const writeTypeSpecificSchemas = (\n model: DMMF.Model,\n sourceFile: SourceFile,\n config: Config\n) => {\n if (model.fields.some(f => f.type === \"Json\")) {\n sourceFile.addStatements(writer => {\n writer.newLine();\n writeArray(writer, [\n \"// Helper schema for JSON fields\",\n `type Literal = boolean | number | string${\n config.prismaJsonNullability ? \"\" : \"| null\"\n }`,\n \"type Json = Literal | { [key: string]: Json } | Json[]\",\n `const literalSchema = z.union([z.string(), z.number(), z.boolean()${\n config.prismaJsonNullability ? \"\" : \", z.null()\"\n }])`,\n \"const jsonSchema: z.ZodSchema<Json> = z.lazy(() => z.union([literalSchema, z.array(jsonSchema), z.record(jsonSchema)]))\"\n ]);\n });\n }\n\n if (config.useDecimalJs && model.fields.some(f => f.type === \"Decimal\")) {\n sourceFile.addStatements(writer => {\n writer.newLine();\n writeArray(writer, [\n \"// Helper schema for Decimal fields\",\n \"z\",\n \".instanceof(Decimal)\",\n \".or(z.string())\",\n \".or(z.number())\",\n \".refine((value) => {\",\n \" try {\",\n \" return new Decimal(value);\",\n \" } catch (error) {\",\n \" return false;\",\n \" }\",\n \"})\",\n \".transform((value) => new Decimal(value));\"\n ]);\n });\n }\n};\n\nexport const generateSchemaForModel = (\n model: DMMF.Model,\n sourceFile: SourceFile,\n config: Config\n) => {\n const { modelName } = useModelNames(config);\n\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n leadingTrivia: writer => writer.blankLineIfLastNot(),\n declarations: [\n {\n name: modelName(model.name),\n initializer(writer) {\n writer\n .write(\"z.object(\")\n .inlineBlock(() => {\n model.fields\n .filter(f => f.kind !== \"object\")\n .forEach(field => {\n writeArray(writer, getJSDocs(field.documentation));\n writer\n .write(`${field.name}: ${getZodConstructor(field)}`)\n .write(\",\")\n .newLine();\n });\n })\n .write(\")\");\n }\n }\n ]\n });\n};\n\nexport const generateRelatedSchemaForModel = (\n model: DMMF.Model,\n sourceFile: SourceFile,\n config: Config\n) => {\n const { modelName, relatedModelName } = useModelNames(config);\n\n const relationFields = model.fields.filter(f => f.kind === \"object\");\n\n sourceFile.addInterface({\n name: `${model.name}`,\n isExported: true,\n extends: [`z.infer<typeof ${modelName(model.name)}>`],\n properties: relationFields.map(f => ({\n hasQuestionToken: !f.isRequired,\n name: f.name,\n type: `${f.type}${f.isList ? \"[]\" : \"\"}${!f.isRequired ? \" | null\" : \"\"}`\n }))\n });\n\n sourceFile.addStatements(writer =>\n writeArray(writer, [\n \"\",\n \"/**\",\n ` * ${relatedModelName(\n model.name\n )} contains all relations on your model in addition to the scalars`,\n \" *\",\n \" * NOTE: Lazy required in case of potential circular dependencies within schema\",\n \" */\"\n ])\n );\n\n sourceFile.addVariableStatement({\n declarationKind: VariableDeclarationKind.Const,\n isExported: true,\n declarations: [\n {\n name: relatedModelName(model.name),\n type: `z.ZodSchema<${model.name}>`,\n initializer(writer) {\n writer\n .write(`z.lazy(() => ${modelName(model.name)}.extend(`)\n .inlineBlock(() => {\n relationFields.forEach(field => {\n writeArray(writer, getJSDocs(field.documentation));\n\n writer\n .write(\n `${field.name}: ${getZodConstructor(\n field,\n relatedModelName\n )}`\n )\n .write(\",\")\n .newLine();\n });\n })\n .write(\"))\");\n }\n }\n ]\n });\n};\n\nexport const populateModelFile = async (\n model: DMMF.Model,\n sourceFile: SourceFile,\n config: Config,\n options: GeneratorOptions\n) => {\n await writeImportsForModel(model, sourceFile, config, options);\n writeTypeSpecificSchemas(model, sourceFile, config);\n generateSchemaForModel(model, sourceFile, config);\n if (needsRelatedModel(model, config))\n generateRelatedSchemaForModel(model, sourceFile, config);\n};\n\nexport const generateBarrelFile = (\n models: DMMF.Model[],\n indexFile: SourceFile\n) => {\n models.forEach(model =>\n indexFile.addExportDeclaration({\n moduleSpecifier: `./${lowerCaseFirst(model.name)}.schema`\n })\n );\n};\n"],"mappings":"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"}