node_modules.graphql.validation.ValidationContext.js.flow 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
/**
* 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.
*
* @flow strict
*/
import type { ObjMap } from '../jsutils/ObjMap';
import { GraphQLError } from '../error';
import { visit, visitWithTypeInfo } from '../language/visitor';
import { Kind } from '../language/kinds';
import type {
DocumentNode,
OperationDefinitionNode,
VariableNode,
SelectionSetNode,
FragmentSpreadNode,
FragmentDefinitionNode,
} from '../language/ast';
import { GraphQLSchema } from '../type/schema';
import type {
GraphQLInputType,
GraphQLOutputType,
GraphQLCompositeType,
GraphQLField,
GraphQLArgument,
} from '../type/definition';
import type { GraphQLDirective } from '../type/directives';
import { TypeInfo } from '../utilities/TypeInfo';
type NodeWithSelectionSet = OperationDefinitionNode | FragmentDefinitionNode;
type VariableUsage = { node: VariableNode, type: ?GraphQLInputType };
/**
* 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.
*/
export default class ValidationContext {
_schema: GraphQLSchema;
_ast: DocumentNode;
_typeInfo: TypeInfo;
_errors: Array;
_fragments: ObjMap;
_fragmentSpreads: Map>;
_recursivelyReferencedFragments: Map<
OperationDefinitionNode,
$ReadOnlyArray,
>;
_variableUsages: Map>;
_recursiveVariableUsages: Map<
OperationDefinitionNode,
$ReadOnlyArray,
>;
constructor(
schema: GraphQLSchema,
ast: DocumentNode,
typeInfo: TypeInfo,
): void {
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();
}
reportError(error: GraphQLError): void {
this._errors.push(error);
}
getErrors(): $ReadOnlyArray {
return this._errors;
}
getSchema(): GraphQLSchema {
return this._schema;
}
getDocument(): DocumentNode {
return this._ast;
}
getFragment(name: string): ?FragmentDefinitionNode {
let fragments = this._fragments;
if (!fragments) {
this._fragments = fragments = this.getDocument().definitions.reduce(
(frags, statement) => {
if (statement.kind === Kind.FRAGMENT_DEFINITION) {
frags[statement.name.value] = statement;
}
return frags;
},
Object.create(null),
);
}
return fragments[name];
}
getFragmentSpreads(
node: SelectionSetNode,
): $ReadOnlyArray {
let spreads = this._fragmentSpreads.get(node);
if (!spreads) {
spreads = [];
const setsToVisit: Array = [node];
while (setsToVisit.length !== 0) {
const set = setsToVisit.pop();
for (let i = 0; i < set.selections.length; i++) {
const 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;
}
getRecursivelyReferencedFragments(
operation: OperationDefinitionNode,
): $ReadOnlyArray {
let fragments = this._recursivelyReferencedFragments.get(operation);
if (!fragments) {
fragments = [];
const collectedNames = Object.create(null);
const nodesToVisit: Array = [operation.selectionSet];
while (nodesToVisit.length !== 0) {
const node = nodesToVisit.pop();
const spreads = this.getFragmentSpreads(node);
for (let i = 0; i < spreads.length; i++) {
const fragName = spreads[i].name.value;
if (collectedNames[fragName] !== true) {
collectedNames[fragName] = true;
const fragment = this.getFragment(fragName);
if (fragment) {
fragments.push(fragment);
nodesToVisit.push(fragment.selectionSet);
}
}
}
}
this._recursivelyReferencedFragments.set(operation, fragments);
}
return fragments;
}
getVariableUsages(node: NodeWithSelectionSet): $ReadOnlyArray {
let usages = this._variableUsages.get(node);
if (!usages) {
const newUsages = [];
const typeInfo = new TypeInfo(this._schema);
visit(
node,
visitWithTypeInfo(typeInfo, {
VariableDefinition: () => false,
Variable(variable) {
newUsages.push({ node: variable, type: typeInfo.getInputType() });
},
}),
);
usages = newUsages;
this._variableUsages.set(node, usages);
}
return usages;
}
getRecursiveVariableUsages(
operation: OperationDefinitionNode,
): $ReadOnlyArray {
let usages = this._recursiveVariableUsages.get(operation);
if (!usages) {
usages = this.getVariableUsages(operation);
const fragments = this.getRecursivelyReferencedFragments(operation);
for (let i = 0; i < fragments.length; i++) {
Array.prototype.push.apply(
usages,
this.getVariableUsages(fragments[i]),
);
}
this._recursiveVariableUsages.set(operation, usages);
}
return usages;
}
getType(): ?GraphQLOutputType {
return this._typeInfo.getType();
}
getParentType(): ?GraphQLCompositeType {
return this._typeInfo.getParentType();
}
getInputType(): ?GraphQLInputType {
return this._typeInfo.getInputType();
}
getParentInputType(): ?GraphQLInputType {
return this._typeInfo.getParentInputType();
}
getFieldDef(): ?GraphQLField<*, *> {
return this._typeInfo.getFieldDef();
}
getDirective(): ?GraphQLDirective {
return this._typeInfo.getDirective();
}
getArgument(): ?GraphQLArgument {
return this._typeInfo.getArgument();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy