summaryrefslogtreecommitdiff
path: root/school/node_modules/graphql/validation/ValidationContext.js.flow
diff options
context:
space:
mode:
Diffstat (limited to 'school/node_modules/graphql/validation/ValidationContext.js.flow')
-rw-r--r--school/node_modules/graphql/validation/ValidationContext.js.flow254
1 files changed, 254 insertions, 0 deletions
diff --git a/school/node_modules/graphql/validation/ValidationContext.js.flow b/school/node_modules/graphql/validation/ValidationContext.js.flow
new file mode 100644
index 0000000..dabe4ba
--- /dev/null
+++ b/school/node_modules/graphql/validation/ValidationContext.js.flow
@@ -0,0 +1,254 @@
+// @flow strict
+import type { ObjMap } from '../jsutils/ObjMap';
+
+import type { GraphQLError } from '../error/GraphQLError';
+
+import type { ASTVisitor } from '../language/visitor';
+import type {
+ DocumentNode,
+ OperationDefinitionNode,
+ VariableNode,
+ SelectionSetNode,
+ FragmentSpreadNode,
+ FragmentDefinitionNode,
+} from '../language/ast';
+
+import { Kind } from '../language/kinds';
+import { visit } from '../language/visitor';
+
+import type { GraphQLSchema } from '../type/schema';
+import type { GraphQLDirective } from '../type/directives';
+import type {
+ GraphQLInputType,
+ GraphQLOutputType,
+ GraphQLCompositeType,
+ GraphQLField,
+ GraphQLArgument,
+ GraphQLEnumValue,
+} from '../type/definition';
+
+import { TypeInfo, visitWithTypeInfo } from '../utilities/TypeInfo';
+
+type NodeWithSelectionSet = OperationDefinitionNode | FragmentDefinitionNode;
+type VariableUsage = {|
+ +node: VariableNode,
+ +type: ?GraphQLInputType,
+ +defaultValue: ?mixed,
+|};
+
+/**
+ * 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 class ASTValidationContext {
+ _ast: DocumentNode;
+ _onError: (err: GraphQLError) => void;
+ _fragments: ?ObjMap<FragmentDefinitionNode>;
+ _fragmentSpreads: Map<SelectionSetNode, $ReadOnlyArray<FragmentSpreadNode>>;
+ _recursivelyReferencedFragments: Map<
+ OperationDefinitionNode,
+ $ReadOnlyArray<FragmentDefinitionNode>,
+ >;
+
+ constructor(ast: DocumentNode, onError: (err: GraphQLError) => void) {
+ this._ast = ast;
+ this._fragments = undefined;
+ this._fragmentSpreads = new Map();
+ this._recursivelyReferencedFragments = new Map();
+ this._onError = onError;
+ }
+
+ reportError(error: GraphQLError): void {
+ this._onError(error);
+ }
+
+ 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<FragmentSpreadNode> {
+ let spreads = this._fragmentSpreads.get(node);
+ if (!spreads) {
+ spreads = [];
+ const setsToVisit: Array<SelectionSetNode> = [node];
+ while (setsToVisit.length !== 0) {
+ const set = setsToVisit.pop();
+ for (const selection of set.selections) {
+ 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<FragmentDefinitionNode> {
+ let fragments = this._recursivelyReferencedFragments.get(operation);
+ if (!fragments) {
+ fragments = [];
+ const collectedNames = Object.create(null);
+ const nodesToVisit: Array<SelectionSetNode> = [operation.selectionSet];
+ while (nodesToVisit.length !== 0) {
+ const node = nodesToVisit.pop();
+ for (const spread of this.getFragmentSpreads(node)) {
+ const fragName = spread.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;
+ }
+}
+
+export type ASTValidationRule = (ASTValidationContext) => ASTVisitor;
+
+export class SDLValidationContext extends ASTValidationContext {
+ _schema: ?GraphQLSchema;
+
+ constructor(
+ ast: DocumentNode,
+ schema: ?GraphQLSchema,
+ onError: (err: GraphQLError) => void,
+ ) {
+ super(ast, onError);
+ this._schema = schema;
+ }
+
+ getSchema(): ?GraphQLSchema {
+ return this._schema;
+ }
+}
+
+export type SDLValidationRule = (SDLValidationContext) => ASTVisitor;
+
+export class ValidationContext extends ASTValidationContext {
+ _schema: GraphQLSchema;
+ _typeInfo: TypeInfo;
+ _variableUsages: Map<NodeWithSelectionSet, $ReadOnlyArray<VariableUsage>>;
+ _recursiveVariableUsages: Map<
+ OperationDefinitionNode,
+ $ReadOnlyArray<VariableUsage>,
+ >;
+
+ constructor(
+ schema: GraphQLSchema,
+ ast: DocumentNode,
+ typeInfo: TypeInfo,
+ onError: (err: GraphQLError) => void,
+ ) {
+ super(ast, onError);
+ this._schema = schema;
+ this._typeInfo = typeInfo;
+ this._variableUsages = new Map();
+ this._recursiveVariableUsages = new Map();
+ }
+
+ getSchema(): GraphQLSchema {
+ return this._schema;
+ }
+
+ getVariableUsages(node: NodeWithSelectionSet): $ReadOnlyArray<VariableUsage> {
+ 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(),
+ defaultValue: typeInfo.getDefaultValue(),
+ });
+ },
+ }),
+ );
+ usages = newUsages;
+ this._variableUsages.set(node, usages);
+ }
+ return usages;
+ }
+
+ getRecursiveVariableUsages(
+ operation: OperationDefinitionNode,
+ ): $ReadOnlyArray<VariableUsage> {
+ let usages = this._recursiveVariableUsages.get(operation);
+ if (!usages) {
+ usages = this.getVariableUsages(operation);
+ for (const frag of this.getRecursivelyReferencedFragments(operation)) {
+ usages = usages.concat(this.getVariableUsages(frag));
+ }
+ 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<mixed, mixed> {
+ return this._typeInfo.getFieldDef();
+ }
+
+ getDirective(): ?GraphQLDirective {
+ return this._typeInfo.getDirective();
+ }
+
+ getArgument(): ?GraphQLArgument {
+ return this._typeInfo.getArgument();
+ }
+
+ getEnumValue(): ?GraphQLEnumValue {
+ return this._typeInfo.getEnumValue();
+ }
+}
+
+export type ValidationRule = (ValidationContext) => ASTVisitor;