UNPKG

@dillonkearns/elm-graphql

Version:

<img src="https://cdn.jsdelivr.net/gh/martimatix/logo-graphqelm/logo.svg" alt="dillonearns/elm-graphql logo" width="40%" align="right">

472 lines (416 loc) 14.4 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.buildASTSchema = buildASTSchema; exports.getDeprecationReason = getDeprecationReason; exports.getDescription = getDescription; exports.buildSchema = buildSchema; var _invariant = require('../jsutils/invariant'); var _invariant2 = _interopRequireDefault(_invariant); var _keyValMap = require('../jsutils/keyValMap'); var _keyValMap2 = _interopRequireDefault(_keyValMap); var _valueFromAST = require('./valueFromAST'); var _lexer = require('../language/lexer'); var _parser = require('../language/parser'); var _values = require('../execution/values'); var _kinds = require('../language/kinds'); var Kind = _interopRequireWildcard(_kinds); var _schema = require('../type/schema'); var _scalars = require('../type/scalars'); var _definition = require('../type/definition'); var _directives = require('../type/directives'); var _introspection = require('../type/introspection'); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * 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. * * */ function buildWrappedType(innerType, inputTypeNode) { if (inputTypeNode.kind === Kind.LIST_TYPE) { return new _definition.GraphQLList(buildWrappedType(innerType, inputTypeNode.type)); } if (inputTypeNode.kind === Kind.NON_NULL_TYPE) { var wrappedType = buildWrappedType(innerType, inputTypeNode.type); !!(wrappedType instanceof _definition.GraphQLNonNull) ? (0, _invariant2.default)(0, 'No nesting nonnull.') : void 0; return new _definition.GraphQLNonNull(wrappedType); } return innerType; } function getNamedTypeNode(typeNode) { var namedType = typeNode; while (namedType.kind === Kind.LIST_TYPE || namedType.kind === Kind.NON_NULL_TYPE) { namedType = namedType.type; } return namedType; } /** * 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. */ function buildASTSchema(ast) { if (!ast || ast.kind !== Kind.DOCUMENT) { throw new Error('Must provide a document ast.'); } var schemaDef = void 0; var typeDefs = []; var nodeMap = Object.create(null); var directiveDefs = []; for (var i = 0; i < ast.definitions.length; i++) { var d = ast.definitions[i]; switch (d.kind) { case Kind.SCHEMA_DEFINITION: if (schemaDef) { throw new Error('Must provide only one schema definition.'); } schemaDef = d; break; case Kind.SCALAR_TYPE_DEFINITION: case Kind.OBJECT_TYPE_DEFINITION: case Kind.INTERFACE_TYPE_DEFINITION: case Kind.ENUM_TYPE_DEFINITION: case Kind.UNION_TYPE_DEFINITION: case Kind.INPUT_OBJECT_TYPE_DEFINITION: var typeName = d.name.value; if (nodeMap[typeName]) { throw new Error('Type "' + typeName + '" was defined more than once.'); } typeDefs.push(d); nodeMap[typeName] = d; break; case Kind.DIRECTIVE_DEFINITION: directiveDefs.push(d); break; } } var queryTypeName = void 0; var mutationTypeName = void 0; var subscriptionTypeName = void 0; if (schemaDef) { schemaDef.operationTypes.forEach(function (operationType) { var typeName = operationType.type.name.value; if (operationType.operation === 'query') { if (queryTypeName) { throw new Error('Must provide only one query type in schema.'); } if (!nodeMap[typeName]) { throw new Error('Specified query type "' + typeName + '" not found in document.'); } queryTypeName = typeName; } else if (operationType.operation === 'mutation') { if (mutationTypeName) { throw new Error('Must provide only one mutation type in schema.'); } if (!nodeMap[typeName]) { throw new Error('Specified mutation type "' + typeName + '" not found in document.'); } mutationTypeName = typeName; } else if (operationType.operation === 'subscription') { if (subscriptionTypeName) { throw new Error('Must provide only one subscription type in schema.'); } if (!nodeMap[typeName]) { throw new Error('Specified subscription type "' + typeName + '" not found in document.'); } subscriptionTypeName = typeName; } }); } else { if (nodeMap.Query) { queryTypeName = 'Query'; } if (nodeMap.Mutation) { mutationTypeName = 'Mutation'; } if (nodeMap.Subscription) { subscriptionTypeName = 'Subscription'; } } if (!queryTypeName) { throw new Error('Must provide schema definition with query type or a type named Query.'); } var innerTypeMap = { String: _scalars.GraphQLString, Int: _scalars.GraphQLInt, Float: _scalars.GraphQLFloat, Boolean: _scalars.GraphQLBoolean, ID: _scalars.GraphQLID, __Schema: _introspection.__Schema, __Directive: _introspection.__Directive, __DirectiveLocation: _introspection.__DirectiveLocation, __Type: _introspection.__Type, __Field: _introspection.__Field, __InputValue: _introspection.__InputValue, __EnumValue: _introspection.__EnumValue, __TypeKind: _introspection.__TypeKind }; var types = typeDefs.map(function (def) { return typeDefNamed(def.name.value); }); var directives = directiveDefs.map(getDirective); // 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({ query: getObjectType(nodeMap[queryTypeName]), mutation: mutationTypeName ? getObjectType(nodeMap[mutationTypeName]) : null, subscription: subscriptionTypeName ? getObjectType(nodeMap[subscriptionTypeName]) : null, types: types, directives: directives, astNode: schemaDef }); function getDirective(directiveNode) { return new _directives.GraphQLDirective({ name: directiveNode.name.value, description: getDescription(directiveNode), locations: directiveNode.locations.map(function (node) { return node.value; }), args: directiveNode.arguments && makeInputValues(directiveNode.arguments), astNode: directiveNode }); } function getObjectType(typeNode) { var type = typeDefNamed(typeNode.name.value); !(type instanceof _definition.GraphQLObjectType) ? (0, _invariant2.default)(0, 'AST must provide object type.') : void 0; return type; } function produceType(typeNode) { var typeName = getNamedTypeNode(typeNode).name.value; var typeDef = typeDefNamed(typeName); return buildWrappedType(typeDef, typeNode); } function produceInputType(typeNode) { return (0, _definition.assertInputType)(produceType(typeNode)); } function produceOutputType(typeNode) { return (0, _definition.assertOutputType)(produceType(typeNode)); } function produceObjectType(typeNode) { var type = produceType(typeNode); !(type instanceof _definition.GraphQLObjectType) ? (0, _invariant2.default)(0, 'Expected Object type.') : void 0; return type; } function produceInterfaceType(typeNode) { var type = produceType(typeNode); !(type instanceof _definition.GraphQLInterfaceType) ? (0, _invariant2.default)(0, 'Expected Interface type.') : void 0; return type; } function typeDefNamed(typeName) { if (!innerTypeMap[typeName]) { if (!nodeMap[typeName]) { throw new Error('Type "' + typeName + '" not found in document.'); } innerTypeMap[typeName] = makeSchemaDef(nodeMap[typeName]); } return innerTypeMap[typeName]; } function makeSchemaDef(def) { switch (def.kind) { case Kind.OBJECT_TYPE_DEFINITION: return makeTypeDef(def); case Kind.INTERFACE_TYPE_DEFINITION: return makeInterfaceDef(def); case Kind.ENUM_TYPE_DEFINITION: return makeEnumDef(def); case Kind.UNION_TYPE_DEFINITION: return makeUnionDef(def); case Kind.SCALAR_TYPE_DEFINITION: return makeScalarDef(def); case Kind.INPUT_OBJECT_TYPE_DEFINITION: return makeInputObjectDef(def); default: throw new Error('Type kind "' + def.kind + '" not supported.'); } } function makeTypeDef(def) { var typeName = def.name.value; return new _definition.GraphQLObjectType({ name: typeName, description: getDescription(def), fields: function fields() { return makeFieldDefMap(def); }, interfaces: function interfaces() { return makeImplementedInterfaces(def); }, astNode: def }); } function makeFieldDefMap(def) { return (0, _keyValMap2.default)(def.fields, function (field) { return field.name.value; }, function (field) { return { type: produceOutputType(field.type), description: getDescription(field), args: makeInputValues(field.arguments), deprecationReason: getDeprecationReason(field), astNode: field }; }); } function makeImplementedInterfaces(def) { return def.interfaces && def.interfaces.map(function (iface) { return produceInterfaceType(iface); }); } function makeInputValues(values) { return (0, _keyValMap2.default)(values, function (value) { return value.name.value; }, function (value) { var type = produceInputType(value.type); return { type: type, description: getDescription(value), defaultValue: (0, _valueFromAST.valueFromAST)(value.defaultValue, type), astNode: value }; }); } function makeInterfaceDef(def) { return new _definition.GraphQLInterfaceType({ name: def.name.value, description: getDescription(def), fields: function fields() { return makeFieldDefMap(def); }, astNode: def, resolveType: cannotExecuteSchema }); } function makeEnumDef(def) { return new _definition.GraphQLEnumType({ name: def.name.value, description: getDescription(def), values: (0, _keyValMap2.default)(def.values, function (enumValue) { return enumValue.name.value; }, function (enumValue) { return { description: getDescription(enumValue), deprecationReason: getDeprecationReason(enumValue), astNode: enumValue }; }), astNode: def }); } function makeUnionDef(def) { return new _definition.GraphQLUnionType({ name: def.name.value, description: getDescription(def), types: def.types.map(function (t) { return produceObjectType(t); }), resolveType: cannotExecuteSchema, astNode: def }); } function makeScalarDef(def) { return new _definition.GraphQLScalarType({ name: def.name.value, description: getDescription(def), astNode: def, serialize: function serialize() { return null; }, // Note: validation calls the parse functions to determine if a // literal value is correct. Returning null would cause use of custom // scalars to always fail validation. Returning false causes them to // always pass validation. parseValue: function parseValue() { return false; }, parseLiteral: function parseLiteral() { return false; } }); } function makeInputObjectDef(def) { return new _definition.GraphQLInputObjectType({ name: def.name.value, description: getDescription(def), fields: function fields() { return makeInputValues(def.fields); }, astNode: def }); } } /** * 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 based on a contiguous * block full-line of comments preceding it. */ function getDescription(node) { var loc = node.loc; if (!loc) { return; } var comments = []; var minSpaces = void 0; var token = loc.startToken.prev; while (token && token.kind === _lexer.TokenKind.COMMENT && token.next && token.prev && token.line + 1 === token.next.line && token.line !== token.prev.line) { var value = String(token.value); var spaces = leadingSpaces(value); if (minSpaces === undefined || spaces < minSpaces) { minSpaces = spaces; } comments.push(value); token = token.prev; } return comments.reverse().map(function (comment) { return comment.slice(minSpaces); }).join('\n'); } /** * A helper function to build a GraphQLSchema directly from a source * document. */ function buildSchema(source) { return buildASTSchema((0, _parser.parse)(source)); } // Count the number of spaces on the starting side of a string. function leadingSpaces(str) { var i = 0; for (; i < str.length; i++) { if (str[i] !== ' ') { break; } } return i; } function cannotExecuteSchema() { throw new Error('Generated Schema cannot use Interface or Union types for execution.'); }