graphql
Version:
A Query Language and Runtime which can target any service.
1 lines • 16.3 kB
Source Map (JSON)
{"version":3,"file":"GraphQLError.js","sourceRoot":"","sources":["../../src/error/GraphQLError.ts"],"names":[],"mappings":"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","sourcesContent":["/** @category Errors */\n\nimport { isObjectLike } from '../jsutils/isObjectLike.ts';\nimport type { Maybe } from '../jsutils/Maybe.ts';\n\nimport type { ASTNode, Location } from '../language/ast.ts';\nimport type { SourceLocation } from '../language/location.ts';\nimport { getLocation } from '../language/location.ts';\nimport {\n printLocation,\n printSourceLocation,\n} from '../language/printLocation.ts';\nimport type { Source } from '../language/source.ts';\n\n/**\n * Custom extensions\n * @remarks\n * Use a unique identifier name for your extension, for example the name of\n * your library or project. Do not use a shortened identifier as this increases\n * the risk of conflicts. We recommend you add at most one extension field,\n * an object which can contain all the values you need.\n */\nexport interface GraphQLErrorExtensions {\n [attributeName: string]: unknown;\n}\n\n/**\n * Custom formatted extensions\n * @remarks\n * Use a unique identifier name for your extension, for example the name of\n * your library or project. Do not use a shortened identifier as this increases\n * the risk of conflicts. We recommend you add at most one extension field,\n * an object which can contain all the values you need.\n */\nexport interface GraphQLFormattedErrorExtensions {\n [attributeName: string]: unknown;\n}\n\n/** Options used to construct a GraphQLError. */\nexport interface GraphQLErrorOptions {\n /** AST node or nodes associated with this error. */\n nodes?: ReadonlyArray<ASTNode> | ASTNode | null | undefined;\n /** Source document used to derive error locations. */\n source?: Maybe<Source>;\n /** Character offsets in the source document associated with this error. */\n positions?: Maybe<ReadonlyArray<number>>;\n /** Response path where this error occurred during execution. */\n path?: Maybe<ReadonlyArray<string | number>>;\n /**\n * Original error that caused this GraphQLError, if one exists.\n * Deprecated in favor of `cause` to better align with JavaScript standards.\n * @deprecated Prefer `cause` instead.\n */\n originalError?: Maybe<Error & { readonly extensions?: unknown }>;\n /** Cause of this GraphQLError, if one exists. */\n cause?: unknown;\n /** Extension fields to include in the formatted result. */\n extensions?: Maybe<GraphQLErrorExtensions>;\n}\n\n/**\n * A GraphQLError describes an Error found during the parse, validate, or\n * execute phases of performing a GraphQL operation. In addition to a message\n * and stack trace, it also includes information about the locations in a\n * GraphQL document and/or execution result that correspond to the Error.\n */\nexport class GraphQLError extends Error {\n /**\n * An array of `{ line, column }` locations within the source GraphQL document\n * which correspond to this error.\n *\n * Errors during validation often contain multiple locations, for example to\n * point out two things with the same name. Errors during execution include a\n * single location, the field which produced the error.\n *\n * Enumerable, and appears in the result of JSON.stringify().\n */\n readonly locations: ReadonlyArray<SourceLocation> | undefined;\n\n /**\n * An array describing the JSON-path into the execution response which\n * corresponds to this error. Only included for errors during execution.\n *\n * Enumerable, and appears in the result of JSON.stringify().\n */\n readonly path: ReadonlyArray<string | number> | undefined;\n\n /** An array of GraphQL AST Nodes corresponding to this error. */\n readonly nodes: ReadonlyArray<ASTNode> | undefined;\n\n /**\n * The source GraphQL document for the first location of this error.\n *\n * Note that if this Error represents more than one node, the source may not\n * represent nodes after the first node.\n */\n readonly source: Source | undefined;\n\n /**\n * An array of character offsets within the source GraphQL document\n * which correspond to this error.\n */\n readonly positions: ReadonlyArray<number> | undefined;\n\n /**\n * Original error that caused this GraphQLError, if one exists.\n * Deprecated in favor of `cause` to better align with JavaScript standards.\n * @deprecated Use `cause` instead.\n */\n readonly originalError: Error | undefined;\n\n /** Extension fields to add to the formatted error. */\n readonly extensions: GraphQLErrorExtensions;\n\n /**\n * Creates a GraphQLError instance.\n * @param message - Human-readable error message.\n * @param options - Error metadata such as source locations, response path, cause, original error, and extensions.\n * @example\n * ```ts\n * // Create an error from AST nodes and response metadata.\n * import { parse } from 'graphql/language';\n * import { GraphQLError } from 'graphql/error';\n *\n * const document = parse('{ greeting }');\n * const fieldNode = document.definitions[0].selectionSet.selections[0];\n * const error = new GraphQLError('Cannot query this field.', {\n * nodes: fieldNode,\n * path: ['greeting'],\n * extensions: { code: 'FORBIDDEN' },\n * });\n *\n * error.message; // => 'Cannot query this field.'\n * error.locations; // => [{ line: 1, column: 3 }]\n * error.path; // => ['greeting']\n * error.extensions; // => { code: 'FORBIDDEN' }\n * ```\n * @example\n * ```ts\n * // This variant derives locations from source positions and preserves the cause.\n * import { Source } from 'graphql/language';\n * import { GraphQLError } from 'graphql/error';\n *\n * const source = new Source('{ greeting }');\n * const cause = new Error('Database unavailable.');\n * const error = new GraphQLError('Resolver failed.', {\n * source,\n * positions: [2],\n * path: ['greeting'],\n * cause,\n * });\n *\n * error.locations; // => [{ line: 1, column: 3 }]\n * error.path; // => ['greeting']\n * error.cause; // => cause\n * ```\n */\n constructor(message: string, options: GraphQLErrorOptions = {}) {\n const { nodes, source, positions, path, originalError, cause, extensions } =\n options;\n\n const hasCause = 'cause' in options;\n const errorCause = hasCause ? cause : originalError;\n const errorOptions =\n hasCause || originalError != null ? { cause: errorCause } : undefined;\n super(message, errorOptions);\n\n this.name = 'GraphQLError';\n this.path = path ?? undefined;\n const underlyingError: typeof originalError =\n originalError ?? (cause instanceof Error ? cause : undefined);\n this.originalError = underlyingError;\n\n // Compute list of blame nodes.\n this.nodes = undefinedIfEmpty(\n Array.isArray(nodes) ? nodes : nodes ? [nodes] : undefined,\n );\n\n const nodeLocations = undefinedIfEmpty(\n this.nodes\n ?.map((node) => node.loc)\n .filter((loc): loc is Location => loc != null),\n );\n\n // Compute locations in the source for the given nodes/positions.\n this.source = source ?? nodeLocations?.[0]?.source;\n\n this.positions = positions ?? nodeLocations?.map((loc) => loc.start);\n\n this.locations =\n positions && source\n ? positions.map((pos) => getLocation(source, pos))\n : nodeLocations?.map((loc) => getLocation(loc.source, loc.start));\n\n const originalExtensions = isObjectLike(underlyingError?.extensions)\n ? underlyingError.extensions\n : undefined;\n this.extensions = extensions ?? originalExtensions ?? Object.create(null);\n\n // Only properties prescribed by the spec should be enumerable.\n // Keep the rest as non-enumerable.\n Object.defineProperties(this, {\n message: {\n writable: true,\n enumerable: true,\n },\n name: { enumerable: false },\n nodes: { enumerable: false },\n source: { enumerable: false },\n positions: { enumerable: false },\n originalError: { enumerable: false },\n });\n\n // Include (non-enumerable) stack trace.\n // Do not copy over the stack trace of the Error.cause, since the tooling\n // already nicely prints/reports the cause chains.\n // Preserve the copy-over behavior of the `originalError`, since users may\n // expect it to work the way it did originally.\n if (originalError?.stack != null) {\n Object.defineProperty(this, 'stack', {\n value: originalError.stack,\n writable: true,\n configurable: true,\n });\n } else if (Error.captureStackTrace != null) {\n Error.captureStackTrace(this, GraphQLError);\n // See: https://github.com/graphql/graphql-js/issues/2317\n /* node:coverage ignore next 7 */\n } else {\n Object.defineProperty(this, 'stack', {\n value: Error().stack,\n writable: true,\n configurable: true,\n });\n }\n }\n\n /**\n * Returns the value used by `Object.prototype.toString`.\n * @returns The built-in string tag for this object.\n */\n get [Symbol.toStringTag](): string {\n return 'GraphQLError';\n }\n\n /**\n * Returns this error as a human-readable message with source locations.\n * @returns The formatted error string.\n * @example\n * ```ts\n * import { Source } from 'graphql/language';\n * import { GraphQLError } from 'graphql/error';\n *\n * const error = new GraphQLError('Cannot query field \"name\".', {\n * source: new Source('{ name }'),\n * positions: [2],\n * });\n *\n * error.toString(); // => 'Cannot query field \"name\".\\n\\nGraphQL request:1:3\\n1 | { name }\\n | ^'\n * ```\n */\n override toString(): string {\n let output = this.message;\n\n if (this.nodes) {\n for (const node of this.nodes) {\n if (node.loc) {\n output += '\\n\\n' + printLocation(node.loc);\n }\n }\n } else if (this.source && this.locations) {\n for (const location of this.locations) {\n output += '\\n\\n' + printSourceLocation(this.source, location);\n }\n }\n\n return output;\n }\n\n /**\n * Returns the JSON representation used when this object is serialized.\n * @returns The JSON-serializable representation.\n * @example\n * ```ts\n * import { GraphQLError } from 'graphql/error';\n *\n * const error = new GraphQLError('Resolver failed.', {\n * path: ['viewer', 'name'],\n * extensions: { code: 'INTERNAL' },\n * });\n *\n * error.toJSON(); // => { message: 'Resolver failed.', path: ['viewer', 'name'], extensions: { code: 'INTERNAL' } }\n * ```\n */\n toJSON(): GraphQLFormattedError {\n type WritableFormattedError = {\n -readonly [P in keyof GraphQLFormattedError]: GraphQLFormattedError[P];\n };\n\n const formattedError: WritableFormattedError = {\n message: this.message,\n };\n\n if (this.locations != null) {\n formattedError.locations = this.locations;\n }\n\n if (this.path != null) {\n formattedError.path = this.path;\n }\n\n if (this.extensions != null && Object.keys(this.extensions).length > 0) {\n formattedError.extensions = this.extensions;\n }\n\n return formattedError;\n }\n}\n\nfunction undefinedIfEmpty<T>(\n array: Array<T> | undefined,\n): Array<T> | undefined {\n return array === undefined || array.length === 0 ? undefined : array;\n}\n\n/** See: https://spec.graphql.org/draft/#sec-Errors */\nexport interface GraphQLFormattedError {\n /**\n * A short, human-readable summary of the problem that **SHOULD NOT** change\n * from occurrence to occurrence of the problem, except for purposes of\n * localization.\n */\n readonly message: string;\n /**\n * If an error can be associated to a particular point in the requested\n * GraphQL document, it should contain a list of locations.\n */\n readonly locations?: ReadonlyArray<SourceLocation>;\n /**\n * If an error can be associated to a particular field in the GraphQL result,\n * it _must_ contain an entry with the key `path` that details the path of\n * the response field which experienced the error. This allows clients to\n * identify whether a null result is intentional or caused by a runtime error.\n */\n readonly path?: ReadonlyArray<string | number>;\n /**\n * Reserved for implementors to extend the protocol however they see fit,\n * and hence there are no additional restrictions on its contents.\n */\n readonly extensions?: GraphQLFormattedErrorExtensions;\n}\n"]}