"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildASTSchema = buildASTSchema; exports.getDescription = getDescription; exports.buildSchema = buildSchema; exports.ASTDefinitionBuilder = void 0; var _objectValues = _interopRequireDefault(require("../polyfills/objectValues")); var _keyMap = _interopRequireDefault(require("../jsutils/keyMap")); var _inspect = _interopRequireDefault(require("../jsutils/inspect")); var _invariant = _interopRequireDefault(require("../jsutils/invariant")); var _devAssert = _interopRequireDefault(require("../jsutils/devAssert")); var _keyValMap = _interopRequireDefault(require("../jsutils/keyValMap")); var _kinds = require("../language/kinds"); var _tokenKind = require("../language/tokenKind"); var _parser = require("../language/parser"); var _predicates = require("../language/predicates"); var _blockString = require("../language/blockString"); var _validate = require("../validation/validate"); var _values = require("../execution/values"); var _scalars = require("../type/scalars"); var _introspection = require("../type/introspection"); var _schema = require("../type/schema"); var _directives = require("../type/directives"); var _definition = require("../type/definition"); var _valueFromAST = require("./valueFromAST"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * This takes the ast of a schema document produced by the parse function in * src/language/parser.js. * * If no schema definition is provided, then it will look for types named Query * and Mutation. * * Given that AST it constructs a GraphQLSchema. The resulting schema * has no resolve methods, so execution will use default resolvers. * * Accepts options as a second argument: * * - commentDescriptions: * Provide true to use preceding comments as the description. * */ function buildASTSchema(documentAST, options) { documentAST && documentAST.kind === _kinds.Kind.DOCUMENT || (0, _devAssert.default)(0, 'Must provide valid Document AST'); if (!options || !(options.assumeValid || options.assumeValidSDL)) { (0, _validate.assertValidSDL)(documentAST); } var schemaDef; var typeDefs = []; var directiveDefs = []; for (var _i2 = 0, _documentAST$definiti2 = documentAST.definitions; _i2 < _documentAST$definiti2.length; _i2++) { var def = _documentAST$definiti2[_i2]; if (def.kind === _kinds.Kind.SCHEMA_DEFINITION) { schemaDef = def; } else if ((0, _predicates.isTypeDefinitionNode)(def)) { typeDefs.push(def); } else if (def.kind === _kinds.Kind.DIRECTIVE_DEFINITION) { directiveDefs.push(def); } } var astBuilder = new ASTDefinitionBuilder(options, function (typeName) { var type = typeMap[typeName]; if (type === undefined) { throw new Error("Type \"".concat(typeName, "\" not found in document.")); } return type; }); var typeMap = keyByNameNode(typeDefs, function (node) { return astBuilder.buildType(node); }); var operationTypes = schemaDef ? getOperationTypes(schemaDef) : { query: 'Query', mutation: 'Mutation', subscription: 'Subscription' }; var directives = directiveDefs.map(function (def) { return astBuilder.buildDirective(def); }); // If specified directives were not explicitly declared, add them. if (!directives.some(function (directive) { return directive.name === 'skip'; })) { directives.push(_directives.GraphQLSkipDirective); } if (!directives.some(function (directive) { return directive.name === 'include'; })) { directives.push(_directives.GraphQLIncludeDirective); } if (!directives.some(function (directive) { return directive.name === 'deprecated'; })) { directives.push(_directives.GraphQLDeprecatedDirective); } return new _schema.GraphQLSchema({ // Note: While this could make early assertions to get the correctly // typed values below, that would throw immediately while type system // validation with validateSchema() will produce more actionable results. query: operationTypes.query ? typeMap[operationTypes.query] : null, mutation: operationTypes.mutation ? typeMap[operationTypes.mutation] : null, subscription: operationTypes.subscription ? typeMap[operationTypes.subscription] : null, types: (0, _objectValues.default)(typeMap), directives: directives, astNode: schemaDef, assumeValid: options && options.assumeValid, allowedLegacyNames: options && options.allowedLegacyNames }); function getOperationTypes(schema) { var opTypes = {}; for (var _i4 = 0, _schema$operationType2 = schema.operationTypes; _i4 < _schema$operationType2.length; _i4++) { var operationType = _schema$operationType2[_i4]; opTypes[operationType.operation] = operationType.type.name.value; } return opTypes; } } var stdTypeMap = (0, _keyMap.default)(_scalars.specifiedScalarTypes.concat(_introspection.introspectionTypes), function (type) { return type.name; }); var ASTDefinitionBuilder = /*#__PURE__*/ function () { function ASTDefinitionBuilder(options, resolveType) { this._options = options; this._resolveType = resolveType; } var _proto = ASTDefinitionBuilder.prototype; _proto.getNamedType = function getNamedType(node) { var name = node.name.value; return stdTypeMap[name] || this._resolveType(name); }; _proto.getWrappedType = function getWrappedType(node) { if (node.kind === _kinds.Kind.LIST_TYPE) { return new _definition.GraphQLList(this.getWrappedType(node.type)); } if (node.kind === _kinds.Kind.NON_NULL_TYPE) { return new _definition.GraphQLNonNull(this.getWrappedType(node.type)); } return this.getNamedType(node); }; _proto.buildDirective = function buildDirective(directive) { var _this = this; var locations = directive.locations.map(function (_ref) { var value = _ref.value; return value; }); return new _directives.GraphQLDirective({ name: directive.name.value, description: getDescription(directive, this._options), locations: locations, isRepeatable: directive.repeatable, args: keyByNameNode(directive.arguments || [], function (arg) { return _this.buildArg(arg); }), astNode: directive }); }; _proto.buildField = function buildField(field) { var _this2 = this; return { // Note: While this could make assertions to get the correctly typed // value, that would throw immediately while type system validation // with validateSchema() will produce more actionable results. type: this.getWrappedType(field.type), description: getDescription(field, this._options), args: keyByNameNode(field.arguments || [], function (arg) { return _this2.buildArg(arg); }), deprecationReason: getDeprecationReason(field), astNode: field }; }; _proto.buildArg = function buildArg(value) { // Note: While this could make assertions to get the correctly typed // value, that would throw immediately while type system validation // with validateSchema() will produce more actionable results. var type = this.getWrappedType(value.type); return { type: type, description: getDescription(value, this._options), defaultValue: (0, _valueFromAST.valueFromAST)(value.defaultValue, type), astNode: value }; }; _proto.buildInputField = function buildInputField(value) { // Note: While this could make assertions to get the correctly typed // value, that would throw immediately while type system validation // with validateSchema() will produce more actionable results. var type = this.getWrappedType(value.type); return { type: type, description: getDescription(value, this._options), defaultValue: (0, _valueFromAST.valueFromAST)(value.defaultValue, type), astNode: value }; }; _proto.buildEnumValue = function buildEnumValue(value) { return { description: getDescription(value, this._options), deprecationReason: getDeprecationReason(value), astNode: value }; }; _proto.buildType = function buildType(astNode) { var name = astNode.name.value; if (stdTypeMap[name]) { return stdTypeMap[name]; } switch (astNode.kind) { case _kinds.Kind.OBJECT_TYPE_DEFINITION: return this._makeTypeDef(astNode); case _kinds.Kind.INTERFACE_TYPE_DEFINITION: return this._makeInterfaceDef(astNode); case _kinds.Kind.ENUM_TYPE_DEFINITION: return this._makeEnumDef(astNode); case _kinds.Kind.UNION_TYPE_DEFINITION: return this._makeUnionDef(astNode); case _kinds.Kind.SCALAR_TYPE_DEFINITION: return this._makeScalarDef(astNode); case _kinds.Kind.INPUT_OBJECT_TYPE_DEFINITION: return this._makeInputObjectDef(astNode); } // Not reachable. All possible type definition nodes have been considered. /* istanbul ignore next */ (0, _invariant.default)(false, 'Unexpected type definition node: ' + (0, _inspect.default)(astNode)); }; _proto._makeTypeDef = function _makeTypeDef(astNode) { var _this3 = this; var interfaceNodes = astNode.interfaces; var fieldNodes = astNode.fields; // Note: While this could make assertions to get the correctly typed // values below, that would throw immediately while type system // validation with validateSchema() will produce more actionable results. var interfaces = interfaceNodes && interfaceNodes.length > 0 ? function () { return interfaceNodes.map(function (ref) { return _this3.getNamedType(ref); }); } : []; var fields = fieldNodes && fieldNodes.length > 0 ? function () { return keyByNameNode(fieldNodes, function (field) { return _this3.buildField(field); }); } : Object.create(null); return new _definition.GraphQLObjectType({ name: astNode.name.value, description: getDescription(astNode, this._options), interfaces: interfaces, fields: fields, astNode: astNode }); }; _proto._makeInterfaceDef = function _makeInterfaceDef(astNode) { var _this4 = this; var fieldNodes = astNode.fields; var fields = fieldNodes && fieldNodes.length > 0 ? function () { return keyByNameNode(fieldNodes, function (field) { return _this4.buildField(field); }); } : Object.create(null); return new _definition.GraphQLInterfaceType({ name: astNode.name.value, description: getDescription(astNode, this._options), fields: fields, astNode: astNode }); }; _proto._makeEnumDef = function _makeEnumDef(astNode) { var _this5 = this; var valueNodes = astNode.values || []; return new _definition.GraphQLEnumType({ name: astNode.name.value, description: getDescription(astNode, this._options), values: keyByNameNode(valueNodes, function (value) { return _this5.buildEnumValue(value); }), astNode: astNode }); }; _proto._makeUnionDef = function _makeUnionDef(astNode) { var _this6 = this; var typeNodes = astNode.types; // Note: While this could make assertions to get the correctly typed // values below, that would throw immediately while type system // validation with validateSchema() will produce more actionable results. var types = typeNodes && typeNodes.length > 0 ? function () { return typeNodes.map(function (ref) { return _this6.getNamedType(ref); }); } : []; return new _definition.GraphQLUnionType({ name: astNode.name.value, description: getDescription(astNode, this._options), types: types, astNode: astNode }); }; _proto._makeScalarDef = function _makeScalarDef(astNode) { return new _definition.GraphQLScalarType({ name: astNode.name.value, description: getDescription(astNode, this._options), astNode: astNode }); }; _proto._makeInputObjectDef = function _makeInputObjectDef(def) { var _this7 = this; var fields = def.fields; return new _definition.GraphQLInputObjectType({ name: def.name.value, description: getDescription(def, this._options), fields: fields ? function () { return keyByNameNode(fields, function (field) { return _this7.buildInputField(field); }); } : Object.create(null), astNode: def }); }; return ASTDefinitionBuilder; }(); exports.ASTDefinitionBuilder = ASTDefinitionBuilder; function keyByNameNode(list, valFn) { return (0, _keyValMap.default)(list, function (_ref2) { var name = _ref2.name; return name.value; }, valFn); } /** * Given a field or enum value node, returns the string value for the * deprecation reason. */ function getDeprecationReason(node) { var deprecated = (0, _values.getDirectiveValues)(_directives.GraphQLDeprecatedDirective, node); return deprecated && deprecated.reason; } /** * Given an ast node, returns its string description. * @deprecated: provided to ease adoption and will be removed in v16. * * Accepts options as a second argument: * * - commentDescriptions: * Provide true to use preceding comments as the description. * */ function getDescription(node, options) { if (node.description) { return node.description.value; } if (options && options.commentDescriptions) { var rawValue = getLeadingCommentBlock(node); if (rawValue !== undefined) { return (0, _blockString.dedentBlockStringValue)('\n' + rawValue); } } } function getLeadingCommentBlock(node) { var loc = node.loc; if (!loc) { return; } var comments = []; var token = loc.startToken.prev; while (token && token.kind === _tokenKind.TokenKind.COMMENT && token.next && token.prev && token.line + 1 === token.next.line && token.line !== token.prev.line) { var value = String(token.value); comments.push(value); token = token.prev; } return comments.reverse().join('\n'); } /** * A helper function to build a GraphQLSchema directly from a source * document. */ function buildSchema(source, options) { return buildASTSchema((0, _parser.parse)(source, options), options); }