UNPKG

@dans98/prismabox

Version:

Typebox generator for prisma schema

264 lines (229 loc) 8.82 kB
import type { DMMF } from "@prisma/generator-helper"; import { extractAnnotations } from "../annotations/annotations"; import { generateTypeboxOptions } from "../annotations/options"; import { getConfig } from "../config"; import type { ProcessedModel } from "../model"; import { processedEnums } from "./enum"; import { type PrimitivePrismaFieldType, isPrimitivePrismaFieldType, stringifyPrimitiveType, } from "./primitiveField"; import { wrapWithArray } from "./wrappers/array"; import { makeIntersection } from "./wrappers/intersect"; import { wrapWithPartial } from "./wrappers/partial"; import { makeUnion } from "./wrappers/union"; const selfReferenceName = "Self"; export const processedWhere: ProcessedModel[] = []; export function processWhere(models: DMMF.Model[] | Readonly<DMMF.Model[]>) { for (const m of models) { const o = stringifyWhere(m); if (o) { processedWhere.push({ name: m.name, stringRepresentation: o }); } } Object.freeze(processedWhere); } export function stringifyWhere(data: DMMF.Model) { const annotations = extractAnnotations(data.documentation); if (annotations.isHidden) return undefined; const fields = data.fields .map((field) => { const annotations = extractAnnotations(field.documentation); if (annotations.isHidden) return undefined; let stringifiedType = ""; if (isPrimitivePrismaFieldType(field.type)) { stringifiedType = stringifyPrimitiveType({ fieldType: field.type as PrimitivePrismaFieldType, options: generateTypeboxOptions({ exludeAdditionalProperties: true, input: annotations, }), }); } else if (processedEnums.find((e) => e.name === field.type)) { // biome-ignore lint/style/noNonNullAssertion: we checked this manually stringifiedType = processedEnums.find( (e) => e.name === field.type, )!.stringRepresentation; } else { return undefined; } if (field.isList) { stringifiedType = wrapWithArray(stringifiedType); } return `${field.name}: ${stringifiedType}`; }) .filter((x) => x) as string[]; if (getConfig().allowRecursion) { return wrapWithPartial( `${ getConfig().typeboxImportVariableName }.Recursive(${selfReferenceName} =>${ getConfig().typeboxImportVariableName }.Object({${AND_OR_NOT()},${fields.join(",")}},${generateTypeboxOptions({ exludeAdditionalProperties: true, input: annotations, })}), { $id: "${data.name}"})`, ); } return wrapWithPartial( `${getConfig().typeboxImportVariableName}.Object({${fields.join( ",", )}},${generateTypeboxOptions({ exludeAdditionalProperties: true, input: annotations })})`, ); } export const processedWhereUnique: ProcessedModel[] = []; export function processWhereUnique( models: DMMF.Model[] | Readonly<DMMF.Model[]>, ) { for (const m of models) { const o = stringifyWhereUnique(m); if (o) { processedWhereUnique.push({ name: m.name, stringRepresentation: o }); } } Object.freeze(processedWhereUnique); } export function stringifyWhereUnique(data: DMMF.Model) { const annotations = extractAnnotations(data.documentation); if (annotations.isHidden) return undefined; const uniqueCompositeFields = data.uniqueFields.map((fields) => { const compositeName = fields.join("_"); const fieldObjects = fields.map( // biome-ignore lint/style/noNonNullAssertion: this must exist (f) => data.fields.find((field) => field.name === f)!, ); const stringifiedFieldObjects = fieldObjects.map((f) => { const annotations = extractAnnotations(f.documentation); if (annotations.isHidden) return undefined; let stringifiedType = ""; if (isPrimitivePrismaFieldType(f.type)) { stringifiedType = stringifyPrimitiveType({ fieldType: f.type as PrimitivePrismaFieldType, options: generateTypeboxOptions({ exludeAdditionalProperties: true, input: annotations, }), }); } else if (processedEnums.find((e) => e.name === f.type)) { // biome-ignore lint/style/noNonNullAssertion: we checked this manually stringifiedType = processedEnums.find( (e) => e.name === f.type, )!.stringRepresentation; } else { throw new Error("Invalid type for unique composite generation"); } return `${f.name}: ${stringifiedType}`; }); const compositeObject = `${ getConfig().typeboxImportVariableName }.Object({${stringifiedFieldObjects.join( ",", )}}, ${generateTypeboxOptions({ exludeAdditionalProperties: true })})`; return `${compositeName}: ${compositeObject}`; }); const allFields = data.fields .map((field) => { const annotations = extractAnnotations(field.documentation); if (annotations.isHidden) return undefined; let stringifiedType = ""; if (isPrimitivePrismaFieldType(field.type)) { stringifiedType = stringifyPrimitiveType({ fieldType: field.type as PrimitivePrismaFieldType, options: generateTypeboxOptions({ exludeAdditionalProperties: true, input: annotations, }), }); } else if (processedEnums.find((e) => e.name === field.type)) { // biome-ignore lint/style/noNonNullAssertion: we checked this manually stringifiedType = processedEnums.find( (e) => e.name === field.type, )!.stringRepresentation; } else { return undefined; } if (field.isList) { stringifiedType = wrapWithArray(stringifiedType); } return `${field.name}: ${stringifiedType}`; }) .filter((x) => x) as string[]; const uniqueFields = data.fields .map((field) => { const annotations = extractAnnotations(field.documentation); if (annotations.isHidden) return undefined; if (!field.isUnique && !field.isId) return undefined; let stringifiedType = ""; if (isPrimitivePrismaFieldType(field.type)) { stringifiedType = stringifyPrimitiveType({ fieldType: field.type as PrimitivePrismaFieldType, options: generateTypeboxOptions({ exludeAdditionalProperties: true, input: annotations, }), }); } else if (processedEnums.find((e) => e.name === field.type)) { // biome-ignore lint/style/noNonNullAssertion: we checked this manually stringifiedType = processedEnums.find( (e) => e.name === field.type, )!.stringRepresentation; } else { return undefined; } if (field.isList) { stringifiedType = wrapWithArray(stringifiedType); } return `${field.name}: ${stringifiedType}`; }) .filter((x) => x) as string[]; const uniqueBaseObject = `${getConfig().typeboxImportVariableName}.Object({${[ ...uniqueFields, ...uniqueCompositeFields, ].join( ",", )}},${generateTypeboxOptions({ exludeAdditionalProperties: true, input: annotations })})`; if (getConfig().allowRecursion) { return `${ getConfig().typeboxImportVariableName }.Recursive(${selfReferenceName} => ${makeIntersection([ wrapWithPartial(uniqueBaseObject, true), makeUnion( [...uniqueFields, ...uniqueCompositeFields].map( (f) => `${getConfig().typeboxImportVariableName}.Object({${f}})`, ), ), wrapWithPartial( `${getConfig().typeboxImportVariableName}.Object({${AND_OR_NOT()}})`, true, ), wrapWithPartial( `${ getConfig().typeboxImportVariableName }.Object({${allFields.join(",")}}, ${generateTypeboxOptions()})`, ), ])}, { $id: "${data.name}"})`; } return makeIntersection([ wrapWithPartial(uniqueBaseObject, true), makeUnion( [...uniqueFields, ...uniqueCompositeFields].map( (f) => `${getConfig().typeboxImportVariableName}.Object({${f}})`, ), ), wrapWithPartial( `${getConfig().typeboxImportVariableName}.Object({${allFields.join( ",", )}})`, ), ]); } function AND_OR_NOT() { return `AND: ${ getConfig().typeboxImportVariableName }.Union([${selfReferenceName}, ${wrapWithArray(selfReferenceName)}]), NOT: ${ getConfig().typeboxImportVariableName }.Union([${selfReferenceName}, ${wrapWithArray(selfReferenceName)}]), OR: ${wrapWithArray(selfReferenceName)}`; }