UNPKG

graphql-compose-mongoose

Version:

Plugin for `graphql-compose` which derive a graphql types from a mongoose model.

327 lines (242 loc) 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DiscriminatorTypeComposer = void 0; var _graphqlCompose = require("graphql-compose"); var _composeWithMongoose = require("../composeWithMongoose"); var _composeChildTC = require("./composeChildTC"); var _mergeCustomizationOptions = require("./utils/mergeCustomizationOptions"); var _prepareBaseResolvers = require("./prepareBaseResolvers"); var _reorderFields = require("./utils/reorderFields"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } // sets the values on DKey enum TC function setDKeyETCValues(discriminators) { const values = {}; for (const DName in discriminators) { if (discriminators.hasOwnProperty(DName)) { values[DName] = { value: DName }; } } return values; } // creates an enum from discriminator names // then sets this enum type as the discriminator key field type function createAndSetDKeyETC(dTC, discriminators) { const DKeyETC = dTC.schemaComposer.createEnumTC({ name: `EnumDKey${dTC.getTypeName()}${dTC.getDKey()[0].toUpperCase() + dTC.getDKey().substr(1)}`, values: setDKeyETCValues(discriminators) }); // set on Output dTC.extendField(dTC.getDKey(), { type: () => DKeyETC }); // set on Input dTC.getInputTypeComposer().extendField(dTC.getDKey(), { type: () => DKeyETC }); return DKeyETC; } class DiscriminatorTypeComposer extends _graphqlCompose.ObjectTypeComposer { /* :: constructor(gqType: any, schemaComposer: SchemaComposer<TContext>): DiscriminatorTypeComposer<TSource, TContext> { super(gqType, schemaComposer); return this; } */ static createFromModel(baseModel, schemaComposer, opts) { if (!baseModel || !baseModel.discriminators) { throw Error('Discriminator Key not Set, Use composeWithMongoose for Normal Collections'); } if (!(schemaComposer instanceof _graphqlCompose.SchemaComposer)) { throw Error('DiscriminatorTC.createFromModel() should recieve SchemaComposer in second argument'); } // eslint-disable-next-line opts = _objectSpread({ reorderFields: true, schemaComposer }, opts); const baseTC = (0, _composeWithMongoose.composeWithMongoose)(baseModel, opts); const baseDTC = new DiscriminatorTypeComposer(baseTC.getType(), schemaComposer); // copy data from baseTC to baseDTC baseTC.clone(baseDTC); baseDTC._gqcInputTypeComposer = baseTC._gqcInputTypeComposer; baseDTC.opts = opts; baseDTC.childTCs = []; baseDTC.discriminatorKey = baseModel.schema.get('discriminatorKey') || '__t'; baseDTC.DInterface = baseDTC._createDInterface(baseDTC); baseDTC.setInterfaces([baseDTC.DInterface]); // discriminators an object containing all discriminators with key being DNames baseDTC.DKeyETC = createAndSetDKeyETC(baseDTC, baseModel.discriminators); (0, _reorderFields.reorderFields)(baseDTC, baseDTC.opts.reorderFields, baseDTC.discriminatorKey); baseDTC.schemaComposer.addSchemaMustHaveType(baseDTC); // prepare Base Resolvers (0, _prepareBaseResolvers.prepareBaseResolvers)(baseDTC); return baseDTC; } _createDInterface(baseTC) { const baseFields = baseTC.getFieldNames(); const interfaceFields = {}; for (const field of baseFields) { interfaceFields[field] = baseTC.getFieldConfig(field); } return this.schemaComposer.createInterfaceTC({ name: `${baseTC.getTypeName()}Interface`, resolveType: value => { const childDName = value[baseTC.getDKey()]; if (childDName) { return baseTC.schemaComposer.getOTC(childDName).getType(); } // as fallback return BaseModelTC return baseTC.schemaComposer.getOTC(baseTC.getTypeName()).getType(); }, fields: interfaceFields }); } getDKey() { return this.discriminatorKey; } getDKeyETC() { return this.DKeyETC; } getDInterface() { return this.DInterface; } hasChildTC(DName) { return !!this.childTCs.find(ch => ch.getTypeName() === DName); } /* eslint no-use-before-define: 0 */ discriminator(childModel, opts) { const customizationOpts = (0, _mergeCustomizationOptions.mergeCustomizationOptions)(this.opts, opts); let childTC = (0, _composeWithMongoose.composeWithMongoose)(childModel, customizationOpts); childTC = (0, _composeChildTC.composeChildTC)(this, childTC, this.opts); this.schemaComposer.addSchemaMustHaveType(childTC); this.childTCs.push(childTC); return childTC; } setFields(fields) { const oldFieldNames = super.getFieldNames(); super.setFields(fields); this.getDInterface().setFields(fields); for (const childTC of this.childTCs) { childTC.removeField(oldFieldNames); childTC.addFields(fields); (0, _reorderFields.reorderFields)(childTC, this.opts.reorderFields, this.getDKey(), super.getFieldNames()); } return this; } setField(fieldName, fieldConfig) { super.setField(fieldName, fieldConfig); this.getDInterface().setField(fieldName, fieldConfig); for (const childTC of this.childTCs) { childTC.setField(fieldName, fieldConfig); } return this; } // discriminators must have all interface fields addFields(newFields) { super.addFields(newFields); this.getDInterface().addFields(newFields); for (const childTC of this.childTCs) { childTC.addFields(newFields); } return this; } addNestedFields(newFields) { super.addNestedFields(newFields); this.getDInterface().setFields(this.getFields()); for (const childTC of this.childTCs) { childTC.addNestedFields(newFields); } return this; } removeField(fieldNameOrArray) { super.removeField(fieldNameOrArray); this.getDInterface().removeField(fieldNameOrArray); for (const childTC of this.childTCs) { childTC.removeField(fieldNameOrArray); } return this; } removeOtherFields(fieldNameOrArray) { const oldFieldNames = super.getFieldNames(); super.removeOtherFields(fieldNameOrArray); this.getDInterface().removeOtherFields(fieldNameOrArray); for (const childTC of this.childTCs) { const specificFields = childTC.getFieldNames().filter(childFieldName => !oldFieldNames.find(oldBaseFieldName => oldBaseFieldName === childFieldName)); childTC.removeOtherFields(super.getFieldNames().concat(specificFields)); (0, _reorderFields.reorderFields)(childTC, this.opts.reorderFields, this.getDKey(), super.getFieldNames()); } return this; } reorderFields(names) { super.reorderFields(names); this.getDInterface().reorderFields(names); for (const childTC of this.childTCs) { childTC.reorderFields(names); } return this; } extendField(fieldName, partialFieldConfig) { super.extendField(fieldName, partialFieldConfig); this.getDInterface().extendField(fieldName, partialFieldConfig); for (const childTC of this.childTCs) { childTC.extendField(fieldName, partialFieldConfig); } return this; } makeFieldNonNull(fieldNameOrArray) { super.makeFieldNonNull(fieldNameOrArray); this.getDInterface().makeFieldNonNull(fieldNameOrArray); for (const childTC of this.childTCs) { childTC.makeFieldNonNull(fieldNameOrArray); } return this; } makeFieldNullable(fieldNameOrArray) { super.makeFieldNullable(fieldNameOrArray); this.getDInterface().makeFieldNullable(fieldNameOrArray); for (const childTC of this.childTCs) { childTC.makeFieldNullable(fieldNameOrArray); } return this; } makeFieldPlural(fieldNameOrArray) { super.makeFieldPlural(fieldNameOrArray); this.getDInterface().makeFieldPlural(fieldNameOrArray); for (const childTC of this.childTCs) { childTC.makeFieldPlural(fieldNameOrArray); } return this; } makeFieldNonPlural(fieldNameOrArray) { super.makeFieldNonPlural(fieldNameOrArray); this.getDInterface().makeFieldNonPlural(fieldNameOrArray); for (const childTC of this.childTCs) { childTC.makeFieldNonPlural(fieldNameOrArray); } return this; } deprecateFields(fields) { super.deprecateFields(fields); this.getDInterface().deprecateFields(fields); for (const childTC of this.childTCs) { childTC.deprecateFields(fields); } return this; } // relations with args are a bit hard to manage as interfaces i believe as of now do not // support field args. Well if one wants to have use args, you setType for resolver as this // this = this DiscriminantTypeComposer // NOTE, those relations will be propagated to the childTypeComposers and you can use normally. addRelation(fieldName, relationOpts) { super.addRelation(fieldName, relationOpts); this.getDInterface().setField(fieldName, this.getField(fieldName)); for (const childTC of this.childTCs) { childTC.addRelation(fieldName, relationOpts); } return this; } setRecordIdFn(fn) { super.setRecordIdFn(fn); for (const childTC of this.childTCs) { childTC.setRecordIdFn(fn); } return this; } } exports.DiscriminatorTypeComposer = DiscriminatorTypeComposer;