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

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));
}
}
}