@grapi/server
Version:
Grapi Schema Generator For GraphQL Server
241 lines (240 loc) • 11.2 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const dataModel_1 = require("../dataModel");
const objectField_1 = __importDefault(require("../dataModel/objectField"));
const type_1 = require("../dataModel/type");
const lodash_1 = require("../lodash");
const baseType_1 = __importDefault(require("./baseType"));
const create_1 = __importDefault(require("./create"));
const whereInput_1 = __importDefault(require("./whereInput"));
const createObjectInputField = (prefix, field, context) => {
const { root } = context;
const content = [];
(0, lodash_1.forEach)(field.getFields(), (nestedField, name) => {
if (nestedField.isScalar()) {
content.push(`${name}: ${nestedField.getTypename()}`);
return;
}
if (nestedField instanceof objectField_1.default) {
const fieldWithPrefix = `${prefix}${(0, lodash_1.upperFirst)(name)}`;
const typeFields = createObjectInputField(fieldWithPrefix, nestedField, context);
const objectInputName = `${fieldWithPrefix}UpdateInput`;
root.addInput(`input ${objectInputName} {
${typeFields.join(' ')}
}`);
content.push(`${name}: ${objectInputName}`);
return;
}
});
return content;
};
const createInputField = (model, context, getCreateInputName, getWhereInputName, getWhereUniqueInputName, getMutationFactoryFromModel, withoutField = undefined, recursive = true) => {
const { root } = context;
const fields = model.getFields();
const content = [];
const mutationFactory = getMutationFactoryFromModel(model);
const relationUpdateInputs = (relationNamings, relationName, relationTo, fieldName, isList, exceptionField = undefined) => {
(0, lodash_1.forEach)(relationTo.getFields(), (modelField, keyField) => {
if ((modelField instanceof dataModel_1.RelationField && modelField.getRelationName() === relationName)) {
exceptionField = keyField;
return false;
}
});
const relationField = (0, lodash_1.capitalize)(exceptionField);
const relationInput = `${relationNamings}UpdateWithout${relationField}Input`;
const inputField = createInputField(relationTo, context, getCreateInputName, getWhereInputName, getWhereUniqueInputName, relationTo.getCreateMutationFactory, exceptionField, false);
const relationCreateInput = `${relationNamings}Update${isList ? `Many` : `One`}Without${relationField}Input`;
const whereUnique = `${getWhereUniqueInputName(relationTo)}`;
root.addInput(`input ${relationInput} {
${inputField}
}`);
if (isList) {
root.addInput(`input ${relationCreateInput} {
create: [${relationInput}]
connect: [${whereUnique}]
disconnect: [${whereUnique}]
delete: [${whereUnique}]
}`);
}
else {
root.addInput(`input ${relationCreateInput} {
create: ${relationInput}
connect: ${whereUnique}
disconnect: Boolean
delete: Boolean
}`);
}
content.push(`${fieldName}: ${relationCreateInput}`);
};
(0, lodash_1.forEach)(fields, (field, name) => {
if (field.isAutoGenerated()) {
return;
}
if (withoutField && withoutField === name) {
return;
}
if (field.isScalar()) {
let fieldType;
if (field.isList()) {
const listOperationInput = `${field.getTypename()}ListFieldUpdateInput`;
root.addInput(`input ${listOperationInput} {
set: [${field.getTypename()}]
add: [${field.getTypename()}]
remove: [${field.getTypename()}]
}`);
fieldType = listOperationInput;
mutationFactory.markArrayField(name);
}
else {
fieldType = field.getTypename();
}
content.push(`${name}: ${fieldType}`);
return;
}
if (field instanceof objectField_1.default) {
const fieldWithPrefix = `${model.getNamings().capitalSingular}${(0, lodash_1.upperFirst)(name)}`;
const typeFields = createObjectInputField(fieldWithPrefix, field, context);
const objectInputName = `${fieldWithPrefix}UpdateInput`;
root.addInput(`input ${objectInputName} {
${typeFields.join(' ')}
}`);
let fieldType;
if (field.isList()) {
const listOperationInput = `${fieldWithPrefix}UpdateListInput`;
root.addInput(`input ${listOperationInput} {
set: [${objectInputName}]
}`);
fieldType = listOperationInput;
mutationFactory.markArrayField(name);
}
else {
fieldType = objectInputName;
}
content.push(`${name}: ${fieldType}`);
return;
}
const isRelation = field instanceof dataModel_1.RelationField;
const isList = field.isList();
if (isRelation && !isList) {
const relationTo = field.getRelationTo();
const relationType = field.getRelationType();
const relationName = field.getRelationName();
const relationNamings = relationTo.getNamings().capitalSingular;
if (recursive && relationType === dataModel_1.RelationType.biOneToOne) {
relationUpdateInputs(relationNamings, relationName, relationTo, name, false);
}
else {
const relationInputName = `${relationTo.getTypename()}UpdateOneInput`;
root.addInput(`input ${relationInputName} {
create: ${getCreateInputName(relationTo)}
connect: ${getWhereUniqueInputName(relationTo)}
disconnect: Boolean
delete: Boolean
}`);
content.push(`${name}: ${relationInputName}`);
}
return;
}
if (isRelation && isList) {
const relationTo = field.getRelationTo();
const relationType = field.getRelationType();
const relationName = field.getRelationName();
const relationNamings = relationTo.getNamings().capitalSingular;
if (recursive && relationType === dataModel_1.RelationType.biOneToMany || relationType === dataModel_1.RelationType.biManyToMany) {
relationUpdateInputs(relationNamings, relationName, relationTo, name, true);
}
else {
const whereUnique = getWhereUniqueInputName(relationTo);
const relationInputName = `${relationTo.getTypename()}UpdateManyInput`;
root.addInput(`input ${relationInputName} {
create: [${getCreateInputName(relationTo)}]
connect: [${whereUnique}]
disconnect: [${whereUnique}]
delete: [${whereUnique}]
}`);
content.push(`${name}: ${relationInputName}`);
}
return;
}
});
return content;
};
class UpdatePlugin {
whereInputPlugin;
baseTypePlugin;
createPlugin;
hook;
constructor({ hook, }) {
this.hook = hook;
}
setPlugins(plugins) {
this.whereInputPlugin = plugins.find(plugin => plugin instanceof whereInput_1.default);
this.baseTypePlugin = plugins.find(plugin => plugin instanceof baseType_1.default);
this.createPlugin = plugins.find(plugin => plugin instanceof create_1.default);
}
visitModel(model, context) {
const { root } = context;
const returnType = this.baseTypePlugin.getTypename(model);
const directives = model.getDirectives(dataModel_1.DirectiveModelAction.Update);
const mutationName = UpdatePlugin.getInputName(model);
const inputName = this.generateUpdateInput(model, context);
const whereUniqueInput = this.whereInputPlugin.getWhereUniqueInputName(model);
root.addMutation(`${mutationName}( where: ${whereUniqueInput}!, data: ${inputName}! ): ${returnType}!${directives}`);
}
resolveInMutation({ model, dataSource }) {
const mutationName = UpdatePlugin.getInputName(model);
const wrapUpdate = (0, lodash_1.get)(this.hook, [model.getName(), 'wrapUpdate']);
return {
[mutationName]: async (root, args, context) => {
const updatedObject = await model.getDataSource().findOne({ where: this.whereInputPlugin.parseUniqueWhere(args.where) });
if (!updatedObject) {
throw new Error(`No Node for the model ${(0, lodash_1.capitalize)(model.getName())} with unique field.`);
}
const whereUnique = { id: { eq: updatedObject.id } };
const data = this.setUpdatedAtDirective(model, args.data);
if (!wrapUpdate) {
return await dataSource.update(whereUnique, this.createMutation(model, data), context);
}
const updateContext = {
where: args.where,
data,
response: {},
graphqlContext: context,
};
await wrapUpdate(updateContext, async (ctx) => {
updateContext.response = await dataSource.update(whereUnique, this.createMutation(model, ctx.data), context);
});
return updateContext.response;
},
};
}
generateUpdateInput(model, context) {
const inputName = `${model.getNamings().capitalSingular}UpdateInput`;
const inputField = createInputField(model, context, this.createPlugin.getCreateInputName, this.whereInputPlugin.getWhereInputName, this.whereInputPlugin.getWhereUniqueInputName, model.getUpdateMutationFactory);
const input = `input ${inputName} {
${inputField}
}`;
context.root.addInput(input);
return inputName;
}
static getInputName(model) {
return `update${model.getNamings().capitalSingular}`;
}
createMutation = (model, payload) => {
const mutationFactory = model.getUpdateMutationFactory();
return mutationFactory.createMutation(payload);
};
setUpdatedAtDirective = (model, data) => {
const fields = model.getFields();
(0, lodash_1.forEach)(fields, (field, name) => {
if (field.isUpdatedAt() && field.getTypename() === type_1.DataModelType.DATE_TIME) {
data[name] = new Date();
}
});
return data;
};
}
exports.default = UpdatePlugin;