Skip to content

Commit 8423d33

Browse files
Deprecate 'formatError' and added 'GraphQLError.toJSON' instead (#3259)
1 parent da685ee commit 8423d33

File tree

6 files changed

+101
-115
lines changed

6 files changed

+101
-115
lines changed

src/error/GraphQLError.ts

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,64 @@ export class GraphQLError extends Error {
215215
return output;
216216
}
217217

218-
// FIXME: workaround to not break chai comparisons, should be remove in v16
218+
toJSON(): GraphQLFormattedError {
219+
type WritableFormattedError = {
220+
-readonly [P in keyof GraphQLFormattedError]: GraphQLFormattedError[P];
221+
};
222+
223+
const formattedError: WritableFormattedError = {
224+
message: this.message,
225+
};
226+
227+
if (this.locations != null) {
228+
formattedError.locations = this.locations;
229+
}
230+
231+
if (this.path != null) {
232+
formattedError.path = this.path;
233+
}
234+
235+
if (this.extensions != null) {
236+
formattedError.extensions = this.extensions;
237+
}
238+
239+
return formattedError;
240+
}
241+
219242
get [Symbol.toStringTag](): string {
220243
return 'Object';
221244
}
222245
}
223246

247+
/**
248+
* See: https://spec.graphql.org/draft/#sec-Errors
249+
*/
250+
export interface GraphQLFormattedError {
251+
/**
252+
* A short, human-readable summary of the problem that **SHOULD NOT** change
253+
* from occurrence to occurrence of the problem, except for purposes of
254+
* localization.
255+
*/
256+
readonly message: string;
257+
/**
258+
* If an error can be associated to a particular point in the requested
259+
* GraphQL document, it should contain a list of locations.
260+
*/
261+
readonly locations?: ReadonlyArray<SourceLocation>;
262+
/**
263+
* If an error can be associated to a particular field in the GraphQL result,
264+
* it _must_ contain an entry with the key `path` that details the path of
265+
* the response field which experienced the error. This allows clients to
266+
* identify whether a null result is intentional or caused by a runtime error.
267+
*/
268+
readonly path?: ReadonlyArray<string | number>;
269+
/**
270+
* Reserved for implementors to extend the protocol however they see fit,
271+
* and hence there are no additional restrictions on its contents.
272+
*/
273+
readonly extensions?: { [key: string]: unknown };
274+
}
275+
224276
/**
225277
* Prints a GraphQLError to a string, representing useful location information
226278
* about the error's position in the source.
@@ -230,3 +282,13 @@ export class GraphQLError extends Error {
230282
export function printError(error: GraphQLError): string {
231283
return error.toString();
232284
}
285+
286+
/**
287+
* Given a GraphQLError, format it according to the rules described by the
288+
* Response Format, Errors section of the GraphQL Specification.
289+
*
290+
* @deprecated Please use `error.toString` instead. Will be removed in v17
291+
*/
292+
export function formatError(error: GraphQLError): GraphQLFormattedError {
293+
return error.toJSON();
294+
}

src/error/__tests__/GraphQLError-test.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Kind } from '../../language/kinds';
99
import { parse } from '../../language/parser';
1010
import { Source } from '../../language/source';
1111

12-
import { GraphQLError, printError } from '../GraphQLError';
12+
import { GraphQLError, printError, formatError } from '../GraphQLError';
1313

1414
const source = new Source(dedent`
1515
{
@@ -204,3 +204,37 @@ describe('toString', () => {
204204
`);
205205
});
206206
});
207+
208+
describe('toJSON', () => {
209+
it('Deprecated: format an error using formatError', () => {
210+
const error = new GraphQLError('Example Error');
211+
expect(formatError(error)).to.deep.equal({
212+
message: 'Example Error',
213+
});
214+
});
215+
216+
it('includes path', () => {
217+
const error = new GraphQLError('msg', null, null, null, [
218+
'path',
219+
3,
220+
'to',
221+
'field',
222+
]);
223+
224+
expect(error.toJSON()).to.deep.equal({
225+
message: 'msg',
226+
path: ['path', 3, 'to', 'field'],
227+
});
228+
});
229+
230+
it('includes extension fields', () => {
231+
const error = new GraphQLError('msg', null, null, null, null, null, {
232+
foo: 'bar',
233+
});
234+
235+
expect(error.toJSON()).to.deep.equal({
236+
message: 'msg',
237+
extensions: { foo: 'bar' },
238+
});
239+
});
240+
});

src/error/__tests__/formatError-test.ts

Lines changed: 0 additions & 58 deletions
This file was deleted.

src/error/formatError.ts

Lines changed: 0 additions & 50 deletions
This file was deleted.

src/error/index.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
export { GraphQLError, printError } from './GraphQLError';
1+
export { GraphQLError, printError, formatError } from './GraphQLError';
2+
export type { GraphQLFormattedError } from './GraphQLError';
23

34
export { syntaxError } from './syntaxError';
45

56
export { locatedError } from './locatedError';
6-
7-
export { formatError } from './formatError';
8-
export type { GraphQLFormattedError } from './formatError';

src/execution/execute.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { promiseForObject } from '../jsutils/promiseForObject';
1313
import { addPath, pathToArray } from '../jsutils/Path';
1414
import { isIterableObject } from '../jsutils/isIterableObject';
1515

16-
import type { GraphQLFormattedError } from '../error/formatError';
16+
import type { GraphQLFormattedError } from '../error/GraphQLError';
1717
import { GraphQLError } from '../error/GraphQLError';
1818
import { locatedError } from '../error/locatedError';
1919

0 commit comments

Comments
 (0)