@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
155 lines (154 loc) • 7.29 kB
JavaScript
;
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 {
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 || '.';
}
static 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, 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],
};
}
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;