node_modules.graphql.utilities.extendSchema.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apollo-client-maven-plugin Show documentation
Show all versions of apollo-client-maven-plugin Show documentation
Maven plugin for generating graphql clients
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.extendSchema = extendSchema;
var _invariant = require('../jsutils/invariant');
var _invariant2 = _interopRequireDefault(_invariant);
var _keyMap = require('../jsutils/keyMap');
var _keyMap2 = _interopRequireDefault(_keyMap);
var _objectValues = require('../jsutils/objectValues');
var _objectValues2 = _interopRequireDefault(_objectValues);
var _buildASTSchema = require('./buildASTSchema');
var _GraphQLError = require('../error/GraphQLError');
var _schema = require('../type/schema');
var _introspection = require('../type/introspection');
var _definition = require('../type/definition');
var _directives = require('../type/directives');
var _kinds = require('../language/kinds');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Produces a new schema given an existing schema and a document which may
* contain GraphQL type extensions and definitions. The original schema will
* remain unaltered.
*
* Because a schema represents a graph of references, a schema cannot be
* extended without effectively making an entire copy. We do not know until it's
* too late if subgraphs remain unchanged.
*
* This algorithm copies the provided schema, applying extensions while
* producing the copy. The original schema remains unaltered.
*
* Accepts options as a third argument:
*
* - commentDescriptions:
* Provide true to use preceding comments as the description.
*
*/
/**
* 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
*/
function extendSchema(schema, documentAST, options) {
!(0, _schema.isSchema)(schema) ? (0, _invariant2.default)(0, 'Must provide valid GraphQLSchema') : void 0;
!(documentAST && documentAST.kind === _kinds.Kind.DOCUMENT) ? (0, _invariant2.default)(0, 'Must provide valid Document AST') : void 0;
// Collect the type definitions and extensions found in the document.
var typeDefinitionMap = Object.create(null);
var typeExtensionsMap = Object.create(null);
// New directives and types are separate because a directives and types can
// have the same name. For example, a type named "skip".
var directiveDefinitions = [];
for (var i = 0; i < documentAST.definitions.length; i++) {
var def = documentAST.definitions[i];
switch (def.kind) {
case _kinds.Kind.OBJECT_TYPE_DEFINITION:
case _kinds.Kind.INTERFACE_TYPE_DEFINITION:
case _kinds.Kind.ENUM_TYPE_DEFINITION:
case _kinds.Kind.UNION_TYPE_DEFINITION:
case _kinds.Kind.SCALAR_TYPE_DEFINITION:
case _kinds.Kind.INPUT_OBJECT_TYPE_DEFINITION:
// Sanity check that none of the defined types conflict with the
// schema's existing types.
var typeName = def.name.value;
if (schema.getType(typeName)) {
throw new _GraphQLError.GraphQLError('Type "' + typeName + '" already exists in the schema. It cannot also ' + 'be defined in this type definition.', [def]);
}
typeDefinitionMap[typeName] = def;
break;
case _kinds.Kind.OBJECT_TYPE_EXTENSION:
case _kinds.Kind.INTERFACE_TYPE_EXTENSION:
// Sanity check that this type extension exists within the
// schema's existing types.
var extendedTypeName = def.name.value;
var existingType = schema.getType(extendedTypeName);
if (!existingType) {
throw new _GraphQLError.GraphQLError('Cannot extend type "' + extendedTypeName + '" because it does not ' + 'exist in the existing schema.', [def]);
}
checkExtensionNode(existingType, def);
var existingTypeExtensions = typeExtensionsMap[extendedTypeName];
typeExtensionsMap[extendedTypeName] = existingTypeExtensions ? existingTypeExtensions.concat([def]) : [def];
break;
case _kinds.Kind.DIRECTIVE_DEFINITION:
var directiveName = def.name.value;
var existingDirective = schema.getDirective(directiveName);
if (existingDirective) {
throw new _GraphQLError.GraphQLError('Directive "' + directiveName + '" already exists in the schema. It ' + 'cannot be redefined.', [def]);
}
directiveDefinitions.push(def);
break;
case _kinds.Kind.SCALAR_TYPE_EXTENSION:
case _kinds.Kind.UNION_TYPE_EXTENSION:
case _kinds.Kind.ENUM_TYPE_EXTENSION:
case _kinds.Kind.INPUT_OBJECT_TYPE_EXTENSION:
throw new Error('The ' + def.kind + ' kind is not yet supported by extendSchema().');
}
}
// If this document contains no new types, extensions, or directives then
// return the same unmodified GraphQLSchema instance.
if (Object.keys(typeExtensionsMap).length === 0 && Object.keys(typeDefinitionMap).length === 0 && directiveDefinitions.length === 0) {
return schema;
}
var astBuilder = new _buildASTSchema.ASTDefinitionBuilder(typeDefinitionMap, options, function (typeRef) {
var typeName = typeRef.name.value;
var existingType = schema.getType(typeName);
if (existingType) {
return getExtendedType(existingType);
}
throw new _GraphQLError.GraphQLError('Unknown type: "' + typeName + '". Ensure that this type exists ' + 'either in the original schema, or is added in a type definition.', [typeRef]);
});
var extendTypeCache = Object.create(null);
// Get the root Query, Mutation, and Subscription object types.
var existingQueryType = schema.getQueryType();
var queryType = existingQueryType ? getExtendedType(existingQueryType) : null;
var existingMutationType = schema.getMutationType();
var mutationType = existingMutationType ? getExtendedType(existingMutationType) : null;
var existingSubscriptionType = schema.getSubscriptionType();
var subscriptionType = existingSubscriptionType ? getExtendedType(existingSubscriptionType) : null;
var types = [].concat((0, _objectValues2.default)(schema.getTypeMap()).map(function (type) {
return getExtendedType(type);
}), astBuilder.buildTypes((0, _objectValues2.default)(typeDefinitionMap)));
// Support both original legacy names and extended legacy names.
var schemaAllowedLegacyNames = schema.__allowedLegacyNames;
var extendAllowedLegacyNames = options && options.allowedLegacyNames;
var allowedLegacyNames = schemaAllowedLegacyNames && extendAllowedLegacyNames ? schemaAllowedLegacyNames.concat(extendAllowedLegacyNames) : schemaAllowedLegacyNames || extendAllowedLegacyNames;
// Then produce and return a Schema with these types.
return new _schema.GraphQLSchema({
query: queryType,
mutation: mutationType,
subscription: subscriptionType,
types: types,
directives: getMergedDirectives(),
astNode: schema.astNode,
allowedLegacyNames: allowedLegacyNames
});
// Below are functions used for producing this schema that have closed over
// this scope and have access to the schema, cache, and newly defined types.
function getMergedDirectives() {
var existingDirectives = schema.getDirectives();
!existingDirectives ? (0, _invariant2.default)(0, 'schema must have default directives') : void 0;
return existingDirectives.concat(directiveDefinitions.map(function (node) {
return astBuilder.buildDirective(node);
}));
}
function getExtendedType(type) {
if (!extendTypeCache[type.name]) {
extendTypeCache[type.name] = extendType(type);
}
return extendTypeCache[type.name];
}
// To be called at most once per type. Only getExtendedType should call this.
function extendType(type) {
if ((0, _introspection.isIntrospectionType)(type)) {
// Introspection types are not extended.
return type;
}
if ((0, _definition.isObjectType)(type)) {
return extendObjectType(type);
}
if ((0, _definition.isInterfaceType)(type)) {
return extendInterfaceType(type);
}
if ((0, _definition.isUnionType)(type)) {
return extendUnionType(type);
}
// This type is not yet extendable.
return type;
}
function extendObjectType(type) {
var name = type.name;
var extensionASTNodes = typeExtensionsMap[name] ? type.extensionASTNodes ? type.extensionASTNodes.concat(typeExtensionsMap[name]) : typeExtensionsMap[name] : type.extensionASTNodes;
return new _definition.GraphQLObjectType({
name: name,
description: type.description,
interfaces: function interfaces() {
return extendImplementedInterfaces(type);
},
fields: function fields() {
return extendFieldMap(type);
},
astNode: type.astNode,
extensionASTNodes: extensionASTNodes,
isTypeOf: type.isTypeOf
});
}
function extendInterfaceType(type) {
var name = type.name;
var extensionASTNodes = typeExtensionsMap[name] ? type.extensionASTNodes ? type.extensionASTNodes.concat(typeExtensionsMap[name]) : typeExtensionsMap[name] : type.extensionASTNodes;
return new _definition.GraphQLInterfaceType({
name: type.name,
description: type.description,
fields: function fields() {
return extendFieldMap(type);
},
astNode: type.astNode,
extensionASTNodes: extensionASTNodes,
resolveType: type.resolveType
});
}
function extendUnionType(type) {
return new _definition.GraphQLUnionType({
name: type.name,
description: type.description,
types: type.getTypes().map(getExtendedType),
astNode: type.astNode,
resolveType: type.resolveType
});
}
function extendImplementedInterfaces(type) {
var interfaces = type.getInterfaces().map(getExtendedType);
// If there are any extensions to the interfaces, apply those here.
var extensions = typeExtensionsMap[type.name];
if (extensions) {
extensions.forEach(function (extension) {
extension.interfaces.forEach(function (namedType) {
// Note: While this could make early assertions to get the correctly
// typed values, that would throw immediately while type system
// validation with validateSchema() will produce more actionable results.
interfaces.push(astBuilder.buildType(namedType));
});
});
}
return interfaces;
}
function extendFieldMap(type) {
var newFieldMap = Object.create(null);
var oldFieldMap = type.getFields();
Object.keys(oldFieldMap).forEach(function (fieldName) {
var field = oldFieldMap[fieldName];
newFieldMap[fieldName] = {
description: field.description,
deprecationReason: field.deprecationReason,
type: extendFieldType(field.type),
args: (0, _keyMap2.default)(field.args, function (arg) {
return arg.name;
}),
astNode: field.astNode,
resolve: field.resolve
};
});
// If there are any extensions to the fields, apply those here.
var extensions = typeExtensionsMap[type.name];
if (extensions) {
extensions.forEach(function (extension) {
extension.fields.forEach(function (field) {
var fieldName = field.name.value;
if (oldFieldMap[fieldName]) {
throw new _GraphQLError.GraphQLError('Field "' + type.name + '.' + fieldName + '" already exists in the ' + 'schema. It cannot also be defined in this type extension.', [field]);
}
newFieldMap[fieldName] = astBuilder.buildField(field);
});
});
}
return newFieldMap;
}
function extendFieldType(typeDef) {
if ((0, _definition.isListType)(typeDef)) {
return (0, _definition.GraphQLList)(extendFieldType(typeDef.ofType));
}
if ((0, _definition.isNonNullType)(typeDef)) {
return (0, _definition.GraphQLNonNull)(extendFieldType(typeDef.ofType));
}
return getExtendedType(typeDef);
}
}
function checkExtensionNode(type, node) {
switch (node.kind) {
case _kinds.Kind.OBJECT_TYPE_EXTENSION:
if (!(0, _definition.isObjectType)(type)) {
throw new _GraphQLError.GraphQLError('Cannot extend non-object type "' + type.name + '".', [node]);
}
break;
case _kinds.Kind.INTERFACE_TYPE_EXTENSION:
if (!(0, _definition.isInterfaceType)(type)) {
throw new _GraphQLError.GraphQLError('Cannot extend non-interface type "' + type.name + '".', [node]);
}
break;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy