{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/validation/validate.ts"],"names":[],"mappings":"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","sourcesContent":["/** @category Validation */\n\nimport { mapValue } from '../jsutils/mapValue.ts';\nimport type { Maybe } from '../jsutils/Maybe.ts';\n\nimport { GraphQLError } from '../error/GraphQLError.ts';\n\nimport type { DocumentNode } from '../language/ast.ts';\nimport { QueryDocumentKeys } from '../language/ast.ts';\nimport { visit, visitInParallel } from '../language/visitor.ts';\n\nimport type { GraphQLSchema } from '../type/schema.ts';\nimport { assertValidSchema } from '../type/validate.ts';\n\nimport { TypeInfo, visitWithTypeInfo } from '../utilities/TypeInfo.ts';\n\nimport { shouldTrace, validateChannel } from '../diagnostics.ts';\n\nimport { specifiedRules, specifiedSDLRules } from './specifiedRules.ts';\nimport type { SDLValidationRule, ValidationRule } from './ValidationContext.ts';\nimport {\n  SDLValidationContext,\n  ValidationContext,\n} from './ValidationContext.ts';\n\n/**\n * Options used when validating a GraphQL document.\n * @category Validation\n */\nexport interface ValidationOptions {\n  /** Maximum number of validation errors before validation stops. */\n  maxErrors?: number;\n  /** Whether suggestion text should be omitted from validation errors. */\n  hideSuggestions?: Maybe<boolean>;\n}\n\n// Per the specification, descriptions must not affect validation.\n// See https://spec.graphql.org/draft/#sec-Descriptions\nconst QueryDocumentKeysToValidate = mapValue(\n  QueryDocumentKeys,\n  (keys: ReadonlyArray<string>) => keys.filter((key) => key !== 'description'),\n);\n\nconst tooManyValidationErrorsError = new GraphQLError(\n  'Too many validation errors, error limit reached. Validation aborted.',\n);\n\n/**\n * Implements the \"Validation\" section of the spec.\n *\n * Validation runs synchronously, returning an array of encountered errors, or\n * an empty array if no errors were encountered and the document is valid.\n *\n * A list of specific validation rules may be provided. If not provided, the\n * default list of rules defined by the GraphQL specification will be used.\n *\n * Each validation rule is a function that returns a visitor\n * (see the language/visitor API). Visitor methods are expected to return\n * GraphQLErrors, or Arrays of GraphQLErrors when invalid.\n *\n * Validate will stop validation after a `maxErrors` limit has been reached.\n * Attackers can send pathologically invalid queries to induce a DoS attack,\n * so `maxErrors` defaults to 100 errors.\n * @param schema - Schema to validate against.\n * @param documentAST - Document AST to validate.\n * @param rules - Validation rules to apply.\n * @param options - Validation options, including error limits and suggestions.\n * @returns Validation errors, or an empty array when the document is valid.\n * @example\n * ```ts\n * // Validate with the default specified rules.\n * import { parse } from 'graphql/language';\n * import { buildSchema } from 'graphql/utilities';\n * import { validate } from 'graphql/validation';\n *\n * const schema = buildSchema(`\n *   type Query {\n *     fullName: String\n *   }\n * `);\n *\n * validate(schema, parse('{ greeting }')); // => []\n *\n * const errors = validate(schema, parse('{ missing }'));\n * errors[0].message; // => 'Cannot query field \"missing\" on type \"Query\".'\n * ```\n * @example\n * ```ts\n * // This variant uses a custom rule list and validation options.\n * import { parse } from 'graphql/language';\n * import { buildSchema } from 'graphql/utilities';\n * import { FieldsOnCorrectTypeRule, validate } from 'graphql/validation';\n *\n * const schema = buildSchema(`\n *   type Query {\n *     greeting: String\n *   }\n * `);\n * const document = parse('{ missingOne missingTwo }');\n *\n * const errors = validate(schema, document, [FieldsOnCorrectTypeRule], {\n *   maxErrors: 1,\n * });\n *\n * errors.length; // => 2\n * errors[1].message; // => 'Too many validation errors, error limit reached. Validation aborted.'\n *\n * const hiddenSuggestionErrors = validate(\n *   schema,\n *   parse('{ name }'),\n *   [FieldsOnCorrectTypeRule],\n *   { hideSuggestions: true },\n * );\n *\n * hiddenSuggestionErrors[0].message; // => 'Cannot query field \"name\" on type \"Query\".'\n * ```\n */\nexport function validate(\n  schema: GraphQLSchema,\n  documentAST: DocumentNode,\n  rules: ReadonlyArray<ValidationRule> = specifiedRules,\n  options?: ValidationOptions,\n): ReadonlyArray<GraphQLError> {\n  return shouldTrace(validateChannel)\n    ? validateChannel.traceSync(\n        () => validateImpl(schema, documentAST, rules, options),\n        { schema, document: documentAST },\n      )\n    : validateImpl(schema, documentAST, rules, options);\n}\n\nfunction validateImpl(\n  schema: GraphQLSchema,\n  documentAST: DocumentNode,\n  rules: ReadonlyArray<ValidationRule>,\n  options: ValidationOptions | undefined,\n): ReadonlyArray<GraphQLError> {\n  const maxErrors = options?.maxErrors ?? 100;\n  const hideSuggestions = options?.hideSuggestions ?? false;\n\n  // If the schema used for validation is invalid, throw an error.\n  assertValidSchema(schema);\n\n  const errors: Array<GraphQLError> = [];\n  const typeInfo = new TypeInfo(schema);\n  const context = new ValidationContext(\n    schema,\n    documentAST,\n    typeInfo,\n    (error) => {\n      if (errors.length >= maxErrors) {\n        throw tooManyValidationErrorsError;\n      }\n      errors.push(error);\n    },\n    hideSuggestions,\n  );\n\n  // This uses a specialized visitor which runs multiple visitors in parallel,\n  // while maintaining the visitor skip and break API.\n  const visitor = visitInParallel(rules.map((rule) => rule(context)));\n\n  // Visit the whole document with each instance of all provided rules.\n  try {\n    visit(\n      documentAST,\n      visitWithTypeInfo(typeInfo, visitor),\n      QueryDocumentKeysToValidate,\n    );\n  } catch (e: unknown) {\n    if (e === tooManyValidationErrorsError) {\n      errors.push(tooManyValidationErrorsError);\n    } else {\n      throw e;\n    }\n  }\n  return errors;\n}\n\n/** @internal */\nexport function validateSDL(\n  documentAST: DocumentNode,\n  schemaToExtend?: Maybe<GraphQLSchema>,\n  rules: ReadonlyArray<SDLValidationRule> = specifiedSDLRules,\n): ReadonlyArray<GraphQLError> {\n  const errors: Array<GraphQLError> = [];\n  const context = new SDLValidationContext(\n    documentAST,\n    schemaToExtend,\n    (error) => {\n      errors.push(error);\n    },\n  );\n\n  const visitors = rules.map((rule) => rule(context));\n  visit(documentAST, visitInParallel(visitors));\n  return errors;\n}\n\n/**\n * Utility function which asserts a SDL document is valid by throwing an error\n * if it is invalid.\n *\n * @internal\n */\nexport function assertValidSDL(documentAST: DocumentNode): void {\n  const errors = validateSDL(documentAST);\n  if (errors.length !== 0) {\n    throw new Error(errors.map((error) => error.message).join('\\n\\n'));\n  }\n}\n\n/**\n * Utility function which asserts a SDL document is valid by throwing an error\n * if it is invalid.\n *\n * @internal\n */\nexport function assertValidSDLExtension(\n  documentAST: DocumentNode,\n  schema: GraphQLSchema,\n): void {\n  const errors = validateSDL(documentAST, schema);\n  if (errors.length !== 0) {\n    throw new Error(errors.map((error) => error.message).join('\\n\\n'));\n  }\n}\n"]}