swc/crates/swc_bundler/tests/.cache/deno/1f429c4cfe3b434f4499e64af941c5f3500798ba.ts
2021-11-09 20:42:49 +09:00

198 lines
4.6 KiB
TypeScript

// Loaded from https://deno.land/x/graphql_deno@v15.0.0/lib/validation/ValidationContext.js
import { Kind } from '../language/kinds.js';
import { visit } from '../language/visitor.js';
import { TypeInfo, visitWithTypeInfo } from '../utilities/TypeInfo.js';
/**
* 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 {
constructor(ast, onError) {
this._ast = ast;
this._fragments = undefined;
this._fragmentSpreads = new Map();
this._recursivelyReferencedFragments = new Map();
this._onError = onError;
}
reportError(error) {
this._onError(error);
}
getDocument() {
return this._ast;
}
getFragment(name) {
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) {
let spreads = this._fragmentSpreads.get(node);
if (!spreads) {
spreads = [];
const setsToVisit = [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) {
let fragments = this._recursivelyReferencedFragments.get(operation);
if (!fragments) {
fragments = [];
const collectedNames = Object.create(null);
const nodesToVisit = [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 class SDLValidationContext extends ASTValidationContext {
constructor(ast, schema, onError) {
super(ast, onError);
this._schema = schema;
}
getSchema() {
return this._schema;
}
}
export class ValidationContext extends ASTValidationContext {
constructor(schema, ast, typeInfo, onError) {
super(ast, onError);
this._schema = schema;
this._typeInfo = typeInfo;
this._variableUsages = new Map();
this._recursiveVariableUsages = new Map();
}
getSchema() {
return this._schema;
}
getVariableUsages(node) {
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) {
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() {
return this._typeInfo.getType();
}
getParentType() {
return this._typeInfo.getParentType();
}
getInputType() {
return this._typeInfo.getInputType();
}
getParentInputType() {
return this._typeInfo.getParentInputType();
}
getFieldDef() {
return this._typeInfo.getFieldDef();
}
getDirective() {
return this._typeInfo.getDirective();
}
getArgument() {
return this._typeInfo.getArgument();
}
}