import { isObjectLike } from '../jsutils/isObjectLike.mjs'; import { getLocation } from '../language/location.mjs'; import { printLocation, printSourceLocation, } from '../language/printLocation.mjs'; function toNormalizedOptions(args) { const firstArg = args[0]; if (firstArg == null || 'kind' in firstArg || 'length' in firstArg) { return { nodes: firstArg, source: args[1], positions: args[2], path: args[3], originalError: args[4], extensions: args[5], }; } return firstArg; } /** * A GraphQLError describes an Error found during the parse, validate, or * execute phases of performing a GraphQL operation. In addition to a message * and stack trace, it also includes information about the locations in a * GraphQL document and/or execution result that correspond to the Error. */ export class GraphQLError extends Error { /** * An array of `{ line, column }` locations within the source GraphQL document * which correspond to this error. * * Errors during validation often contain multiple locations, for example to * point out two things with the same name. Errors during execution include a * single location, the field which produced the error. * * Enumerable, and appears in the result of JSON.stringify(). */ /** * An array describing the JSON-path into the execution response which * corresponds to this error. Only included for errors during execution. * * Enumerable, and appears in the result of JSON.stringify(). */ /** * An array of GraphQL AST Nodes corresponding to this error. */ /** * The source GraphQL document for the first location of this error. * * Note that if this Error represents more than one node, the source may not * represent nodes after the first node. */ /** * An array of character offsets within the source GraphQL document * which correspond to this error. */ /** * The original error thrown from a field resolver during execution. */ /** * Extension fields to add to the formatted error. */ /** * @deprecated Please use the `GraphQLErrorOptions` constructor overload instead. */ constructor(message, ...rawArgs) { var _this$nodes, _nodeLocations$, _ref; const { nodes, source, positions, path, originalError, extensions } = toNormalizedOptions(rawArgs); super(message); this.name = 'GraphQLError'; this.path = path !== null && path !== void 0 ? path : undefined; this.originalError = originalError !== null && originalError !== void 0 ? originalError : undefined; // Compute list of blame nodes. this.nodes = undefinedIfEmpty( Array.isArray(nodes) ? nodes : nodes ? [nodes] : undefined, ); const nodeLocations = undefinedIfEmpty( (_this$nodes = this.nodes) === null || _this$nodes === void 0 ? void 0 : _this$nodes.map((node) => node.loc).filter((loc) => loc != null), ); // Compute locations in the source for the given nodes/positions. this.source = source !== null && source !== void 0 ? source : nodeLocations === null || nodeLocations === void 0 ? void 0 : (_nodeLocations$ = nodeLocations[0]) === null || _nodeLocations$ === void 0 ? void 0 : _nodeLocations$.source; this.positions = positions !== null && positions !== void 0 ? positions : nodeLocations === null || nodeLocations === void 0 ? void 0 : nodeLocations.map((loc) => loc.start); this.locations = positions && source ? positions.map((pos) => getLocation(source, pos)) : nodeLocations === null || nodeLocations === void 0 ? void 0 : nodeLocations.map((loc) => getLocation(loc.source, loc.start)); const originalExtensions = isObjectLike( originalError === null || originalError === void 0 ? void 0 : originalError.extensions, ) ? originalError === null || originalError === void 0 ? void 0 : originalError.extensions : undefined; this.extensions = (_ref = extensions !== null && extensions !== void 0 ? extensions : originalExtensions) !== null && _ref !== void 0 ? _ref : Object.create(null); // Only properties prescribed by the spec should be enumerable. // Keep the rest as non-enumerable. Object.defineProperties(this, { message: { writable: true, enumerable: true, }, name: { enumerable: false, }, nodes: { enumerable: false, }, source: { enumerable: false, }, positions: { enumerable: false, }, originalError: { enumerable: false, }, }); // Include (non-enumerable) stack trace. /* c8 ignore start */ // FIXME: https://github.com/graphql/graphql-js/issues/2317 if ( originalError !== null && originalError !== void 0 && originalError.stack ) { Object.defineProperty(this, 'stack', { value: originalError.stack, writable: true, configurable: true, }); } else if (Error.captureStackTrace) { Error.captureStackTrace(this, GraphQLError); } else { Object.defineProperty(this, 'stack', { value: Error().stack, writable: true, configurable: true, }); } /* c8 ignore stop */ } get [Symbol.toStringTag]() { return 'GraphQLError'; } toString() { let output = this.message; if (this.nodes) { for (const node of this.nodes) { if (node.loc) { output += '\n\n' + printLocation(node.loc); } } } else if (this.source && this.locations) { for (const location of this.locations) { output += '\n\n' + printSourceLocation(this.source, location); } } return output; } toJSON() { const formattedError = { message: this.message, }; if (this.locations != null) { formattedError.locations = this.locations; } if (this.path != null) { formattedError.path = this.path; } if (this.extensions != null && Object.keys(this.extensions).length > 0) { formattedError.extensions = this.extensions; } return formattedError; } } function undefinedIfEmpty(array) { return array === undefined || array.length === 0 ? undefined : array; } /** * See: https://spec.graphql.org/draft/#sec-Errors */ /** * Prints a GraphQLError to a string, representing useful location information * about the error's position in the source. * * @deprecated Please use `error.toString` instead. Will be removed in v17 */ export function printError(error) { return error.toString(); } /** * Given a GraphQLError, format it according to the rules described by the * Response Format, Errors section of the GraphQL Specification. * * @deprecated Please use `error.toJSON` instead. Will be removed in v17 */ export function formatError(error) { return error.toJSON(); }