The validation system implements all GraphQL specification validation rules with extensible validation context and support for custom validation rules.
Validate GraphQL documents against a schema using the complete set of GraphQL validation rules.
/**
* Validate a GraphQL document against a schema
* @param schema - GraphQL schema to validate against
* @param documentAST - Parsed GraphQL document to validate
* @param rules - Validation rules to apply (defaults to specifiedRules)
* @returns Array of validation errors (empty if valid)
*/
function validate(
schema: GraphQLSchema,
documentAST: DocumentNode,
rules?: ReadonlyArray<ValidationRule>
): ReadonlyArray<GraphQLError>;
/**
* Type definition for validation rules
*/
type ValidationRule = (context: ValidationContext) => ASTVisitor;Usage Examples:
import { validate, parse, buildSchema, specifiedRules } from "graphql";
const schema = buildSchema(`
type Query {
user(id: ID!): User
}
type User {
id: ID!
name: String!
}
`);
// Validate a valid document
const validDocument = parse(`
query GetUser($id: ID!) {
user(id: $id) {
id
name
}
}
`);
const validationErrors = validate(schema, validDocument);
console.log(validationErrors.length); // 0 - no errors
// Validate an invalid document
const invalidDocument = parse(`
query GetUser {
user(id: "123") {
id
nonExistentField
}
}
`);
const errors = validate(schema, invalidDocument);
console.log(errors.map(error => error.message));
// ["Cannot query field \"nonExistentField\" on type \"User\"."]
// Validate with custom rules
const customErrors = validate(schema, documentAST, [
...specifiedRules,
NoDeprecatedCustomRule
]);Validation context provides schema information and error reporting during validation.
/**
* Context object passed to validation rules with schema and document information
*/
class ValidationContext {
constructor(schema: GraphQLSchema, ast: DocumentNode, typeInfo: TypeInfo);
/** Report a validation error */
reportError(error: GraphQLError): void;
/** Get all reported errors */
getErrors(): ReadonlyArray<GraphQLError>;
/** Get the GraphQL schema */
getSchema(): GraphQLSchema;
/** Get the document AST */
getDocument(): DocumentNode;
/** Get fragment definition by name */
getFragment(name: string): FragmentDefinitionNode | undefined;
/** Get all fragment definitions */
getFragmentSpreads(node: SelectionSetNode): ReadonlyArray<FragmentSpreadNode>;
/** Get recursively referenced fragments */
getRecursivelyReferencedFragments(operation: OperationDefinitionNode): ReadonlyArray<FragmentDefinitionNode>;
/** Get variable usages in a node */
getRecursiveVariableUsages(node: OperationDefinitionNode | FragmentDefinitionNode): ReadonlyArray<VariableUsage>;
/** Get type information tracker */
getType(): Maybe<GraphQLOutputType>;
getParentType(): Maybe<GraphQLCompositeType>;
getInputType(): Maybe<GraphQLInputType>;
getParentInputType(): Maybe<GraphQLInputType>;
getFieldDef(): Maybe<GraphQLField<any, any>>;
getDirective(): Maybe<GraphQLDirective>;
getArgument(): Maybe<GraphQLArgument>;
}
interface VariableUsage {
readonly node: VariableNode;
readonly type: Maybe<GraphQLInputType>;
readonly defaultValue: unknown;
}Pre-defined collections of validation rules for different use cases.
/**
* All validation rules specified in the GraphQL specification
*/
const specifiedRules: ReadonlyArray<ValidationRule>;
/**
* Recommended subset of validation rules for production use
* Excludes some expensive rules like MaxIntrospectionDepthRule
*/
const recommendedRules: ReadonlyArray<ValidationRule>;Usage Examples:
import { validate, specifiedRules, recommendedRules } from "graphql";
// Use all specification rules (default)
const allErrors = validate(schema, document, specifiedRules);
// Use recommended rules for better performance
const prodErrors = validate(schema, document, recommendedRules);
// Use specific rules only
const customRules = [
FieldsOnCorrectTypeRule,
KnownArgumentNamesRule,
ProvidedRequiredArgumentsRule
];
const limitedErrors = validate(schema, document, customRules);Rules that validate the overall structure and organization of GraphQL documents.
/**
* Validates that document contains only executable definitions
*/
const ExecutableDefinitionsRule: ValidationRule;
/**
* Validates that anonymous operations are alone in the document
*/
const LoneAnonymousOperationRule: ValidationRule;
/**
* Validates that subscription operations have a single root field
*/
const SingleFieldSubscriptionsRule: ValidationRule;Rules that validate field selections and fragment usage.
/**
* Validates that fields exist on their parent types
*/
const FieldsOnCorrectTypeRule: ValidationRule;
/**
* Validates that fragments are defined on composite types
*/
const FragmentsOnCompositeTypesRule: ValidationRule;
/**
* Validates that fragment spreads reference defined fragments
*/
const KnownFragmentNamesRule: ValidationRule;
/**
* Validates that fragments don't create reference cycles
*/
const NoFragmentCyclesRule: ValidationRule;
/**
* Validates that all defined fragments are used
*/
const NoUnusedFragmentsRule: ValidationRule;
/**
* Validates that fragment spreads are type-compatible
*/
const PossibleFragmentSpreadsRule: ValidationRule;
/**
* Validates that overlapping fields can be merged
*/
const OverlappingFieldsCanBeMergedRule: ValidationRule;Rules that validate arguments and variable usage.
/**
* Validates that field and directive arguments are defined
*/
const KnownArgumentNamesRule: ValidationRule;
/**
* Validates that required arguments are provided
*/
const ProvidedRequiredArgumentsRule: ValidationRule;
/**
* Validates that argument names are unique within field/directive
*/
const UniqueArgumentNamesRule: ValidationRule;
/**
* Validates that variables are defined before use
*/
const NoUndefinedVariablesRule: ValidationRule;
/**
* Validates that all defined variables are used
*/
const NoUnusedVariablesRule: ValidationRule;
/**
* Validates that variable names are unique within operation
*/
const UniqueVariableNamesRule: ValidationRule;
/**
* Validates that variables have input types
*/
const VariablesAreInputTypesRule: ValidationRule;
/**
* Validates that variables are used in compatible positions
*/
const VariablesInAllowedPositionRule: ValidationRule;Rules that validate directive usage.
/**
* Validates that directives are defined and used in valid locations
*/
const KnownDirectivesRule: ValidationRule;
/**
* Validates that non-repeatable directives appear once per location
*/
const UniqueDirectivesPerLocationRule: ValidationRule;Rules that validate types and literal values.
/**
* Validates that referenced types are defined in the schema
*/
const KnownTypeNamesRule: ValidationRule;
/**
* Validates that leaf fields don't have selections
*/
const ScalarLeafsRule: ValidationRule;
/**
* Validates that literal values match their expected types
*/
const ValuesOfCorrectTypeRule: ValidationRule;Rules that ensure uniqueness of various GraphQL constructs.
/**
* Validates that fragment names are unique within document
*/
const UniqueFragmentNamesRule: ValidationRule;
/**
* Validates that input object field names are unique
*/
const UniqueInputFieldNamesRule: ValidationRule;
/**
* Validates that operation names are unique within document
*/
const UniqueOperationNamesRule: ValidationRule;Rules that apply specifically to Schema Definition Language documents.
/**
* Validates that schema definition appears at most once
*/
const LoneSchemaDefinitionRule: ValidationRule;
/**
* Validates that operation types are unique in schema definition
*/
const UniqueOperationTypesRule: ValidationRule;
/**
* Validates that type names are unique within schema
*/
const UniqueTypeNamesRule: ValidationRule;
/**
* Validates that enum value names are unique within enum
*/
const UniqueEnumValueNamesRule: ValidationRule;
/**
* Validates that field names are unique within object/interface types
*/
const UniqueFieldDefinitionNamesRule: ValidationRule;
/**
* Validates that argument names are unique within field definitions
*/
const UniqueArgumentDefinitionNamesRule: ValidationRule;
/**
* Validates that directive names are unique within schema
*/
const UniqueDirectiveNamesRule: ValidationRule;
/**
* Validates that type extensions are valid
*/
const PossibleTypeExtensionsRule: ValidationRule;Additional validation rules for specific use cases.
/**
* Custom rule to disallow deprecated fields and arguments
*/
const NoDeprecatedCustomRule: ValidationRule;
/**
* Custom rule to disallow schema introspection queries
*/
const NoSchemaIntrospectionCustomRule: ValidationRule;
/**
* Rule to limit introspection query depth for security
*/
const MaxIntrospectionDepthRule: ValidationRule;Usage Examples:
import {
validate,
NoDeprecatedCustomRule,
NoSchemaIntrospectionCustomRule
} from "graphql";
// Create custom validation with security rules
const securityRules = [
NoSchemaIntrospectionCustomRule,
MaxIntrospectionDepthRule,
NoDeprecatedCustomRule
];
const errors = validate(schema, document, [
...specifiedRules,
...securityRules
]);
// Custom validation rule example
const NoLongFieldNamesRule = (context) => ({
Field(node) {
if (node.name.value.length > 20) {
context.reportError(
new GraphQLError(
`Field name "${node.name.value}" is too long`,
{ nodes: node }
)
);
}
}
});
const customErrors = validate(schema, document, [
...specifiedRules,
NoLongFieldNamesRule
]);/**
* Create a custom validation rule
* @param context - Validation context
* @returns AST visitor object
*/
type ValidationRule = (context: ValidationContext) => ASTVisitor;
/**
* Example custom validation rule
*/
const ExampleCustomRule: ValidationRule = (context) => ({
// Visit field nodes
Field(node) {
// Perform validation logic
if (shouldReportError(node)) {
context.reportError(
new GraphQLError('Custom validation error', { nodes: node })
);
}
},
// Visit other node types
Directive(node) {
// Additional validation logic
}
});Usage Examples:
import { GraphQLError, ValidationRule } from "graphql";
// Rule to prevent fields starting with underscore (except introspection)
const NoUnderscoreFieldsRule: ValidationRule = (context) => ({
Field(node) {
const fieldName = node.name.value;
if (fieldName.startsWith('_') && !fieldName.startsWith('__')) {
context.reportError(
new GraphQLError(
`Field names cannot start with underscore: "${fieldName}"`,
{ nodes: node }
)
);
}
}
});
// Rule to limit query depth
const MaxDepthRule = (maxDepth: number): ValidationRule => (context) => {
let depth = 0;
return {
Field: {
enter() {
depth++;
if (depth > maxDepth) {
context.reportError(
new GraphQLError(
`Query depth exceeds maximum of ${maxDepth}`,
{ nodes: context.getDocument() }
)
);
}
},
leave() {
depth--;
}
}
};
};
// Use custom rules
const errors = validate(schema, document, [
...specifiedRules,
NoUnderscoreFieldsRule,
MaxDepthRule(10)
]);