graphql
Version:
A Query Language and Runtime which can target any service.
387 lines (322 loc) • 13 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isSchema = isSchema;
exports.assertSchema = assertSchema;
exports.GraphQLSchema = void 0;
var _find = _interopRequireDefault(require("../polyfills/find"));
var _objectValues = _interopRequireDefault(require("../polyfills/objectValues"));
var _isObjectLike = _interopRequireDefault(require("../jsutils/isObjectLike"));
var _definition = require("./definition");
var _directives = require("./directives");
var _inspect = _interopRequireDefault(require("../jsutils/inspect"));
var _introspection = require("./introspection");
var _defineToStringTag = _interopRequireDefault(require("../jsutils/defineToStringTag"));
var _instanceOf = _interopRequireDefault(require("../jsutils/instanceOf"));
var _invariant = _interopRequireDefault(require("../jsutils/invariant"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// eslint-disable-next-line no-redeclare
function isSchema(schema) {
return (0, _instanceOf.default)(schema, GraphQLSchema);
}
function assertSchema(schema) {
!isSchema(schema) ? (0, _invariant.default)(0, "Expected ".concat((0, _inspect.default)(schema), " to be a GraphQL schema.")) : void 0;
return schema;
}
/**
* 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: When the schema is constructed, by default only the types that are
* reachable by traversing the root types are included, other types must be
* explicitly referenced.
*
* Example:
*
* const characterInterface = new GraphQLInterfaceType({
* name: 'Character',
* ...
* });
*
* const humanType = new GraphQLObjectType({
* name: 'Human',
* interfaces: [characterInterface],
* ...
* });
*
* const droidType = new GraphQLObjectType({
* name: 'Droid',
* interfaces: [characterInterface],
* ...
* });
*
* const schema = new GraphQLSchema({
* query: new GraphQLObjectType({
* name: 'Query',
* fields: {
* hero: { type: characterInterface, ... },
* }
* }),
* ...
* // Since this schema references only the `Character` interface it's
* // necessary to explicitly list the types that implement it if
* // you want them to be included in the final schema.
* types: [humanType, droidType],
* })
*
* 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 =
/*#__PURE__*/
function () {
// Used as a cache for validateSchema().
// Referenced by validateSchema().
function GraphQLSchema(config) {
// 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 {
this.__validationErrors = undefined; // Otherwise check for common mistakes during construction to produce
// clear and early error messages.
!(0, _isObjectLike.default)(config) ? (0, _invariant.default)(0, 'Must provide configuration object.') : void 0;
!(!config.types || Array.isArray(config.types)) ? (0, _invariant.default)(0, "\"types\" must be Array if provided but got: ".concat((0, _inspect.default)(config.types), ".")) : void 0;
!(!config.directives || Array.isArray(config.directives)) ? (0, _invariant.default)(0, '"directives" must be Array if provided but got: ' + "".concat((0, _inspect.default)(config.directives), ".")) : void 0;
!(!config.allowedLegacyNames || Array.isArray(config.allowedLegacyNames)) ? (0, _invariant.default)(0, '"allowedLegacyNames" must be Array if provided but got: ' + "".concat((0, _inspect.default)(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;
this.extensionASTNodes = config.extensionASTNodes; // 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;
this._possibleTypeMap = Object.create(null); // Keep track of all implementations by interface name.
this._implementations = Object.create(null);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = (0, _objectValues.default)(this._typeMap)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var type = _step.value;
if ((0, _definition.isObjectType)(type)) {
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = type.getInterfaces()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var iface = _step2.value;
if ((0, _definition.isInterfaceType)(iface)) {
var impls = this._implementations[iface.name];
if (impls) {
impls.push(type);
} else {
this._implementations[iface.name] = [type];
}
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
} else if ((0, _definition.isAbstractType)(type) && !this._implementations[type.name]) {
this._implementations[type.name] = [];
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
var _proto = GraphQLSchema.prototype;
_proto.getQueryType = function getQueryType() {
return this._queryType;
};
_proto.getMutationType = function getMutationType() {
return this._mutationType;
};
_proto.getSubscriptionType = function getSubscriptionType() {
return this._subscriptionType;
};
_proto.getTypeMap = function getTypeMap() {
return this._typeMap;
};
_proto.getType = function getType(name) {
return this.getTypeMap()[name];
};
_proto.getPossibleTypes = function getPossibleTypes(abstractType) {
if ((0, _definition.isUnionType)(abstractType)) {
return abstractType.getTypes();
}
return this._implementations[abstractType.name];
};
_proto.isPossibleType = function isPossibleType(abstractType, possibleType) {
var possibleTypeMap = this._possibleTypeMap;
if (!possibleTypeMap[abstractType.name]) {
var possibleTypes = this.getPossibleTypes(abstractType);
possibleTypeMap[abstractType.name] = possibleTypes.reduce(function (map, type) {
map[type.name] = true;
return map;
}, Object.create(null));
}
return Boolean(possibleTypeMap[abstractType.name][possibleType.name]);
};
_proto.getDirectives = function getDirectives() {
return this._directives;
};
_proto.getDirective = function getDirective(name) {
return (0, _find.default)(this.getDirectives(), function (directive) {
return directive.name === name;
});
};
_proto.toConfig = function toConfig() {
return {
types: (0, _objectValues.default)(this.getTypeMap()),
directives: this.getDirectives().slice(),
query: this.getQueryType(),
mutation: this.getMutationType(),
subscription: this.getSubscriptionType(),
astNode: this.astNode,
extensionASTNodes: this.extensionASTNodes || [],
assumeValid: this.__validationErrors !== undefined,
allowedLegacyNames: this.__allowedLegacyNames
};
};
return GraphQLSchema;
}(); // Conditionally apply `[Symbol.toStringTag]` if `Symbol`s are supported
exports.GraphQLSchema = GraphQLSchema;
(0, _defineToStringTag.default)(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, _invariant.default)(0, 'Schema must contain uniquely named types but contains multiple ' + "types named \"".concat(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)) {
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = (0, _objectValues.default)(type.getFields())[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var field = _step3.value;
if (field.args) {
var fieldArgTypes = field.args.map(function (arg) {
return arg.type;
});
reducedMap = fieldArgTypes.reduce(typeMapReducer, reducedMap);
}
reducedMap = typeMapReducer(reducedMap, field.type);
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
_iterator3.return();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
}
if ((0, _definition.isInputObjectType)(type)) {
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
var _iteratorError4 = undefined;
try {
for (var _iterator4 = (0, _objectValues.default)(type.getFields())[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
var _field = _step4.value;
reducedMap = typeMapReducer(reducedMap, _field.type);
}
} catch (err) {
_didIteratorError4 = true;
_iteratorError4 = err;
} finally {
try {
if (!_iteratorNormalCompletion4 && _iterator4.return != null) {
_iterator4.return();
}
} finally {
if (_didIteratorError4) {
throw _iteratorError4;
}
}
}
}
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);
}