kapix-typegraphql-prisma
Version:

510 lines (475 loc) • 21.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateEnhanceMap = void 0;
const ts_morph_1 = require("ts-morph");
const config_1 = require("./config");
function generateEnhanceMap(sourceFile, dmmfDocument, modelMappings, relationModels, models, inputs, outputs, options) {
var _a;
const hasRelations = relationModels.length > 0;
sourceFile.addImportDeclaration({
moduleSpecifier: "type-graphql",
namedImports: ["ClassType"],
});
sourceFile.addImportDeclaration({
moduleSpecifier: "tslib",
namespaceImport: "tslib",
});
if (dmmfDocument.shouldGenerateBlock("crudResolvers") ||
(hasRelations && dmmfDocument.shouldGenerateBlock("relationResolvers"))) {
sourceFile.addStatements(/* ts */ `
export type MethodDecoratorOverrideFn = (decorators: MethodDecorator[]) => MethodDecorator[];
`);
}
if (dmmfDocument.shouldGenerateBlock("crudResolvers")) {
sourceFile.addImportDeclaration({
moduleSpecifier: `./${config_1.resolversFolderName}/${config_1.crudResolversFolderName}/resolvers-crud.index`,
namespaceImport: "crudResolvers",
});
sourceFile.addImportDeclaration({
moduleSpecifier: `./helpers`,
namedImports: ["MutationInterceptor", "_resolversInterceptors"],
});
sourceFile.addImportDeclaration({
moduleSpecifier: `./${config_1.resolversFolderName}/${config_1.crudResolversFolderName}/args.index`,
namespaceImport: "argsTypes",
});
sourceFile.addVariableStatement({
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
declarations: [
{
name: "crudResolversMap",
initializer: ts_morph_1.Writers.object(Object.fromEntries(modelMappings.map(mapping => [
mapping.modelTypeName,
`crudResolvers.${mapping.resolverName}`,
]))),
},
],
trailingTrivia: "\r\n",
});
sourceFile.addImportDeclaration({
moduleSpecifier: `./${config_1.resolversFolderName}/${config_1.crudResolversFolderName}/resolvers-actions.index`,
namespaceImport: "actionResolvers",
});
sourceFile.addVariableStatement({
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
declarations: [
{
name: "actionResolversMap",
initializer: ts_morph_1.Writers.object(Object.fromEntries(modelMappings.map(mapping => [
mapping.modelTypeName,
ts_morph_1.Writers.object(Object.fromEntries(mapping.actions.map(action => [
action.name,
`actionResolvers.${action.actionResolverName}`,
]))),
]))),
},
],
});
sourceFile.addVariableStatement({
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
declarations: [
{
name: "crudResolversInfo",
initializer: ts_morph_1.Writers.object(Object.fromEntries(modelMappings.map(mapping => [
mapping.modelTypeName,
`[${mapping.actions
.map(action => `"${action.name}"`)
.join(", ")}]`,
]))),
},
],
trailingTrivia: "\r\n",
});
const actions = modelMappings
.flatMap(it => it.actions)
.filter(it => it.argsTypeName);
sourceFile.addVariableStatement({
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
declarations: [
{
name: "argsInfo",
initializer: ts_morph_1.Writers.object(Object.fromEntries(actions.map(action => [
action.argsTypeName,
`[${action.method.args
.map(arg => `"${arg.typeName}"`)
.join(", ")}]`,
]))),
},
],
trailingTrivia: "\r\n",
});
sourceFile.addStatements(/* ts */ `
type ResolverModelNames = keyof typeof crudResolversMap;
type ModelResolverActionNames<
TModel extends ResolverModelNames
> = keyof typeof crudResolversMap[TModel]["prototype"];
export type ResolverActionsConfig<
TModel extends ResolverModelNames
> = Partial<Record<ModelResolverActionNames<TModel>, MethodDecorator[] | MethodDecoratorOverrideFn>>
& {
_all?: MethodDecorator[];
_query?: MethodDecorator[];
_mutation?: MethodDecorator[];
};
export type ResolversEnhanceMap = {
[TModel in ResolverModelNames]?: ResolverActionsConfig<TModel>;
};
export function applyResolversEnhanceMap(
resolversEnhanceMap: ResolversEnhanceMap,
) {
const mutationOperationPrefixes = [
${((_a = options.mutationActions) !== null && _a !== void 0 ? _a : config_1.supportedMutationActions)
.map(it => `"${it}"`)
.join(", ")}
];
for (const resolversEnhanceMapKey of Object.keys(resolversEnhanceMap)) {
const modelName = resolversEnhanceMapKey as keyof typeof resolversEnhanceMap;
const crudTarget = crudResolversMap[modelName].prototype;
const resolverActionsConfig = resolversEnhanceMap[modelName]!;
const actionResolversConfig = actionResolversMap[modelName];
const allActionsDecorators = resolverActionsConfig._all;
const resolverActionNames = crudResolversInfo[modelName as keyof typeof crudResolversInfo];
for (const resolverActionName of resolverActionNames) {
const maybeDecoratorsOrFn = resolverActionsConfig[
resolverActionName as keyof typeof resolverActionsConfig
] as MethodDecorator[] | MethodDecoratorOverrideFn | undefined;
const isWriteOperation = mutationOperationPrefixes.some(prefix => resolverActionName.startsWith(prefix));
const operationKindDecorators = isWriteOperation ? resolverActionsConfig._mutation : resolverActionsConfig._query;
const mainDecorators = [
...allActionsDecorators ?? [],
...operationKindDecorators ?? [],
]
let decorators: MethodDecorator[];
if (typeof maybeDecoratorsOrFn === "function") {
decorators = maybeDecoratorsOrFn(mainDecorators);
} else {
decorators = [...mainDecorators, ...maybeDecoratorsOrFn ?? []];
}
const actionTarget = (actionResolversConfig[
resolverActionName as keyof typeof actionResolversConfig
] as Function).prototype;
tslib.__decorate(decorators, crudTarget, resolverActionName, null);
tslib.__decorate(decorators, actionTarget, resolverActionName, null);
}
}
}
export type ResolverInterceptor<TModel extends ResolverModelNames> = Partial<Record<ModelResolverActionNames<TModel>, MutationInterceptor>>
& {
_all?: MutationInterceptor
};
export type ResolversInterceptors = {
[TModel in ResolverModelNames]?: ResolverInterceptor<TModel>
};
export function applyResolversInterceptors(resolversInterceptors: ResolversInterceptors) {
Object.assign(_resolversInterceptors, resolversInterceptors)
}
`);
sourceFile.addStatements(/* ts */ `
type ArgsTypesNames = keyof typeof argsTypes;
type ArgFieldNames<TArgsType extends ArgsTypesNames> = Exclude<
keyof typeof argsTypes[TArgsType]["prototype"],
number | symbol
>;
type ArgFieldsConfig<
TArgsType extends ArgsTypesNames
> = FieldsConfig<ArgFieldNames<TArgsType>>;
export type ArgConfig<TArgsType extends ArgsTypesNames> = {
class?: ClassDecorator[];
fields?: ArgFieldsConfig<TArgsType>;
};
export type ArgsTypesEnhanceMap = {
[TArgsType in ArgsTypesNames]?: ArgConfig<TArgsType>;
};
export function applyArgsTypesEnhanceMap(
argsTypesEnhanceMap: ArgsTypesEnhanceMap,
) {
for (const argsTypesEnhanceMapKey of Object.keys(argsTypesEnhanceMap)) {
const argsTypeName = argsTypesEnhanceMapKey as keyof typeof argsTypesEnhanceMap;
const typeConfig = argsTypesEnhanceMap[argsTypeName]!;
const typeClass = argsTypes[argsTypeName];
const typeTarget = typeClass.prototype;
applyTypeClassEnhanceConfig(
typeConfig,
typeClass,
typeTarget,
argsInfo[argsTypeName as keyof typeof argsInfo],
);
}
}
`);
}
if (hasRelations && dmmfDocument.shouldGenerateBlock("relationResolvers")) {
sourceFile.addImportDeclaration({
moduleSpecifier: `./${config_1.resolversFolderName}/${config_1.relationsResolversFolderName}/resolvers.index`,
namespaceImport: "relationResolvers",
});
sourceFile.addVariableStatement({
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
declarations: [
{
name: "relationResolversMap",
initializer: ts_morph_1.Writers.object(Object.fromEntries(relationModels.map(relationModel => [
relationModel.model.typeName,
`relationResolvers.${relationModel.resolverName}`,
]))),
},
],
trailingTrivia: "\r\n",
});
sourceFile.addVariableStatement({
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
declarations: [
{
name: "relationResolversInfo",
initializer: ts_morph_1.Writers.object(Object.fromEntries(relationModels.map(relationModel => [
relationModel.model.typeName,
`[${relationModel.relationFields
.map(field => `"${field.name}"`)
.join(", ")}]`,
]))),
},
],
trailingTrivia: "\r\n",
});
sourceFile.addStatements(/* ts */ `
type RelationResolverModelNames = keyof typeof relationResolversMap;
type RelationResolverActionNames<
TModel extends RelationResolverModelNames
> = keyof typeof relationResolversMap[TModel]["prototype"];
export type RelationResolverActionsConfig<TModel extends RelationResolverModelNames>
= Partial<Record<RelationResolverActionNames<TModel>, MethodDecorator[] | MethodDecoratorOverrideFn>>
& { _all?: MethodDecorator[] };
export type RelationResolversEnhanceMap = {
[TModel in RelationResolverModelNames]?: RelationResolverActionsConfig<TModel>;
};
export function applyRelationResolversEnhanceMap(
relationResolversEnhanceMap: RelationResolversEnhanceMap,
) {
for (const relationResolversEnhanceMapKey of Object.keys(relationResolversEnhanceMap)) {
const modelName = relationResolversEnhanceMapKey as keyof typeof relationResolversEnhanceMap;
const relationResolverTarget = relationResolversMap[modelName].prototype;
const relationResolverActionsConfig = relationResolversEnhanceMap[modelName]!;
const allActionsDecorators = relationResolverActionsConfig._all ?? [];
const relationResolverActionNames = relationResolversInfo[modelName as keyof typeof relationResolversInfo];
for (const relationResolverActionName of relationResolverActionNames) {
const maybeDecoratorsOrFn = relationResolverActionsConfig[
relationResolverActionName as keyof typeof relationResolverActionsConfig
] as MethodDecorator[] | MethodDecoratorOverrideFn | undefined;
let decorators: MethodDecorator[];
if (typeof maybeDecoratorsOrFn === "function") {
decorators = maybeDecoratorsOrFn(allActionsDecorators);
} else {
decorators = [...allActionsDecorators, ...maybeDecoratorsOrFn ?? []];
}
tslib.__decorate(decorators, relationResolverTarget, relationResolverActionName, null);
}
}
}
`);
}
if (["outputs", "inputs", "models"].some(it => dmmfDocument.shouldGenerateBlock(it))) {
sourceFile.addStatements(/* ts */ `
type TypeConfig = {
class?: ClassDecorator[];
fields?: FieldsConfig;
};
export type PropertyDecoratorOverrideFn = (decorators: PropertyDecorator[]) => PropertyDecorator[];
type FieldsConfig<TTypeKeys extends string = string> = Partial<
Record<TTypeKeys, PropertyDecorator[] | PropertyDecoratorOverrideFn>
> & { _all?: PropertyDecorator[] };
function applyTypeClassEnhanceConfig<
TEnhanceConfig extends TypeConfig,
TType extends object
>(
enhanceConfig: TEnhanceConfig,
typeClass: ClassType<TType>,
typePrototype: TType,
typeFieldNames: string[]
) {
if (enhanceConfig.class) {
tslib.__decorate(enhanceConfig.class, typeClass);
}
if (enhanceConfig.fields) {
const allFieldsDecorators = enhanceConfig.fields._all ?? [];
for (const typeFieldName of typeFieldNames) {
const maybeDecoratorsOrFn = enhanceConfig.fields[
typeFieldName
] as PropertyDecorator[] | PropertyDecoratorOverrideFn | undefined;
let decorators: PropertyDecorator[];
if (typeof maybeDecoratorsOrFn === "function") {
decorators = maybeDecoratorsOrFn(allFieldsDecorators);
} else {
decorators = [...allFieldsDecorators, ...maybeDecoratorsOrFn ?? []];
}
tslib.__decorate(decorators, typePrototype, typeFieldName, void 0);
}
}
}
`);
}
if (dmmfDocument.shouldGenerateBlock("models")) {
sourceFile.addImportDeclaration({
moduleSpecifier: `./${config_1.modelsFolderName}`,
namespaceImport: "models",
});
sourceFile.addVariableStatement({
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
declarations: [
{
name: "modelsInfo",
initializer: ts_morph_1.Writers.object(Object.fromEntries(
// TODO: support _count
models.map(model => {
const fieldsToEmit = model.fields.filter(field => !field.relationName && !field.isOmitted.output);
return [
model.typeName,
`[${fieldsToEmit
.map(field => { var _a; return `"${(_a = field.typeFieldAlias) !== null && _a !== void 0 ? _a : field.name}"`; })
.join(", ")}]`,
];
}))),
},
],
trailingTrivia: "\r\n",
});
sourceFile.addStatements(/* ts */ `
type ModelNames = keyof typeof models;
type ModelFieldNames<TModel extends ModelNames> = Exclude<
keyof typeof models[TModel]["prototype"],
number | symbol
>;
type ModelFieldsConfig<TModel extends ModelNames> = FieldsConfig<
ModelFieldNames<TModel>
>;
export type ModelConfig<TModel extends ModelNames> = {
class?: ClassDecorator[];
fields?: ModelFieldsConfig<TModel>;
};
export type ModelsEnhanceMap = {
[TModel in ModelNames]?: ModelConfig<TModel>;
};
export function applyModelsEnhanceMap(modelsEnhanceMap: ModelsEnhanceMap) {
for (const modelsEnhanceMapKey of Object.keys(modelsEnhanceMap)) {
const modelName = modelsEnhanceMapKey as keyof typeof modelsEnhanceMap;
const modelConfig = modelsEnhanceMap[modelName]!;
const modelClass = models[modelName];
const modelTarget = modelClass.prototype;
applyTypeClassEnhanceConfig(
modelConfig,
modelClass,
modelTarget,
modelsInfo[modelName as keyof typeof modelsInfo],
);
}
}
`);
}
if (dmmfDocument.shouldGenerateBlock("outputs")) {
sourceFile.addImportDeclaration({
moduleSpecifier: `./${config_1.resolversFolderName}/${config_1.outputsFolderName}`,
namespaceImport: "outputTypes",
});
sourceFile.addVariableStatement({
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
declarations: [
{
name: "outputsInfo",
initializer: ts_morph_1.Writers.object(Object.fromEntries(outputs.map(output => [
output.typeName,
`[${output.fields.map(field => `"${field.name}"`).join(", ")}]`,
]))),
},
],
trailingTrivia: "\r\n",
});
sourceFile.addStatements(/* ts */ `
type OutputTypesNames = keyof typeof outputTypes;
type OutputTypeFieldNames<TOutput extends OutputTypesNames> = Exclude<
keyof typeof outputTypes[TOutput]["prototype"],
number | symbol
>;
type OutputTypeFieldsConfig<
TOutput extends OutputTypesNames
> = FieldsConfig<OutputTypeFieldNames<TOutput>>;
export type OutputTypeConfig<TOutput extends OutputTypesNames> = {
class?: ClassDecorator[];
fields?: OutputTypeFieldsConfig<TOutput>;
};
export type OutputTypesEnhanceMap = {
[TOutput in OutputTypesNames]?: OutputTypeConfig<TOutput>;
};
export function applyOutputTypesEnhanceMap(
outputTypesEnhanceMap: OutputTypesEnhanceMap,
) {
for (const outputTypeEnhanceMapKey of Object.keys(outputTypesEnhanceMap)) {
const outputTypeName = outputTypeEnhanceMapKey as keyof typeof outputTypesEnhanceMap;
const typeConfig = outputTypesEnhanceMap[outputTypeName]!;
const typeClass = outputTypes[outputTypeName];
const typeTarget = typeClass.prototype;
applyTypeClassEnhanceConfig(
typeConfig,
typeClass,
typeTarget,
outputsInfo[outputTypeName as keyof typeof outputsInfo],
);
}
}
`);
}
if (dmmfDocument.shouldGenerateBlock("inputs")) {
sourceFile.addImportDeclaration({
moduleSpecifier: `./${config_1.resolversFolderName}/${config_1.inputsFolderName}`,
namespaceImport: "inputTypes",
});
sourceFile.addVariableStatement({
declarationKind: ts_morph_1.VariableDeclarationKind.Const,
declarations: [
{
name: "inputsInfo",
initializer: ts_morph_1.Writers.object(Object.fromEntries(inputs.map(input => [
input.typeName,
`[${input.fields
.map(field => `"${field.typeName}"`)
.join(", ")}]`,
]))),
},
],
trailingTrivia: "\r\n",
});
sourceFile.addStatements(/* ts */ `
type InputTypesNames = keyof typeof inputTypes;
type InputTypeFieldNames<TInput extends InputTypesNames> = Exclude<
keyof typeof inputTypes[TInput]["prototype"],
number | symbol
>;
type InputTypeFieldsConfig<
TInput extends InputTypesNames
> = FieldsConfig<InputTypeFieldNames<TInput>>;
export type InputTypeConfig<TInput extends InputTypesNames> = {
class?: ClassDecorator[];
fields?: InputTypeFieldsConfig<TInput>;
};
export type InputTypesEnhanceMap = {
[TInput in InputTypesNames]?: InputTypeConfig<TInput>;
};
export function applyInputTypesEnhanceMap(
inputTypesEnhanceMap: InputTypesEnhanceMap,
) {
for (const inputTypeEnhanceMapKey of Object.keys(inputTypesEnhanceMap)) {
const inputTypeName = inputTypeEnhanceMapKey as keyof typeof inputTypesEnhanceMap;
const typeConfig = inputTypesEnhanceMap[inputTypeName]!;
const typeClass = inputTypes[inputTypeName];
const typeTarget = typeClass.prototype;
applyTypeClassEnhanceConfig(
typeConfig,
typeClass,
typeTarget,
inputsInfo[inputTypeName as keyof typeof inputsInfo],
);
}
}
`);
}
}
exports.generateEnhanceMap = generateEnhanceMap;
//# sourceMappingURL=generate-enhance.js.map