"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SchemaComposer = exports.BUILT_IN_DIRECTIVES = void 0; var _deprecate = _interopRequireDefault(require("./utils/deprecate")); var _TypeStorage = require("./TypeStorage"); var _TypeMapper = require("./TypeMapper"); var _ObjectTypeComposer = require("./ObjectTypeComposer"); var _InputTypeComposer = require("./InputTypeComposer"); var _ScalarTypeComposer = require("./ScalarTypeComposer"); var _EnumTypeComposer = require("./EnumTypeComposer"); var _InterfaceTypeComposer = require("./InterfaceTypeComposer"); var _UnionTypeComposer = require("./UnionTypeComposer"); var _Resolver = require("./Resolver"); var _is = require("./utils/is"); var _misc = require("./utils/misc"); var _typeHelpers = require("./utils/typeHelpers"); var _graphql = require("./graphql"); var _default = _interopRequireDefault(require("./directive/default")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, 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; } const BUILT_IN_DIRECTIVES = [_graphql.GraphQLSkipDirective, _graphql.GraphQLIncludeDirective, _graphql.GraphQLDeprecatedDirective, _default.default]; exports.BUILT_IN_DIRECTIVES = BUILT_IN_DIRECTIVES; class SchemaComposer extends _TypeStorage.TypeStorage { constructor(schema) { super(); _defineProperty(this, "_schemaMustHaveTypes", []); _defineProperty(this, "_directives", BUILT_IN_DIRECTIVES); this.typeMapper = new _TypeMapper.TypeMapper(this); if (schema instanceof _graphql.GraphQLSchema) { this.merge(schema); } // alive proper Flow type casting in autosuggestions for class with Generics /* :: return this; */ } get Query() { return this.getOrCreateOTC('Query'); } /* @deprecated 7.0.0 */ rootQuery() { (0, _deprecate.default)('Use schemaComposer.Query property instead'); return this.getOrCreateOTC('Query'); } get Mutation() { return this.getOrCreateOTC('Mutation'); } /* @deprecated 7.0.0 */ rootMutation() { (0, _deprecate.default)('Use schemaComposer.Mutation property instead'); return this.getOrCreateOTC('Mutation'); } get Subscription() { return this.getOrCreateOTC('Subscription'); } /* @deprecated 7.0.0 */ rootSubscription() { (0, _deprecate.default)('Use schemaComposer.Subscription property instead'); return this.getOrCreateOTC('Subscription'); } buildSchema(extraConfig) { const roots = {}; if (this.has('Query')) { const tc = this.getOTC('Query'); this.removeEmptyTypes(tc, new Set()); roots.query = tc.getType(); } if (this.has('Mutation')) { const tc = this.getOTC('Mutation'); this.removeEmptyTypes(tc, new Set()); roots.mutation = tc.getType(); } if (this.has('Subscription')) { const tc = this.getOTC('Subscription'); this.removeEmptyTypes(tc, new Set()); roots.subscription = tc.getType(); } if (!roots.query) { throw new Error('Can not build schema. Must be initialized Query type. See https://github.com/graphql/graphql-js/issues/448'); } if (Object.keys(roots).length === 0) { throw new Error('Can not build schema. Must be initialized at least one ' + 'of the following types: Query, Mutation, Subscription.'); } const types = [...this._schemaMustHaveTypes.map(t => (0, _typeHelpers.getGraphQLType)(t)), // additional types, eg. used in Interfaces ...(extraConfig && Array.isArray(extraConfig.types) ? [...extraConfig.types] : [])]; const directives = [...this._directives, ...(extraConfig && Array.isArray(extraConfig.directives) ? [...extraConfig.directives] : [])]; return new _graphql.GraphQLSchema(_objectSpread({}, roots, extraConfig, { types, directives })); } addSchemaMustHaveType(type) { this._schemaMustHaveTypes.push(type); return this; } removeEmptyTypes(tc, passedTypes = new Set()) { tc.getFieldNames().forEach(fieldName => { const fieldType = tc.getFieldType(fieldName); if (fieldType instanceof _graphql.GraphQLObjectType) { const typeName = fieldType.name; if (!passedTypes.has(typeName)) { passedTypes.add(typeName); const fieldTC = new _ObjectTypeComposer.ObjectTypeComposer(fieldType, this); if (Object.keys(fieldTC.getFields()).length > 0) { this.removeEmptyTypes(fieldTC, passedTypes); } else { // eslint-disable-next-line console.log(`graphql-compose: Delete field '${tc.getTypeName()}.${fieldName}' ` + `with type '${fieldTC.getTypeName()}', cause it does not have fields.`); tc.removeField(fieldName); } } } }); } merge(schema) { let query; let mutation; let subscription; let typeMap; let directives; if (schema instanceof SchemaComposer) { query = schema.Query; mutation = schema.Mutation; subscription = schema.Subscription; typeMap = schema.types; directives = schema.getDirectives(); } else if (schema instanceof _graphql.GraphQLSchema) { query = schema.getQueryType(); mutation = schema.getMutationType(); subscription = schema.getSubscriptionType(); typeMap = new Map(); (0, _misc.forEachKey)(schema.getTypeMap(), (v, k) => { typeMap.set(k, v); }); directives = schema.getDirectives(); } else { throw new Error('SchemaComposer.merge() accepts only GraphQLSchema or SchemaComposer instances.'); } // Root types may have any name, so import them manually. if (query) this.Query.merge(query); if (mutation) this.Mutation.merge(mutation); if (subscription) this.Subscription.merge(subscription); // Merging non-root types typeMap.forEach((type, key) => { // skip internal and root types if (typeof key === 'string' && key.startsWith('__') || type === query || type === mutation || type === subscription) return; // merge regular types if (this.has(key)) { this.getAnyTC(key).merge(type); } else { this.set(key, type); } }); directives.forEach(directive => { this.addDirective(directive); }); return this; } /** * ----------------------------------------------- * Like graphql-tools methods * ----------------------------------------------- */ addTypeDefs(typeDefs) { const types = this.typeMapper.parseTypesFromString(typeDefs); types.forEach(type => { const name = type.getTypeName(); if (name !== 'Query' && name !== 'Mutation' && name !== 'Subscription') { this.add(type); } }); if (types.has('Query')) { const tc = types.get('Query'); if (!(tc instanceof _ObjectTypeComposer.ObjectTypeComposer)) { throw new Error(`Type Query in typedefs isn't an Object Type.`); } this.Query.addFields(tc.getFields()); } if (types.has('Mutation')) { const tc = types.get('Mutation'); if (!(tc instanceof _ObjectTypeComposer.ObjectTypeComposer)) { throw new Error(`Type Mutation in typedefs isn't an Object Type.`); } this.Mutation.addFields(tc.getFields()); } if (types.has('Subscription')) { const tc = types.get('Subscription'); if (!(tc instanceof _ObjectTypeComposer.ObjectTypeComposer)) { throw new Error(`Type Subscription in typedefs isn't an Object Type.`); } this.Subscription.addFields(tc.getFields()); } return types; } addResolveMethods(typesFieldsResolve) { const typeNames = Object.keys(typesFieldsResolve); typeNames.forEach(typeName => { let type = this.get(typeName); if (type instanceof _ScalarTypeComposer.ScalarTypeComposer) { type = type.getType(); } if (type instanceof _graphql.GraphQLScalarType) { const maybeScalar = typesFieldsResolve[typeName]; if (maybeScalar instanceof _graphql.GraphQLScalarType) { this.set(typeName, maybeScalar); return; } if (typeof maybeScalar.name === 'string' && typeof maybeScalar.serialize === 'function') { this.set(typeName, new _graphql.GraphQLScalarType(maybeScalar)); return; } } const tc = this.getOTC(typeName); const fieldsResolve = typesFieldsResolve[typeName]; const fieldNames = Object.keys(fieldsResolve); fieldNames.forEach(fieldName => { tc.extendField(fieldName, { resolve: fieldsResolve[fieldName] }); }); }); } /** * ----------------------------------------------- * Type methods * ----------------------------------------------- */ createObjectTC(typeDef) { return _ObjectTypeComposer.ObjectTypeComposer.create(typeDef, this); } createInputTC(typeDef) { return _InputTypeComposer.InputTypeComposer.create(typeDef, this); } createEnumTC(typeDef) { return _EnumTypeComposer.EnumTypeComposer.create(typeDef, this); } createInterfaceTC(typeDef) { return _InterfaceTypeComposer.InterfaceTypeComposer.create(typeDef, this); } createUnionTC(typeDef) { return _UnionTypeComposer.UnionTypeComposer.create(typeDef, this); } createScalarTC(typeDef) { return _ScalarTypeComposer.ScalarTypeComposer.create(typeDef, this); } createResolver(opts) { return new _Resolver.Resolver(opts, this); } createTC(typeOrSDL) { if (this.has(typeOrSDL)) { return this.get(typeOrSDL); } const tc = this.createTempTC(typeOrSDL); this.set(tc.getTypeName(), tc); this.set(typeOrSDL, tc); return tc; } createTempTC(typeOrSDL) { let type; if (typeof typeOrSDL === 'string') { type = this.typeMapper.createType(typeOrSDL); } else { type = typeOrSDL; } if (type instanceof _ObjectTypeComposer.ObjectTypeComposer || type instanceof _InputTypeComposer.InputTypeComposer || type instanceof _ScalarTypeComposer.ScalarTypeComposer || type instanceof _EnumTypeComposer.EnumTypeComposer || type instanceof _InterfaceTypeComposer.InterfaceTypeComposer || type instanceof _UnionTypeComposer.UnionTypeComposer) { return type; } else if (type instanceof _graphql.GraphQLObjectType) { return _ObjectTypeComposer.ObjectTypeComposer.createTemp(type, this); } else if (type instanceof _graphql.GraphQLInputObjectType) { return _InputTypeComposer.InputTypeComposer.createTemp(type, this); } else if (type instanceof _graphql.GraphQLScalarType) { return _ScalarTypeComposer.ScalarTypeComposer.createTemp(type, this); } else if (type instanceof _graphql.GraphQLEnumType) { return _EnumTypeComposer.EnumTypeComposer.createTemp(type, this); } else if (type instanceof _graphql.GraphQLInterfaceType) { return _InterfaceTypeComposer.InterfaceTypeComposer.createTemp(type, this); } else if (type instanceof _graphql.GraphQLUnionType) { return _UnionTypeComposer.UnionTypeComposer.createTemp(type, this); } throw new Error(`Cannot create as TypeComposer the following value: ${(0, _misc.inspect)(type)}.`); } /* @deprecated 7.0.0 */ getOrCreateTC(typeName, onCreate) { (0, _deprecate.default)(`Use SchemaComposer.getOrCreateOTC() method instead`); return this.getOrCreateOTC(typeName, onCreate); } getOrCreateOTC(typeName, onCreate) { try { return this.getOTC(typeName); } catch (e) { const tc = _ObjectTypeComposer.ObjectTypeComposer.create(typeName, this); this.set(typeName, tc); if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(tc); return tc; } } getOrCreateITC(typeName, onCreate) { try { return this.getITC(typeName); } catch (e) { const itc = _InputTypeComposer.InputTypeComposer.create(typeName, this); this.set(typeName, itc); if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(itc); return itc; } } getOrCreateETC(typeName, onCreate) { try { return this.getETC(typeName); } catch (e) { const etc = _EnumTypeComposer.EnumTypeComposer.create(typeName, this); this.set(typeName, etc); if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(etc); return etc; } } getOrCreateIFTC(typeName, onCreate) { try { return this.getIFTC(typeName); } catch (e) { const iftc = _InterfaceTypeComposer.InterfaceTypeComposer.create(typeName, this); this.set(typeName, iftc); if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(iftc); return iftc; } } getOrCreateUTC(typeName, onCreate) { try { return this.getUTC(typeName); } catch (e) { const utc = _UnionTypeComposer.UnionTypeComposer.create(typeName, this); this.set(typeName, utc); if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(utc); return utc; } } getOrCreateSTC(typeName, onCreate) { try { return this.getSTC(typeName); } catch (e) { const stc = _ScalarTypeComposer.ScalarTypeComposer.create(typeName, this); this.set(typeName, stc); if (onCreate && (0, _is.isFunction)(onCreate)) onCreate(stc); return stc; } } /* @deprecated 7.0.0 */ getTC(typeName) { (0, _deprecate.default)(`Use SchemaComposer.getOTC() method instead`); return this.getOTC(typeName); } getOTC(typeName) { if (this.hasInstance(typeName, _graphql.GraphQLObjectType)) { return _ObjectTypeComposer.ObjectTypeComposer.create(this.get(typeName), this); } if (this.hasInstance(typeName, _ObjectTypeComposer.ObjectTypeComposer)) { return this.get(typeName); } throw new Error(`Cannot find ObjectTypeComposer with name ${typeName}`); } getITC(typeName) { if (this.hasInstance(typeName, _graphql.GraphQLInputObjectType)) { return _InputTypeComposer.InputTypeComposer.create(this.get(typeName), this); } if (this.hasInstance(typeName, _InputTypeComposer.InputTypeComposer)) { return this.get(typeName); } throw new Error(`Cannot find InputTypeComposer with name ${typeName}`); } getETC(typeName) { if (this.hasInstance(typeName, _graphql.GraphQLEnumType)) { return _EnumTypeComposer.EnumTypeComposer.create(this.get(typeName), this); } if (this.hasInstance(typeName, _EnumTypeComposer.EnumTypeComposer)) { return this.get(typeName); } throw new Error(`Cannot find EnumTypeComposer with name ${typeName}`); } getIFTC(typeName) { if (this.hasInstance(typeName, _graphql.GraphQLInterfaceType)) { return _InterfaceTypeComposer.InterfaceTypeComposer.create(this.get(typeName), this); } if (this.hasInstance(typeName, _InterfaceTypeComposer.InterfaceTypeComposer)) { return this.get(typeName); } throw new Error(`Cannot find InterfaceTypeComposer with name ${typeName}`); } getUTC(typeName) { if (this.hasInstance(typeName, _graphql.GraphQLUnionType)) { return _UnionTypeComposer.UnionTypeComposer.create(this.get(typeName), this); } if (this.hasInstance(typeName, _UnionTypeComposer.UnionTypeComposer)) { return this.get(typeName); } throw new Error(`Cannot find UnionTypeComposer with name ${typeName}`); } getSTC(typeName) { if (this.hasInstance(typeName, _graphql.GraphQLScalarType)) { return _ScalarTypeComposer.ScalarTypeComposer.create(this.get(typeName), this); } if (this.hasInstance(typeName, _ScalarTypeComposer.ScalarTypeComposer)) { return this.get(typeName); } throw new Error(`Cannot find ScalarTypeComposer with name ${typeName}`); } getAnyTC(typeOrName) { let type; if (typeof typeOrName === 'string') { type = this.get(typeOrName); } else { type = typeOrName; } if (type == null) { throw new Error(`Cannot find type with name ${typeOrName}`); } else if (type instanceof _ObjectTypeComposer.ObjectTypeComposer || type instanceof _InputTypeComposer.InputTypeComposer || type instanceof _ScalarTypeComposer.ScalarTypeComposer || type instanceof _EnumTypeComposer.EnumTypeComposer || type instanceof _InterfaceTypeComposer.InterfaceTypeComposer || type instanceof _UnionTypeComposer.UnionTypeComposer) { return type; } while (type instanceof _graphql.GraphQLList || type instanceof _graphql.GraphQLNonNull) { type = type.ofType; } if (type instanceof _graphql.GraphQLObjectType) { return _ObjectTypeComposer.ObjectTypeComposer.create(type, this); } else if (type instanceof _graphql.GraphQLInputObjectType) { return _InputTypeComposer.InputTypeComposer.create(type, this); } else if (type instanceof _graphql.GraphQLScalarType) { return _ScalarTypeComposer.ScalarTypeComposer.create(type, this); } else if (type instanceof _graphql.GraphQLEnumType) { return _EnumTypeComposer.EnumTypeComposer.create(type, this); } else if (type instanceof _graphql.GraphQLInterfaceType) { return _InterfaceTypeComposer.InterfaceTypeComposer.create(type, this); } else if (type instanceof _graphql.GraphQLUnionType) { return _UnionTypeComposer.UnionTypeComposer.create(type, this); } throw new Error(`Type with name ${(0, _misc.inspect)(typeOrName)} cannot be obtained as any Composer helper. Put something strange?`); } addAsComposer(typeOrSDL) { const composer = this.createTempTC(typeOrSDL); this.set(composer.getTypeName(), composer); return composer.getTypeName(); } /** * ----------------------------------------------- * Storage methods * ----------------------------------------------- */ clear() { super.clear(); this._schemaMustHaveTypes = []; this._directives = BUILT_IN_DIRECTIVES; this.typeMapper.initScalars(); } add(typeOrSDL) { if (typeof typeOrSDL === 'string') { return this.addAsComposer(typeOrSDL); } else { return super.add(typeOrSDL); } } /** * ----------------------------------------------- * Directive methods * ----------------------------------------------- */ addDirective(directive) { if (!(directive instanceof _graphql.GraphQLDirective)) { throw new Error(`You should provide GraphQLDirective to schemaComposer.addDirective(), but recieved ${(0, _misc.inspect)(directive)}`); } if (!this.hasDirective(directive)) { this._directives.push(directive); } return this; } removeDirective(directive) { this._directives = this._directives.filter(o => o !== directive); return this; } getDirectives() { return this._directives; } /** * This method used in TypeMapper and for fast parsing */ _getDirective(name) { const directives = this.getDirectives(); return directives.find(d => d.name === name); } getDirective(name) { const directive = this._getDirective(name); if (!directive) { throw new Error(`Directive instance with name ${name} does not exists.`); } return directive; } hasDirective(directive) { if (!directive) return false; if (typeof directive === 'string') { const name = directive.startsWith('@') ? directive.slice(1) : directive; return !!this._directives.find(o => o.name === name); } else if (directive instanceof _graphql.GraphQLDirective) { return !!this._directives.find(o => o === directive); } return false; } /** * ----------------------------------------------- * Misc methods * ----------------------------------------------- */ // disable redundant noise in console.logs toString() { return 'SchemaComposer'; } toJSON() { return 'SchemaComposer'; } inspect() { return 'SchemaComposer'; } } exports.SchemaComposer = SchemaComposer;