@relay-graphql-js/validation-rules
Version:
shared relay validation rules for graphql-js parser
93 lines (92 loc) • 5.28 kB
JavaScript
;
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
exports.__esModule = true;
exports.RelayVariablesInAllowedPosition = void 0;
var graphql_1 = require("graphql");
var argumentDefinitions_1 = require("./argumentDefinitions");
// tslint:disable-next-line: no-shadowed-variable
exports.RelayVariablesInAllowedPosition = function RelayVariablesInAllowedPosition(context) {
return {
FragmentDefinition: function (fragmentDef) {
var schema = context.getSchema();
var varUsages = argumentDefinitions_1.getRecursiveVariableUsagesWithRelayInfo(context, fragmentDef);
varUsages.forEach(function (usage) {
if (usage.variableDefinition) {
var varDefType = usage.variableDefinition.schemaType;
var varDefDefault = usage.variableDefinition.defaultValue;
var definitionNode = usage.variableDefinition.node;
var locationType = usage.type;
var locationDefaultValue = usage.defaultValue;
var varName = usage.node.name.value;
if (varDefType &&
locationType &&
definitionNode &&
!allowedVariableUsage(schema, varDefType, varDefDefault, locationType, locationDefaultValue)) {
// The diagnostics in vscode does seemingly not support errors in one file having a related location
// in a different file
var location_1 = __spreadArrays((!usage.usingFragmentName ? [definitionNode] : []), [usage.node]);
context.reportError(new graphql_1.GraphQLError(badVarPosMessage(varName, varDefType.toString(), locationType.toString()), location_1));
}
}
});
},
OperationDefinition: function (opDef) {
var schema = context.getSchema();
var varUsages = argumentDefinitions_1.getRecursiveVariableUsagesWithRelayInfo(context, opDef);
var errors = Object.create(null);
varUsages.forEach(function (usage) {
// We only check for variables that are not defined in the fragment itself
// as the visitor for the fragment definition will test for that
// thus giving errors for those variables even when the fragment is not
// used in an operation
if (usage.variableDefinition && !argumentDefinitions_1.isFragmentDefinedVariable(usage.variableDefinition)) {
var varDefType = usage.variableDefinition.schemaType;
var varDefDefault = usage.variableDefinition.defaultValue;
var definitionNode = usage.variableDefinition.node;
var locationType = usage.type;
var locationDefaultValue = usage.defaultValue;
var varName = usage.node.name.value;
if (varDefType &&
locationType &&
definitionNode &&
!allowedVariableUsage(schema, varDefType, varDefDefault, locationType, locationDefaultValue)) {
// The diagnostics in vscode does seemingly not support errors in one file having a related location
// in a different file
var location_2 = __spreadArrays((!usage.usingFragmentName ? [usage.node] : []), [opDef]);
var errorStr = badVarPosMessage(varName, varDefType.toString(), locationType.toString());
if (!errors[errorStr]) {
if (usage.usingFragmentName) {
errors[errorStr] = true;
}
context.reportError(new graphql_1.GraphQLError(errorStr, location_2));
}
}
}
});
}
};
};
/**
* This is ported from the `VariablesInAllowedPosition` rule from GraphQL itself
*/
function allowedVariableUsage(schema, varType, varDefaultValue, locationType, locationDefaultValue) {
if (graphql_1.isNonNullType(locationType) && !graphql_1.isNonNullType(varType)) {
var hasNonNullVariableDefaultValue = varDefaultValue != null && varDefaultValue.kind !== "NullValue";
var hasLocationDefaultValue = locationDefaultValue !== undefined;
if (!hasNonNullVariableDefaultValue && !hasLocationDefaultValue) {
return false;
}
var nullableLocationType = locationType.ofType;
return graphql_1.isTypeSubTypeOf(schema, varType, nullableLocationType);
}
return graphql_1.isTypeSubTypeOf(schema, varType, locationType);
}
function badVarPosMessage(varName, varType, expectedType) {
return "Variable \"$" + varName + "\" of type \"" + varType + "\" used in position expecting type \"" + expectedType + "\".";
}