typegraphql-prisma-nestjs
Version:
This project is a fork of another with minor changes, created for personal use.
229 lines • 16.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = generateCode;
const tslib_1 = require("tslib");
const ts_morph_1 = require("ts-morph");
const path_1 = tslib_1.__importDefault(require("path"));
const node_child_process_1 = require("node:child_process");
const node_util_1 = require("node:util");
const execa = (0, node_util_1.promisify)(node_child_process_1.exec);
const helpers_1 = require("./helpers");
const enum_1 = tslib_1.__importDefault(require("./enum"));
const model_type_class_1 = tslib_1.__importDefault(require("./model-type-class"));
const relations_1 = tslib_1.__importDefault(require("./resolvers/relations"));
const type_class_1 = require("./type-class");
const full_crud_1 = tslib_1.__importDefault(require("./resolvers/full-crud"));
const config_1 = require("./config");
const imports_1 = require("./imports");
const dmmf_document_1 = require("./dmmf/dmmf-document");
const args_class_1 = tslib_1.__importDefault(require("./args-class"));
const separate_action_1 = tslib_1.__importDefault(require("./resolvers/separate-action"));
const prisma_version_1 = require("../utils/prisma-version");
const generate_enhance_1 = require("./generate-enhance");
const generate_scalars_1 = require("./generate-scalars");
const generate_helpers_1 = require("./generate-helpers");
const emit_block_1 = require("./emit-block");
const baseCompilerOptions = {
target: ts_morph_1.ScriptTarget.ES2021,
module: ts_morph_1.ModuleKind.CommonJS,
emitDecoratorMetadata: true,
experimentalDecorators: true,
esModuleInterop: true,
skipLibCheck: true,
};
async function generateCode(dmmf, baseOptions, log = helpers_1.noop) {
(0, prisma_version_1.ensureInstalledCorrectPrismaPackage)();
const options = {
...baseOptions,
blocksToEmit: (0, emit_block_1.getBlocksToEmit)(baseOptions.emitOnly),
contextPrismaKey: baseOptions.contextPrismaKey ?? "prisma",
relativePrismaOutputPath: (0, helpers_1.toUnixPath)(path_1.default.relative(baseOptions.outputDirPath, baseOptions.prismaClientPath)),
absolutePrismaOutputPath: !baseOptions.customPrismaImportPath &&
baseOptions.prismaClientPath.includes("node_modules")
? "@prisma/client"
: undefined,
formatGeneratedCode: baseOptions.formatGeneratedCode ?? "tsc", // default for backward compatibility
};
const baseDirPath = options.outputDirPath;
const emitTranspiledCode = options.emitTranspiledCode ??
options.outputDirPath.includes("node_modules");
const project = new ts_morph_1.Project({
compilerOptions: {
...baseCompilerOptions,
...(emitTranspiledCode && {
declaration: true,
importHelpers: true,
}),
},
});
log("Transforming dmmfDocument...");
const dmmfDocument = new dmmf_document_1.DmmfDocument(dmmf, options);
if (dmmfDocument.shouldGenerateBlock("enums")) {
log("Generating enums...");
const datamodelEnumNames = dmmfDocument.datamodel.enums.map(enumDef => enumDef.typeName);
dmmfDocument.datamodel.enums.forEach(enumDef => (0, enum_1.default)(project, baseDirPath, enumDef, options));
dmmfDocument.schema.enums
// skip enums from datamodel
.filter(enumDef => !datamodelEnumNames.includes(enumDef.typeName))
.forEach(enumDef => (0, enum_1.default)(project, baseDirPath, enumDef, options));
const emittedEnumNames = [
...new Set([
...dmmfDocument.schema.enums.map(it => it.typeName),
...dmmfDocument.datamodel.enums.map(it => it.typeName),
]),
];
const enumsBarrelExportSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.enumsFolderName, "index.ts"), undefined, { overwrite: true });
(0, imports_1.generateEnumsBarrelFile)(enumsBarrelExportSourceFile, emittedEnumNames);
}
if (dmmfDocument.shouldGenerateBlock("models")) {
log("Generating models...");
dmmfDocument.datamodel.models.forEach(model => {
const modelOutputType = dmmfDocument.schema.outputTypes.find(type => type.name === model.name);
return (0, model_type_class_1.default)(project, baseDirPath, model, modelOutputType, dmmfDocument);
});
const modelsBarrelExportSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.modelsFolderName, "index.ts"), undefined, { overwrite: true });
(0, imports_1.generateModelsBarrelFile)(modelsBarrelExportSourceFile, dmmfDocument.datamodel.models.map(it => it.typeName));
}
const resolversDirPath = path_1.default.resolve(baseDirPath, config_1.resolversFolderName);
let outputTypesToGenerate = [];
if (dmmfDocument.shouldGenerateBlock("outputs")) {
log("Generating output types...");
const rootTypes = dmmfDocument.schema.outputTypes.filter(type => ["Query", "Mutation"].includes(type.name));
const modelNames = dmmfDocument.datamodel.models.map(model => model.name);
outputTypesToGenerate = dmmfDocument.schema.outputTypes.filter(
// skip generating models and root resolvers
type => !modelNames.includes(type.name) && !rootTypes.includes(type));
const outputTypesFieldsArgsToGenerate = outputTypesToGenerate
.map(it => it.fields)
.reduce((a, b) => a.concat(b), [])
.filter(it => it.argsTypeName);
outputTypesToGenerate.forEach(type => (0, type_class_1.generateOutputTypeClassFromType)(project, resolversDirPath, type, dmmfDocument));
const outputsBarrelExportSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.outputsFolderName, "index.ts"), undefined, { overwrite: true });
(0, imports_1.generateOutputsBarrelFile)(outputsBarrelExportSourceFile, outputTypesToGenerate.map(it => it.typeName), outputTypesFieldsArgsToGenerate.length > 0);
if (outputTypesFieldsArgsToGenerate.length > 0) {
log("Generating output types args...");
outputTypesFieldsArgsToGenerate.forEach(async (field) => {
(0, args_class_1.default)(project, path_1.default.resolve(resolversDirPath, config_1.outputsFolderName), field.args, field.argsTypeName, dmmfDocument, 2);
});
const outputsArgsBarrelExportSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.outputsFolderName, config_1.argsFolderName, "index.ts"), undefined, { overwrite: true });
(0, imports_1.generateArgsBarrelFile)(outputsArgsBarrelExportSourceFile, outputTypesFieldsArgsToGenerate.map(it => it.argsTypeName));
}
}
if (dmmfDocument.shouldGenerateBlock("inputs")) {
log("Generating input types...");
dmmfDocument.schema.inputTypes.forEach(type => (0, type_class_1.generateInputTypeClassFromType)(project, resolversDirPath, type, options));
const inputsBarrelExportSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.inputsFolderName, "index.ts"), undefined, { overwrite: true });
(0, imports_1.generateInputsBarrelFile)(inputsBarrelExportSourceFile, dmmfDocument.schema.inputTypes.map(it => it.typeName));
}
if (dmmfDocument.relationModels.length > 0 &&
dmmfDocument.shouldGenerateBlock("relationResolvers")) {
log("Generating relation resolvers...");
dmmfDocument.relationModels.forEach(relationModel => (0, relations_1.default)(project, baseDirPath, dmmfDocument, relationModel, options));
const relationResolversBarrelExportSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.relationsResolversFolderName, "resolvers.index.ts"), undefined, { overwrite: true });
(0, imports_1.generateResolversBarrelFile)(relationResolversBarrelExportSourceFile, dmmfDocument.relationModels.map(relationModel => ({
resolverName: relationModel.resolverName,
modelName: relationModel.model.typeName,
})));
log("Generating relation resolver args...");
dmmfDocument.relationModels.forEach(async (relationModelData) => {
const resolverDirPath = path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.relationsResolversFolderName, relationModelData.model.typeName);
relationModelData.relationFields
.filter(field => field.argsTypeName)
.forEach(async (field) => {
(0, args_class_1.default)(project, resolverDirPath, field.outputTypeField.args, field.argsTypeName, dmmfDocument);
});
const argTypeNames = relationModelData.relationFields
.filter(it => it.argsTypeName !== undefined)
.map(it => it.argsTypeName);
if (argTypeNames.length) {
const barrelExportSourceFile = project.createSourceFile(path_1.default.resolve(resolverDirPath, config_1.argsFolderName, "index.ts"), undefined, { overwrite: true });
(0, imports_1.generateArgsBarrelFile)(barrelExportSourceFile, argTypeNames);
}
});
const relationModelsWithArgs = dmmfDocument.relationModels.filter(relationModelData => relationModelData.relationFields.some(it => it.argsTypeName !== undefined));
if (relationModelsWithArgs.length > 0) {
const relationResolversArgsIndexSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.relationsResolversFolderName, "args.index.ts"), undefined, { overwrite: true });
(0, imports_1.generateArgsIndexFile)(relationResolversArgsIndexSourceFile, relationModelsWithArgs.map(relationModelData => relationModelData.model.typeName));
}
const relationResolversIndexSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.relationsResolversFolderName, "index.ts"), undefined, { overwrite: true });
(0, imports_1.generateResolversIndexFile)(relationResolversIndexSourceFile, "relations", relationModelsWithArgs.length > 0);
}
if (dmmfDocument.shouldGenerateBlock("crudResolvers")) {
log("Generating crud resolvers...");
dmmfDocument.modelMappings.forEach(async (mapping) => {
const model = dmmfDocument.datamodel.models.find(model => model.name === mapping.modelName);
(0, full_crud_1.default)(project, baseDirPath, mapping, model, dmmfDocument, options);
mapping.actions
.filter(a => !options.emitActions?.includes(a.prismaMethod))
.forEach(async (action) => {
const model = dmmfDocument.datamodel.models.find(model => model.name === mapping.modelName);
(0, separate_action_1.default)(project, baseDirPath, model, action, mapping, dmmfDocument, options);
});
});
const generateMappingData = dmmfDocument.modelMappings.map(mapping => {
const model = dmmfDocument.datamodel.models.find(model => model.name === mapping.modelName);
return {
modelName: model.typeName,
resolverName: mapping.resolverName,
actionResolverNames: mapping.actions
.filter(a => !options.emitActions?.includes(a.prismaMethod))
.map(it => it.actionResolverName),
};
});
const crudResolversBarrelExportSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.crudResolversFolderName, "resolvers-crud.index.ts"), undefined, { overwrite: true });
(0, imports_1.generateResolversBarrelFile)(crudResolversBarrelExportSourceFile, generateMappingData);
const crudResolversActionsBarrelExportSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.crudResolversFolderName, "resolvers-actions.index.ts"), undefined, { overwrite: true });
(0, imports_1.generateResolversActionsBarrelFile)(crudResolversActionsBarrelExportSourceFile, generateMappingData);
const crudResolversIndexSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.crudResolversFolderName, "index.ts"), undefined, { overwrite: true });
(0, imports_1.generateResolversIndexFile)(crudResolversIndexSourceFile, "crud", true);
log("Generating crud resolvers args...");
dmmfDocument.modelMappings.forEach(async (mapping) => {
const actionsWithArgs = mapping.actions
.filter(a => !options.emitActions?.includes(a.prismaMethod))
.filter(it => it.argsTypeName !== undefined);
if (actionsWithArgs.length) {
const model = dmmfDocument.datamodel.models.find(model => model.name === mapping.modelName);
const resolverDirPath = path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.crudResolversFolderName, model.typeName);
actionsWithArgs.forEach(async (action) => {
(0, args_class_1.default)(project, resolverDirPath, action.method.args, action.argsTypeName, dmmfDocument);
});
const barrelExportSourceFile = project.createSourceFile(path_1.default.resolve(resolverDirPath, config_1.argsFolderName, "index.ts"), undefined, { overwrite: true });
(0, imports_1.generateArgsBarrelFile)(barrelExportSourceFile, actionsWithArgs.map(it => it.argsTypeName));
}
});
const crudResolversArgsIndexSourceFile = project.createSourceFile(path_1.default.resolve(baseDirPath, config_1.resolversFolderName, config_1.crudResolversFolderName, "args.index.ts"), undefined, { overwrite: true });
(0, imports_1.generateArgsIndexFile)(crudResolversArgsIndexSourceFile, dmmfDocument.modelMappings
.filter(mapping => mapping.actions
.filter(a => !options.emitActions?.includes(a.prismaMethod))
.some(it => it.argsTypeName !== undefined))
.map(mapping => mapping.modelTypeName));
}
log("Generate enhance map");
const enhanceSourceFile = project.createSourceFile(baseDirPath + "/enhance.ts", undefined, { overwrite: true });
(0, generate_enhance_1.generateEnhanceMap)(enhanceSourceFile, dmmfDocument, dmmfDocument.modelMappings, dmmfDocument.relationModels, dmmfDocument.datamodel.models, dmmfDocument.schema.inputTypes, outputTypesToGenerate, dmmfDocument.options);
log("Generate custom scalars");
const scalarsSourceFile = project.createSourceFile(baseDirPath + "/scalars.ts", undefined, { overwrite: true });
(0, generate_scalars_1.generateCustomScalars)(scalarsSourceFile, dmmfDocument.options);
log("Generate custom helpers");
const helpersSourceFile = project.createSourceFile(baseDirPath + "/helpers.ts", undefined, { overwrite: true });
(0, generate_helpers_1.generateHelpersFile)(helpersSourceFile, dmmfDocument.options);
log("Generating index file");
const indexSourceFile = project.createSourceFile(baseDirPath + "/index.ts", undefined, { overwrite: true });
(0, imports_1.generateIndexFile)(indexSourceFile, dmmfDocument.relationModels.length > 0, dmmfDocument.options.blocksToEmit);
log("Emitting generated code files");
if (emitTranspiledCode) {
await project.emit();
}
else {
if (options.formatGeneratedCode === "tsc") {
for (const file of project.getSourceFiles()) {
file.formatText({ indentSize: 2 });
}
}
await project.save();
if (options.formatGeneratedCode === "prettier") {
await execa(`npx prettier --write --ignore-path .prettierignore ${baseDirPath}`);
}
}
}
//# sourceMappingURL=generate-code.js.map