'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.GraphQLSchema = undefined; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; exports.isSchema = isSchema; var _definition = require('./definition'); var _directives = require('./directives'); var _introspection = require('./introspection'); var _find = require('../jsutils/find'); var _find2 = _interopRequireDefault(_find); var _instanceOf = require('../jsutils/instanceOf'); var _instanceOf2 = _interopRequireDefault(_instanceOf); var _invariant = require('../jsutils/invariant'); var _invariant2 = _interopRequireDefault(_invariant); var _objectValues = require('../jsutils/objectValues'); var _objectValues2 = _interopRequireDefault(_objectValues); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /** * Copyright (c) 2015-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * strict */ // eslint-disable-next-line no-redeclare /** * Test if the given value is a GraphQL schema. */ function isSchema(schema) { return (0, _instanceOf2.default)(schema, GraphQLSchema); } /** * Schema Definition * * A Schema is created by supplying the root types of each type of operation, * query and mutation (optional). A schema definition is then supplied to the * validator and executor. * * Example: * * const MyAppSchema = new GraphQLSchema({ * query: MyAppQueryRootType, * mutation: MyAppMutationRootType, * }) * * Note: If an array of `directives` are provided to GraphQLSchema, that will be * the exact list of directives represented and allowed. If `directives` is not * provided then a default set of the specified directives (e.g. @include and * @skip) will be used. If you wish to provide *additional* directives to these * specified directives, you must explicitly declare them. Example: * * const MyAppSchema = new GraphQLSchema({ * ... * directives: specifiedDirectives.concat([ myCustomDirective ]), * }) * */ var GraphQLSchema = exports.GraphQLSchema = function () { // Used as a cache for validateSchema(). function GraphQLSchema(config) { var _this = this; _classCallCheck(this, GraphQLSchema); // If this schema was built from a source known to be valid, then it may be // marked with assumeValid to avoid an additional type system validation. if (config && config.assumeValid) { this.__validationErrors = []; } else { // Otherwise check for common mistakes during construction to produce // clear and early error messages. !((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') ? (0, _invariant2.default)(0, 'Must provide configuration object.') : void 0; !(!config.types || Array.isArray(config.types)) ? (0, _invariant2.default)(0, '"types" must be Array if provided but got: ' + String(config.types) + '.') : void 0; !(!config.directives || Array.isArray(config.directives)) ? (0, _invariant2.default)(0, '"directives" must be Array if provided but got: ' + (String(config.directives) + '.')) : void 0; !(!config.allowedLegacyNames || Array.isArray(config.allowedLegacyNames)) ? (0, _invariant2.default)(0, '"allowedLegacyNames" must be Array if provided but got: ' + (String(config.allowedLegacyNames) + '.')) : void 0; } this.__allowedLegacyNames = config.allowedLegacyNames; this._queryType = config.query; this._mutationType = config.mutation; this._subscriptionType = config.subscription; // Provide specified directives (e.g. @include and @skip) by default. this._directives = config.directives || _directives.specifiedDirectives; this.astNode = config.astNode; // Build type map now to detect any errors within this schema. var initialTypes = [this.getQueryType(), this.getMutationType(), this.getSubscriptionType(), _introspection.__Schema]; var types = config.types; if (types) { initialTypes = initialTypes.concat(types); } // Keep track of all types referenced within the schema. var typeMap = Object.create(null); // First by deeply visiting all initial types. typeMap = initialTypes.reduce(typeMapReducer, typeMap); // Then by deeply visiting all directive types. typeMap = this._directives.reduce(typeMapDirectiveReducer, typeMap); // Storing the resulting map for reference by the schema. this._typeMap = typeMap; // Keep track of all implementations by interface name. this._implementations = Object.create(null); Object.keys(this._typeMap).forEach(function (typeName) { var type = _this._typeMap[typeName]; if ((0, _definition.isObjectType)(type)) { type.getInterfaces().forEach(function (iface) { if ((0, _definition.isInterfaceType)(iface)) { var impls = _this._implementations[iface.name]; if (impls) { impls.push(type); } else { _this._implementations[iface.name] = [type]; } } }); } }); } // Referenced by validateSchema(). GraphQLSchema.prototype.getQueryType = function getQueryType() { return this._queryType; }; GraphQLSchema.prototype.getMutationType = function getMutationType() { return this._mutationType; }; GraphQLSchema.prototype.getSubscriptionType = function getSubscriptionType() { return this._subscriptionType; }; GraphQLSchema.prototype.getTypeMap = function getTypeMap() { return this._typeMap; }; GraphQLSchema.prototype.getType = function getType(name) { return this.getTypeMap()[name]; }; GraphQLSchema.prototype.getPossibleTypes = function getPossibleTypes(abstractType) { if ((0, _definition.isUnionType)(abstractType)) { return abstractType.getTypes(); } return this._implementations[abstractType.name]; }; GraphQLSchema.prototype.isPossibleType = function isPossibleType(abstractType, possibleType) { var possibleTypeMap = this._possibleTypeMap; if (!possibleTypeMap) { this._possibleTypeMap = possibleTypeMap = Object.create(null); } if (!possibleTypeMap[abstractType.name]) { var possibleTypes = this.getPossibleTypes(abstractType); !Array.isArray(possibleTypes) ? (0, _invariant2.default)(0, 'Could not find possible implementing types for ' + abstractType.name + ' ' + 'in schema. Check that schema.types is defined and is an array of ' + 'all possible types in the schema.') : void 0; possibleTypeMap[abstractType.name] = possibleTypes.reduce(function (map, type) { return map[type.name] = true, map; }, Object.create(null)); } return Boolean(possibleTypeMap[abstractType.name][possibleType.name]); }; GraphQLSchema.prototype.getDirectives = function getDirectives() { return this._directives; }; GraphQLSchema.prototype.getDirective = function getDirective(name) { return (0, _find2.default)(this.getDirectives(), function (directive) { return directive.name === name; }); }; return GraphQLSchema; }(); function typeMapReducer(map, type) { if (!type) { return map; } if ((0, _definition.isWrappingType)(type)) { return typeMapReducer(map, type.ofType); } if (map[type.name]) { !(map[type.name] === type) ? (0, _invariant2.default)(0, 'Schema must contain unique named types but contains multiple ' + ('types named "' + type.name + '".')) : void 0; return map; } map[type.name] = type; var reducedMap = map; if ((0, _definition.isUnionType)(type)) { reducedMap = type.getTypes().reduce(typeMapReducer, reducedMap); } if ((0, _definition.isObjectType)(type)) { reducedMap = type.getInterfaces().reduce(typeMapReducer, reducedMap); } if ((0, _definition.isObjectType)(type) || (0, _definition.isInterfaceType)(type)) { (0, _objectValues2.default)(type.getFields()).forEach(function (field) { if (field.args) { var fieldArgTypes = field.args.map(function (arg) { return arg.type; }); reducedMap = fieldArgTypes.reduce(typeMapReducer, reducedMap); } reducedMap = typeMapReducer(reducedMap, field.type); }); } if ((0, _definition.isInputObjectType)(type)) { (0, _objectValues2.default)(type.getFields()).forEach(function (field) { reducedMap = typeMapReducer(reducedMap, field.type); }); } return reducedMap; } function typeMapDirectiveReducer(map, directive) { // Directives are not validated until validateSchema() is called. if (!(0, _directives.isDirective)(directive)) { return map; } return directive.args.reduce(function (_map, arg) { return typeMapReducer(_map, arg.type); }, map); }