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">

231 lines (198 loc) 9.32 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.ValidationContext = undefined; exports.validate = validate; var _invariant = require('../jsutils/invariant'); var _invariant2 = _interopRequireDefault(_invariant); var _error = require('../error'); var _visitor = require('../language/visitor'); var _kinds = require('../language/kinds'); var Kind = _interopRequireWildcard(_kinds); var _schema = require('../type/schema'); var _TypeInfo = require('../utilities/TypeInfo'); var _specifiedRules = require('./specifiedRules'); 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 }; } 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. * * */ /** * Implements the "Validation" section of the spec. * * Validation runs synchronously, returning an array of encountered errors, or * an empty array if no errors were encountered and the document is valid. * * A list of specific validation rules may be provided. If not provided, the * default list of rules defined by the GraphQL specification will be used. * * Each validation rules is a function which returns a visitor * (see the language/visitor API). Visitor methods are expected to return * GraphQLErrors, or Arrays of GraphQLErrors when invalid. * * Optionally a custom TypeInfo instance may be provided. If not provided, one * will be created from the provided schema. */ function validate(schema, ast, rules, typeInfo) { !schema ? (0, _invariant2.default)(0, 'Must provide schema') : void 0; !ast ? (0, _invariant2.default)(0, 'Must provide document') : void 0; !(schema instanceof _schema.GraphQLSchema) ? (0, _invariant2.default)(0, 'Schema must be an instance of GraphQLSchema. Also ensure that there are ' + 'not multiple versions of GraphQL installed in your node_modules directory.') : void 0; return visitUsingRules(schema, typeInfo || new _TypeInfo.TypeInfo(schema), ast, rules || _specifiedRules.specifiedRules); } /** * This uses a specialized visitor which runs multiple visitors in parallel, * while maintaining the visitor skip and break API. * * @internal */ function visitUsingRules(schema, typeInfo, documentAST, rules) { var context = new ValidationContext(schema, documentAST, typeInfo); var visitors = rules.map(function (rule) { return rule(context); }); // Visit the whole document with each instance of all provided rules. (0, _visitor.visit)(documentAST, (0, _visitor.visitWithTypeInfo)(typeInfo, (0, _visitor.visitInParallel)(visitors))); return context.getErrors(); } /** * An instance of this class is passed as the "this" context to all validators, * allowing access to commonly useful contextual information from within a * validation rule. */ var ValidationContext = exports.ValidationContext = function () { function ValidationContext(schema, ast, typeInfo) { _classCallCheck(this, ValidationContext); this._schema = schema; this._ast = ast; this._typeInfo = typeInfo; this._errors = []; this._fragmentSpreads = new Map(); this._recursivelyReferencedFragments = new Map(); this._variableUsages = new Map(); this._recursiveVariableUsages = new Map(); } ValidationContext.prototype.reportError = function reportError(error) { this._errors.push(error); }; ValidationContext.prototype.getErrors = function getErrors() { return this._errors; }; ValidationContext.prototype.getSchema = function getSchema() { return this._schema; }; ValidationContext.prototype.getDocument = function getDocument() { return this._ast; }; ValidationContext.prototype.getFragment = function getFragment(name) { var fragments = this._fragments; if (!fragments) { this._fragments = fragments = this.getDocument().definitions.reduce(function (frags, statement) { if (statement.kind === Kind.FRAGMENT_DEFINITION) { frags[statement.name.value] = statement; } return frags; }, Object.create(null)); } return fragments[name]; }; ValidationContext.prototype.getFragmentSpreads = function getFragmentSpreads(node) { var spreads = this._fragmentSpreads.get(node); if (!spreads) { spreads = []; var setsToVisit = [node]; while (setsToVisit.length !== 0) { var set = setsToVisit.pop(); for (var i = 0; i < set.selections.length; i++) { var selection = set.selections[i]; if (selection.kind === Kind.FRAGMENT_SPREAD) { spreads.push(selection); } else if (selection.selectionSet) { setsToVisit.push(selection.selectionSet); } } } this._fragmentSpreads.set(node, spreads); } return spreads; }; ValidationContext.prototype.getRecursivelyReferencedFragments = function getRecursivelyReferencedFragments(operation) { var fragments = this._recursivelyReferencedFragments.get(operation); if (!fragments) { fragments = []; var collectedNames = Object.create(null); var nodesToVisit = [operation.selectionSet]; while (nodesToVisit.length !== 0) { var _node = nodesToVisit.pop(); var spreads = this.getFragmentSpreads(_node); for (var i = 0; i < spreads.length; i++) { var fragName = spreads[i].name.value; if (collectedNames[fragName] !== true) { collectedNames[fragName] = true; var fragment = this.getFragment(fragName); if (fragment) { fragments.push(fragment); nodesToVisit.push(fragment.selectionSet); } } } } this._recursivelyReferencedFragments.set(operation, fragments); } return fragments; }; ValidationContext.prototype.getVariableUsages = function getVariableUsages(node) { var usages = this._variableUsages.get(node); if (!usages) { var newUsages = []; var typeInfo = new _TypeInfo.TypeInfo(this._schema); (0, _visitor.visit)(node, (0, _visitor.visitWithTypeInfo)(typeInfo, { VariableDefinition: function VariableDefinition() { return false; }, Variable: function Variable(variable) { newUsages.push({ node: variable, type: typeInfo.getInputType() }); } })); usages = newUsages; this._variableUsages.set(node, usages); } return usages; }; ValidationContext.prototype.getRecursiveVariableUsages = function getRecursiveVariableUsages(operation) { var usages = this._recursiveVariableUsages.get(operation); if (!usages) { usages = this.getVariableUsages(operation); var fragments = this.getRecursivelyReferencedFragments(operation); for (var i = 0; i < fragments.length; i++) { Array.prototype.push.apply(usages, this.getVariableUsages(fragments[i])); } this._recursiveVariableUsages.set(operation, usages); } return usages; }; ValidationContext.prototype.getType = function getType() { return this._typeInfo.getType(); }; ValidationContext.prototype.getParentType = function getParentType() { return this._typeInfo.getParentType(); }; ValidationContext.prototype.getInputType = function getInputType() { return this._typeInfo.getInputType(); }; ValidationContext.prototype.getFieldDef = function getFieldDef() { return this._typeInfo.getFieldDef(); }; ValidationContext.prototype.getDirective = function getDirective() { return this._typeInfo.getDirective(); }; ValidationContext.prototype.getArgument = function getArgument() { return this._typeInfo.getArgument(); }; return ValidationContext; }();