mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 05:32:09 +03:00
119 lines
4.2 KiB
TypeScript
119 lines
4.2 KiB
TypeScript
// Loaded from https://deno.land/x/graphql_deno@v15.0.0/lib/validation/rules/ValuesOfCorrectTypeRule.js
|
|
|
|
|
|
import objectValues from '../../polyfills/objectValues.js';
|
|
import keyMap from '../../jsutils/keyMap.js';
|
|
import inspect from '../../jsutils/inspect.js';
|
|
import didYouMean from '../../jsutils/didYouMean.js';
|
|
import suggestionList from '../../jsutils/suggestionList.js';
|
|
import { GraphQLError } from '../../error/GraphQLError.js';
|
|
import { print } from '../../language/printer.js';
|
|
import { isLeafType, isInputObjectType, isListType, isNonNullType, isRequiredInputField, getNullableType, getNamedType } from '../../type/definition.js';
|
|
|
|
/**
|
|
* Value literals of correct type
|
|
*
|
|
* A GraphQL document is only valid if all value literals are of the type
|
|
* expected at their position.
|
|
*/
|
|
export function ValuesOfCorrectTypeRule(context) {
|
|
return {
|
|
ListValue(node) {
|
|
// Note: TypeInfo will traverse into a list's item type, so look to the
|
|
// parent input type to check if it is a list.
|
|
const type = getNullableType(context.getParentInputType());
|
|
|
|
if (!isListType(type)) {
|
|
isValidValueNode(context, node);
|
|
return false; // Don't traverse further.
|
|
}
|
|
},
|
|
|
|
ObjectValue(node) {
|
|
const type = getNamedType(context.getInputType());
|
|
|
|
if (!isInputObjectType(type)) {
|
|
isValidValueNode(context, node);
|
|
return false; // Don't traverse further.
|
|
} // Ensure every required field exists.
|
|
|
|
|
|
const fieldNodeMap = keyMap(node.fields, field => field.name.value);
|
|
|
|
for (const fieldDef of objectValues(type.getFields())) {
|
|
const fieldNode = fieldNodeMap[fieldDef.name];
|
|
|
|
if (!fieldNode && isRequiredInputField(fieldDef)) {
|
|
const typeStr = inspect(fieldDef.type);
|
|
context.reportError(new GraphQLError(`Field "${type.name}.${fieldDef.name}" of required type "${typeStr}" was not provided.`, node));
|
|
}
|
|
}
|
|
},
|
|
|
|
ObjectField(node) {
|
|
const parentType = getNamedType(context.getParentInputType());
|
|
const fieldType = context.getInputType();
|
|
|
|
if (!fieldType && isInputObjectType(parentType)) {
|
|
const suggestions = suggestionList(node.name.value, Object.keys(parentType.getFields()));
|
|
context.reportError(new GraphQLError(`Field "${node.name.value}" is not defined by type "${parentType.name}".` + didYouMean(suggestions), node));
|
|
}
|
|
},
|
|
|
|
NullValue(node) {
|
|
const type = context.getInputType();
|
|
|
|
if (isNonNullType(type)) {
|
|
context.reportError(new GraphQLError(`Expected value of type "${inspect(type)}", found ${print(node)}.`, node));
|
|
}
|
|
},
|
|
|
|
EnumValue: node => isValidValueNode(context, node),
|
|
IntValue: node => isValidValueNode(context, node),
|
|
FloatValue: node => isValidValueNode(context, node),
|
|
StringValue: node => isValidValueNode(context, node),
|
|
BooleanValue: node => isValidValueNode(context, node)
|
|
};
|
|
}
|
|
/**
|
|
* Any value literal may be a valid representation of a Scalar, depending on
|
|
* that scalar type.
|
|
*/
|
|
|
|
function isValidValueNode(context, node) {
|
|
// Report any error at the full type expected by the location.
|
|
const locationType = context.getInputType();
|
|
|
|
if (!locationType) {
|
|
return;
|
|
}
|
|
|
|
const type = getNamedType(locationType);
|
|
|
|
if (!isLeafType(type)) {
|
|
const typeStr = inspect(locationType);
|
|
context.reportError(new GraphQLError(`Expected value of type "${typeStr}", found ${print(node)}.`, node));
|
|
return;
|
|
} // Scalars and Enums determine if a literal value is valid via parseLiteral(),
|
|
// which may throw or return an invalid value to indicate failure.
|
|
|
|
|
|
try {
|
|
const parseResult = type.parseLiteral(node, undefined
|
|
/* variables */
|
|
);
|
|
|
|
if (parseResult === undefined) {
|
|
const typeStr = inspect(locationType);
|
|
context.reportError(new GraphQLError(`Expected value of type "${typeStr}", found ${print(node)}.`, node));
|
|
}
|
|
} catch (error) {
|
|
const typeStr = inspect(locationType);
|
|
|
|
if (error instanceof GraphQLError) {
|
|
context.reportError(error);
|
|
} else {
|
|
context.reportError(new GraphQLError(`Expected value of type "${typeStr}", found ${print(node)}; ` + error.message, node, undefined, undefined, undefined, error));
|
|
}
|
|
}
|
|
} |