UNPKG

@weverson_na/prisma-generator-nestjs-dto

Version:

Advanced Prisma Generator with Smart Merge v2: Creates DTO and Entity classes with AST-based preservation, intelligent import management, and modular architecture for NestJS

158 lines (157 loc) 7.53 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Helpers = void 0; const node_path_1 = __importDefault(require("node:path")); const field_classifiers_1 = require("../field-classifiers"); const template_helpers_1 = require("./template-helpers"); class Helpers { constructor(decoratorStrategy) { this.decoratorStrategy = decoratorStrategy; } static uniq(input) { return Array.from(new Set(input)); } static concatIntoArray(source, target) { source.forEach((item) => target.push(item)); } static makeImportsFromPrismaClient(fields) { const enumsToImport = Helpers.uniq(fields.filter(({ kind }) => kind === 'enum').map(({ type }) => type)); const importPrisma = fields .filter(({ kind }) => kind === 'scalar') .some(({ type }) => template_helpers_1.TemplateHelpers.scalarToTS(type).includes('Prisma')); if (!enumsToImport.length && !importPrisma) return null; return { from: '@prisma/client', destruct: importPrisma ? ['Prisma', ...enumsToImport] : enumsToImport, }; } static mapDMMFToParsedField(field, overrides = {}) { return { ...field, ...overrides }; } static getRelationScalars(fields) { const scalars = fields.flatMap(({ relationFromFields = [] }) => relationFromFields); return scalars.reduce((result, scalar) => { const related = fields .filter(({ relationFromFields = [] }) => relationFromFields.includes(scalar)) .map(({ name }) => name); return { ...result, [scalar]: related }; }, {}); } static getRelationConnectInputFields({ field, allModels, }) { if (!(0, field_classifiers_1.isRelation)(field)) { throw new Error(`Can not resolve RelationConnectInputFields for field '${field.name}'. Not a relation field.`); } const relatedModel = allModels.find((m) => m.name === field.type); if (!relatedModel) { throw new Error(`Can not resolve RelationConnectInputFields for field '${field.name}'. Related model '${field.type}' unknown.`); } const { relationToFields = [] } = field; if (!relationToFields.length) { throw new Error(`Can not resolve RelationConnectInputFields for field '${field.name}'. Foreign keys are unknown.`); } const foreignKeyFields = relationToFields.map((relName) => { const rf = relatedModel.fields.find((f) => f.name === relName); if (!rf) throw new Error(`Can not find foreign key field '${relName}' on model '${relatedModel.name}'`); return rf; }); const idFields = relatedModel.fields.filter(field_classifiers_1.isId); const uniqueFields = relatedModel.fields.filter(field_classifiers_1.isUnique); return new Set([...foreignKeyFields, ...idFields, ...uniqueFields]); } static getRelativePath(from, to) { const relative = node_path_1.default.relative(from, to); const result = relative.split(node_path_1.default.sep).join('/'); return result || '.'; } generateRelationInput(params) { const { field, model, allModels, templateHelpers: t, preAndSuffixClassName, canCreateAnnotation, canConnectAnnotation, addExposePropertyDecorator, } = params; const relationInputClassProps = []; const imports = []; const apiExtraModels = []; const generatedClasses = []; if ((0, field_classifiers_1.isAnnotatedWith)(field, canCreateAnnotation)) { const cls = t.createDtoName(field.type); apiExtraModels.push(cls); const mdl = allModels.find((m) => m.name === field.type); if (!mdl) throw new Error(`related model '${field.type}' for '${model.name}.${field.name}' not found`); const rel = Helpers.getRelativePath(model.output.dto, mdl.output.dto); imports.push({ from: `${rel}/${t.createDtoFilename(field.type)}`, destruct: [cls], }); relationInputClassProps.push({ name: 'create', type: cls, documentation: field.documentation, }); } if ((0, field_classifiers_1.isAnnotatedWith)(field, canConnectAnnotation)) { const cls = t.connectDtoName(field.type); apiExtraModels.push(cls); const mdl = allModels.find((m) => m.name === field.type); if (!mdl) throw new Error(`related model '${field.type}' for '${model.name}.${field.name}' not found`); const rel = Helpers.getRelativePath(model.output.dto, mdl.output.dto); imports.push({ from: `${rel}/${t.connectDtoFilename(field.type)}`, destruct: [cls], }); relationInputClassProps.push({ name: 'connect', type: cls, documentation: field.documentation, }); } if (!relationInputClassProps.length) { throw new Error(`Can not find relation input props for '${model.name}.${field.name}'`); } const baseName = `${t.transformClassNameCase(model.name)}${t.transformClassNameCase(field.name)}RelationInput`; const inputClassName = preAndSuffixClassName(baseName); generatedClasses.push(`class ${inputClassName} {\n ${t.fieldsToDtoProps(relationInputClassProps.map((f) => ({ ...f, kind: 'relation-input', isRequired: relationInputClassProps.length === 1, isList: field.isList, })), true, field === null || field === void 0 ? void 0 : field.isRequired, addExposePropertyDecorator)}\n}`); apiExtraModels.push(inputClassName); return { type: inputClassName, imports, generatedClasses, apiExtraModels }; } static mergeImportStatements(first, second) { if (first.from !== second.from) { throw new Error(`Cannot merge import statements; 'from' differs`); } if (first.default && second.default) { throw new Error(`Cannot merge import statements; both have default`); } const firstDestruct = first.destruct || []; const secondDestruct = second.destruct || []; const destructStrings = Helpers.uniq([...firstDestruct, ...secondDestruct].filter((x) => typeof x === 'string')); const destructObject = [...firstDestruct, ...secondDestruct].reduce((result, destructItem) => { if (typeof destructItem === 'string') return result; return { ...result, ...destructItem }; }, {}); return { ...first, ...second, destruct: [...destructStrings, destructObject].filter((value) => !(typeof value === 'object' && Object.keys(value).length === 0)), }; } static zipImportStatementParams(items) { const map = items.reduce((acc, item) => { const existing = acc[item.from]; acc[item.from] = existing ? Helpers.mergeImportStatements(existing, item) : item; return acc; }, {}); return Object.values(map); } } exports.Helpers = Helpers;