You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
5.1 KiB
232 lines
5.1 KiB
'use strict'; |
|
|
|
Object.defineProperty(exports, '__esModule', { |
|
value: true, |
|
}); |
|
exports.ValidationContext = |
|
exports.SDLValidationContext = |
|
exports.ASTValidationContext = |
|
void 0; |
|
|
|
var _kinds = require('../language/kinds.js'); |
|
|
|
var _visitor = require('../language/visitor.js'); |
|
|
|
var _TypeInfo = require('../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. |
|
*/ |
|
class ASTValidationContext { |
|
constructor(ast, onError) { |
|
this._ast = ast; |
|
this._fragments = undefined; |
|
this._fragmentSpreads = new Map(); |
|
this._recursivelyReferencedFragments = new Map(); |
|
this._onError = onError; |
|
} |
|
|
|
get [Symbol.toStringTag]() { |
|
return 'ASTValidationContext'; |
|
} |
|
|
|
reportError(error) { |
|
this._onError(error); |
|
} |
|
|
|
getDocument() { |
|
return this._ast; |
|
} |
|
|
|
getFragment(name) { |
|
let fragments; |
|
|
|
if (this._fragments) { |
|
fragments = this._fragments; |
|
} else { |
|
fragments = Object.create(null); |
|
|
|
for (const defNode of this.getDocument().definitions) { |
|
if (defNode.kind === _kinds.Kind.FRAGMENT_DEFINITION) { |
|
fragments[defNode.name.value] = defNode; |
|
} |
|
} |
|
|
|
this._fragments = fragments; |
|
} |
|
|
|
return fragments[name]; |
|
} |
|
|
|
getFragmentSpreads(node) { |
|
let spreads = this._fragmentSpreads.get(node); |
|
|
|
if (!spreads) { |
|
spreads = []; |
|
const setsToVisit = [node]; |
|
let set; |
|
|
|
while ((set = setsToVisit.pop())) { |
|
for (const selection of set.selections) { |
|
if (selection.kind === _kinds.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]; |
|
let node; |
|
|
|
while ((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; |
|
} |
|
} |
|
|
|
exports.ASTValidationContext = ASTValidationContext; |
|
|
|
class SDLValidationContext extends ASTValidationContext { |
|
constructor(ast, schema, onError) { |
|
super(ast, onError); |
|
this._schema = schema; |
|
} |
|
|
|
get [Symbol.toStringTag]() { |
|
return 'SDLValidationContext'; |
|
} |
|
|
|
getSchema() { |
|
return this._schema; |
|
} |
|
} |
|
|
|
exports.SDLValidationContext = SDLValidationContext; |
|
|
|
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(); |
|
} |
|
|
|
get [Symbol.toStringTag]() { |
|
return 'ValidationContext'; |
|
} |
|
|
|
getSchema() { |
|
return this._schema; |
|
} |
|
|
|
getVariableUsages(node) { |
|
let usages = this._variableUsages.get(node); |
|
|
|
if (!usages) { |
|
const newUsages = []; |
|
const typeInfo = new _TypeInfo.TypeInfo(this._schema); |
|
(0, _visitor.visit)( |
|
node, |
|
(0, _TypeInfo.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(); |
|
} |
|
|
|
getEnumValue() { |
|
return this._typeInfo.getEnumValue(); |
|
} |
|
} |
|
|
|
exports.ValidationContext = ValidationContext;
|
|
|