summaryrefslogtreecommitdiff
path: root/alarm/node_modules/graphql/validation/rules/VariablesInAllowedPositionRule.js.flow
diff options
context:
space:
mode:
Diffstat (limited to 'alarm/node_modules/graphql/validation/rules/VariablesInAllowedPositionRule.js.flow')
-rw-r--r--alarm/node_modules/graphql/validation/rules/VariablesInAllowedPositionRule.js.flow98
1 files changed, 98 insertions, 0 deletions
diff --git a/alarm/node_modules/graphql/validation/rules/VariablesInAllowedPositionRule.js.flow b/alarm/node_modules/graphql/validation/rules/VariablesInAllowedPositionRule.js.flow
new file mode 100644
index 0000000..722ee99
--- /dev/null
+++ b/alarm/node_modules/graphql/validation/rules/VariablesInAllowedPositionRule.js.flow
@@ -0,0 +1,98 @@
+// @flow strict
+import inspect from '../../jsutils/inspect';
+
+import { GraphQLError } from '../../error/GraphQLError';
+
+import { Kind } from '../../language/kinds';
+import type { ValueNode } from '../../language/ast';
+import type { ASTVisitor } from '../../language/visitor';
+
+import type { GraphQLSchema } from '../../type/schema';
+import type { GraphQLType } from '../../type/definition';
+import { isNonNullType } from '../../type/definition';
+
+import { typeFromAST } from '../../utilities/typeFromAST';
+import { isTypeSubTypeOf } from '../../utilities/typeComparators';
+
+import type { ValidationContext } from '../ValidationContext';
+
+/**
+ * Variables passed to field arguments conform to type
+ */
+export function VariablesInAllowedPositionRule(
+ context: ValidationContext,
+): ASTVisitor {
+ let varDefMap = Object.create(null);
+
+ return {
+ OperationDefinition: {
+ enter() {
+ varDefMap = Object.create(null);
+ },
+ leave(operation) {
+ const usages = context.getRecursiveVariableUsages(operation);
+
+ for (const { node, type, defaultValue } of usages) {
+ const varName = node.name.value;
+ const varDef = varDefMap[varName];
+ if (varDef && type) {
+ // A var type is allowed if it is the same or more strict (e.g. is
+ // a subtype of) than the expected type. It can be more strict if
+ // the variable type is non-null when the expected type is nullable.
+ // If both are list types, the variable item type can be more strict
+ // than the expected item type (contravariant).
+ const schema = context.getSchema();
+ const varType = typeFromAST(schema, varDef.type);
+ if (
+ varType &&
+ !allowedVariableUsage(
+ schema,
+ varType,
+ varDef.defaultValue,
+ type,
+ defaultValue,
+ )
+ ) {
+ const varTypeStr = inspect(varType);
+ const typeStr = inspect(type);
+ context.reportError(
+ new GraphQLError(
+ `Variable "$${varName}" of type "${varTypeStr}" used in position expecting type "${typeStr}".`,
+ [varDef, node],
+ ),
+ );
+ }
+ }
+ }
+ },
+ },
+ VariableDefinition(node) {
+ varDefMap[node.variable.name.value] = node;
+ },
+ };
+}
+
+/**
+ * Returns true if the variable is allowed in the location it was found,
+ * which includes considering if default values exist for either the variable
+ * or the location at which it is located.
+ */
+function allowedVariableUsage(
+ schema: GraphQLSchema,
+ varType: GraphQLType,
+ varDefaultValue: ?ValueNode,
+ locationType: GraphQLType,
+ locationDefaultValue: ?mixed,
+): boolean {
+ if (isNonNullType(locationType) && !isNonNullType(varType)) {
+ const hasNonNullVariableDefaultValue =
+ varDefaultValue != null && varDefaultValue.kind !== Kind.NULL;
+ const hasLocationDefaultValue = locationDefaultValue !== undefined;
+ if (!hasNonNullVariableDefaultValue && !hasLocationDefaultValue) {
+ return false;
+ }
+ const nullableLocationType = locationType.ofType;
+ return isTypeSubTypeOf(schema, varType, nullableLocationType);
+ }
+ return isTypeSubTypeOf(schema, varType, locationType);
+}