UNPKG

@grapi/server

Version:

Grapi Schema Generator For GraphQL Server

241 lines (240 loc) 11.2 kB
"use strict"; 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;