@vegardit/prisma-generator-nestjs-dto
Version:
Generates DTO and Entity classes from Prisma Schema for NestJS
168 lines (167 loc) • 8.17 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.zipImportStatementParams = exports.mergeImportStatements = exports.generateRelationInput = exports.getRelativePath = exports.getRelationConnectInputFields = exports.getRelationScalars = exports.mapDMMFToParsedField = exports.makeImportsFromPrismaClient = exports.concatIntoArray = exports.uniq = void 0;
const node_path_1 = __importDefault(require("node:path"));
const slash_1 = __importDefault(require("slash"));
const field_classifiers_1 = require("./field-classifiers");
const template_helpers_1 = require("./template-helpers");
const uniq = (input) => Array.from(new Set(input));
exports.uniq = uniq;
const concatIntoArray = (source, target) => source.forEach((item) => target.push(item));
exports.concatIntoArray = concatIntoArray;
const makeImportsFromPrismaClient = (fields) => {
const enumsToImport = (0, exports.uniq)(fields.filter(({ kind }) => kind === 'enum').map(({ type }) => type));
const importPrisma = fields
.filter(({ kind }) => kind === 'scalar')
.some(({ type }) => (0, template_helpers_1.scalarToTS)(type).includes('Prisma'));
if (!(enumsToImport.length || importPrisma)) {
return null;
}
return {
from: '@prisma/client',
destruct: importPrisma ? ['Prisma', ...enumsToImport] : enumsToImport,
};
};
exports.makeImportsFromPrismaClient = makeImportsFromPrismaClient;
const mapDMMFToParsedField = (field, overrides = {}) => ({
...field,
...overrides,
});
exports.mapDMMFToParsedField = mapDMMFToParsedField;
const getRelationScalars = (fields) => {
const scalars = fields.flatMap(({ relationFromFields = [] }) => relationFromFields);
return scalars.reduce((result, scalar) => ({
...result,
[scalar]: fields
.filter(({ relationFromFields = [] }) => relationFromFields.includes(scalar))
.map(({ name }) => name),
}), {});
};
exports.getRelationScalars = getRelationScalars;
const getRelationConnectInputFields = ({ field, allModels, }) => {
const { name, type, relationToFields = [] } = field;
if (!(0, field_classifiers_1.isRelation)(field)) {
throw new Error(`Can not resolve RelationConnectInputFields for field '${name}'. Not a relation field.`);
}
const relatedModel = allModels.find(({ name: modelName }) => modelName === type);
if (!relatedModel) {
throw new Error(`Can not resolve RelationConnectInputFields for field '${name}'. Related model '${type}' unknown.`);
}
if (!relationToFields.length) {
throw new Error(`Can not resolve RelationConnectInputFields for field '${name}'. Foreign keys are unknown.`);
}
const foreignKeyFields = relationToFields.map((relationToFieldName) => {
const relatedField = relatedModel.fields.find((relatedModelField) => relatedModelField.name === relationToFieldName);
if (!relatedField)
throw new Error(`Can not find foreign key field '${relationToFieldName}' on model '${relatedModel.name}'`);
return relatedField;
});
const idFields = relatedModel.fields.filter((relatedModelField) => (0, field_classifiers_1.isId)(relatedModelField));
const uniqueFields = relatedModel.fields.filter((relatedModelField) => (0, field_classifiers_1.isUnique)(relatedModelField));
const foreignFields = new Set([
...foreignKeyFields,
...idFields,
...uniqueFields,
]);
return foreignFields;
};
exports.getRelationConnectInputFields = getRelationConnectInputFields;
const getRelativePath = (from, to) => {
const result = (0, slash_1.default)(node_path_1.default.relative(from, to));
return result || '.';
};
exports.getRelativePath = getRelativePath;
const generateRelationInput = ({ field, model, allModels, templateHelpers: t, preAndSuffixClassName, canCreateAnnotation, canConnectAnnotation, }) => {
const relationInputClassProps = [];
const imports = [];
const apiExtraModels = [];
const generatedClasses = [];
if ((0, field_classifiers_1.isAnnotatedWith)(field, canCreateAnnotation)) {
const preAndPostfixedName = t.createDtoName(field.type);
apiExtraModels.push(preAndPostfixedName);
const modelToImportFrom = allModels.find(({ name }) => name === field.type);
if (!modelToImportFrom)
throw new Error(`related model '${field.type}' for '${model.name}.${field.name}' not found`);
imports.push({
from: (0, slash_1.default)(`${(0, exports.getRelativePath)(model.output.dto, modelToImportFrom.output.dto)}${node_path_1.default.sep}${t.createDtoFilename(field.type)}`),
destruct: [preAndPostfixedName],
});
relationInputClassProps.push({
name: 'create',
type: preAndPostfixedName,
});
}
if ((0, field_classifiers_1.isAnnotatedWith)(field, canConnectAnnotation)) {
const preAndPostfixedName = t.connectDtoName(field.type);
apiExtraModels.push(preAndPostfixedName);
const modelToImportFrom = allModels.find(({ name }) => name === field.type);
if (!modelToImportFrom)
throw new Error(`related model '${field.type}' for '${model.name}.${field.name}' not found`);
imports.push({
from: (0, slash_1.default)(`${(0, exports.getRelativePath)(model.output.dto, modelToImportFrom.output.dto)}${node_path_1.default.sep}${t.connectDtoFilename(field.type)}`),
destruct: [preAndPostfixedName],
});
relationInputClassProps.push({
name: 'connect',
type: preAndPostfixedName,
});
}
if (!relationInputClassProps.length) {
throw new Error(`Can not find relation input props for '${model.name}.${field.name}'`);
}
const originalInputClassName = `${t.transformClassNameCase(model.name)}${t.transformClassNameCase(field.name)}RelationInput`;
const preAndPostfixedInputClassName = preAndSuffixClassName(originalInputClassName);
generatedClasses.push(`class ${preAndPostfixedInputClassName} {
${t.fieldsToDtoProps(relationInputClassProps.map((inputField) => ({
...inputField,
kind: 'relation-input',
isRequired: relationInputClassProps.length === 1,
isList: field.isList,
})), true)}
}`);
apiExtraModels.push(preAndPostfixedInputClassName);
return {
type: preAndPostfixedInputClassName,
imports,
generatedClasses,
apiExtraModels,
};
};
exports.generateRelationInput = generateRelationInput;
const mergeImportStatements = (first, second) => {
if (first.from !== second.from) {
throw new Error(`Can not merge import statements; 'from' parameter is different`);
}
if (first.default && second.default) {
throw new Error(`Can not merge import statements; both statements have set the 'default' preoperty`);
}
const firstDestruct = first.destruct || [];
const secondDestruct = second.destruct || [];
const destructStrings = (0, exports.uniq)([...firstDestruct, ...secondDestruct].filter((destructItem) => typeof destructItem === 'string'));
const destructObject = [...firstDestruct, ...secondDestruct].reduce((result, destructItem) => {
if (typeof destructItem === 'string')
return result;
return { ...result, ...destructItem };
}, {});
return {
...first,
...second,
destruct: [...destructStrings, destructObject],
};
};
exports.mergeImportStatements = mergeImportStatements;
const zipImportStatementParams = (items) => {
const itemsByFrom = items.reduce((result, item) => {
const { from } = item;
const { [from]: existingItem } = result;
if (!existingItem) {
return { ...result, [from]: item };
}
return { ...result, [from]: (0, exports.mergeImportStatements)(existingItem, item) };
}, {});
return Object.values(itemsByFrom);
};
exports.zipImportStatementParams = zipImportStatementParams;