graphql

Search for an npm package
/** @category Errors */
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.
*/
/** Original error that caused this GraphQLError, if one exists. */
/** Extension fields to add to the formatted error. */
/**
* Creates a GraphQLError instance.
* @param message - Human-readable error message.
* @param options - Error metadata such as source locations, response path, original error, and extensions.
* This positional-arguments constructor overload is deprecated. Use the
* `GraphQLError(message, options)` overload instead.
* @example
* ```ts
* // Create an error from AST nodes and response metadata.
* import { parse } from 'graphql/language';
* import { GraphQLError } from 'graphql/error';
*
* const document = parse('{ greeting }');
* const fieldNode = document.definitions[0].selectionSet.selections[0];
* const error = new GraphQLError('Cannot query this field.', {
* nodes: fieldNode,
* path: ['greeting'],
* extensions: { code: 'FORBIDDEN' },
* });
*
* error.message; // => 'Cannot query this field.'
* error.locations; // => [{ line: 1, column: 3 }]
* error.path; // => ['greeting']
* error.extensions; // => { code: 'FORBIDDEN' }
* ```
* @example
* ```ts
* // This variant derives locations from source positions and preserves the original error.
* import { Source } from 'graphql/language';
* import { GraphQLError } from 'graphql/error';
*
* const source = new Source('{ greeting }');
* const originalError = new Error('Database unavailable.');
* const error = new GraphQLError('Resolver failed.', {
* source,
* positions: [2],
* path: ['greeting'],
* originalError,
* });
*
* error.locations; // => [{ line: 1, column: 3 }]
* error.path; // => ['greeting']
* error.originalError; // => originalError
* ```
*/
/**
* Creates a GraphQLError instance using the legacy positional constructor.
* This deprecated overload will be removed in v17. Prefer the
* `GraphQLErrorOptions` object overload, which keeps optional error metadata
* in a single options bag.
* @param message - Human-readable error message.
* @param nodes - AST node or nodes associated with this error.
* @param source - Source document used to derive error locations.
* @param positions - Character offsets in the source document associated with
* this error.
* @param path - Response path where this error occurred during execution.
* @param originalError - Original error that caused this GraphQLError, if one
* exists.
* @param extensions - Extension fields to include in the formatted error.
* @example
* ```ts
* import { Source } from 'graphql/language';
* import { GraphQLError } from 'graphql/error';
*
* const source = new Source('{ greeting }');
* const originalError = new Error('Database unavailable.');
* const error = new GraphQLError(
* 'Resolver failed.',
* undefined,
* source,
* [2],
* ['greeting'],
* originalError,
* { code: 'INTERNAL' },
* );
*
* error.locations; // => [{ line: 1, column: 3 }]
* error.path; // => ['greeting']
* error.originalError; // => originalError
* error.extensions; // => { code: 'INTERNAL' }
* ```
* @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 */
}
/**
* Returns the value used by `Object.prototype.toString`.
* @returns The built-in string tag for this object.
*/
get [Symbol.toStringTag]() {
return 'GraphQLError';
}
/**
* Returns this error as a human-readable message with source locations.
* @returns The formatted error string.
* @example
* ```ts
* import { Source } from 'graphql/language';
* import { GraphQLError } from 'graphql/error';
*
* const error = new GraphQLError('Cannot query field "name".', {
* source: new Source('{ name }'),
* positions: [2],
* });
*
* error.toString(); // => 'Cannot query field "name".\n\nGraphQL request:1:3\n1 | { name }\n | ^'
* ```
*/
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;
}
/**
* Returns the JSON representation used when this object is serialized.
* @returns The JSON-serializable representation.
* @example
* ```ts
* import { GraphQLError } from 'graphql/error';
*
* const error = new GraphQLError('Resolver failed.', {
* path: ['viewer', 'name'],
* extensions: { code: 'INTERNAL' },
* });
*
* error.toJSON(); // => { message: 'Resolver failed.', path: ['viewer', 'name'], extensions: { code: 'INTERNAL' } }
* ```
*/
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. This deprecated helper is retained
* for backwards compatibility; call `error.toString()` instead because
* printError will be removed in v17.
* @param error - The error to format.
* @returns The printed string representation.
* @example
* ```ts
* import { GraphQLError, printError } from 'graphql/error';
*
* const message = printError(new GraphQLError('Example error'));
*
* message; // => 'Example error'
* ```
* @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. This deprecated
* helper is retained for backwards compatibility; call `error.toJSON()`
* instead because formatError will be removed in v17.
* @param error - The error to format.
* @returns The JSON-serializable formatted error.
* @example
* ```ts
* import { GraphQLError, formatError } from 'graphql/error';
*
* const formatted = formatError(new GraphQLError('Example error'));
*
* formatted; // => { message: 'Example error' }
* ```
* @deprecated Please use `error.toJSON` instead. Will be removed in v17
*/
export function formatError(error) {
return error.toJSON();
}