Skip to content

Commit 20e783e

Browse files
committed
use the official proposal
1 parent a08dcdf commit 20e783e

File tree

5 files changed

+94
-45
lines changed

5 files changed

+94
-45
lines changed

.changeset/floppy-women-poke.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ import { normalizedExecutor } from '@graphql-tools/executor'
1616
import { parse } from 'graphql'
1717
import schema from './schema'
1818

19-
// You can also use `Symbol.for('graphql.error.schemaCoordinate')` to get the symbol if you don't
20-
// want to depend on `@graphql-tools/utils`
21-
2219
const result = await normalizedExecutor({
2320
schema,
2421
document: parse(gql`...`),
@@ -29,6 +26,7 @@ if (result.errors) {
2926
for (const error of result.errors) {
3027
console.log(
3128
'Error in resolver ',
29+
// You can also just use `error.coordinate`, but this function allows you to workaround types
3230
getSchemaCoordinate(error), ':',
3331
error.message
3432
)

packages/utils/src/errors.ts

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { locatedError as _locatedError, ASTNode, GraphQLError, Source, versionInfo } from 'graphql';
1+
import {
2+
GraphQLError as _GraphQLError,
3+
locatedError as _locatedError,
4+
ASTNode,
5+
Source,
6+
versionInfo,
7+
} from 'graphql';
28
import { Maybe } from './types.js';
39

410
interface GraphQLErrorOptions {
@@ -12,6 +18,24 @@ interface GraphQLErrorOptions {
1218
}
1319
>;
1420
extensions?: any;
21+
coordinate?: string;
22+
}
23+
24+
export class GraphQLError extends _GraphQLError {
25+
/**
26+
* Coordinate in the schema of the field which is the source of this error (`type.field`)
27+
* Note: This is an experimental RFC proposal (https://github.com/graphql/graphql-spec/pull/1200)
28+
*/
29+
coordinate?: string;
30+
31+
constructor(message: string, options?: GraphQLErrorOptions);
32+
constructor(...args: ConstructorParameters<typeof _GraphQLError>);
33+
constructor(message: string, options?: GraphQLErrorOptions | any, ...args: any[]) {
34+
super(message, options, ...args);
35+
if (options && 'coordinate' in options) {
36+
this.coordinate = options.coordinate;
37+
}
38+
}
1539
}
1640

1741
const possibleGraphQLErrorProperties = [
@@ -25,6 +49,7 @@ const possibleGraphQLErrorProperties = [
2549
'name',
2650
'stack',
2751
'extensions',
52+
'coordinate',
2853
];
2954

3055
function isGraphQLErrorLike(error: any) {
@@ -61,23 +86,20 @@ export function createGraphQLError(message: string, options?: GraphQLErrorOption
6186
}
6287

6388
type SchemaCoordinateInfo = { fieldName: string; parentType: { name: string } };
64-
export const ERROR_EXTENSION_SCHEMA_COORDINATE = Symbol.for('graphql.error.schemaCoordinate');
6589
function addSchemaCoordinateToError(error: GraphQLError, info: SchemaCoordinateInfo): void {
66-
// @ts-expect-error extensions can't be Symbol in official GraphQL Error type
67-
error.extensions[ERROR_EXTENSION_SCHEMA_COORDINATE] = `${info.parentType.name}.${info.fieldName}`;
90+
error.coordinate = `${info.parentType.name}.${info.fieldName}`;
6891
}
6992

7093
export function getSchemaCoordinate(error: GraphQLError): string | undefined {
71-
// @ts-expect-error extensions can't be Symbol in official GraphQL Error type
72-
return error.extensions[ERROR_EXTENSION_SCHEMA_COORDINATE];
94+
return error.coordinate;
7395
}
7496

7597
export function locatedError(
7698
rawError: unknown,
7799
nodes: ASTNode | ReadonlyArray<ASTNode> | undefined,
78100
path: Maybe<ReadonlyArray<string | number>>,
79101
info: SchemaCoordinateInfo | false | null | undefined,
80-
) {
102+
): GraphQLError {
81103
const error = _locatedError(rawError, nodes, path);
82104

83105
if (info) {

packages/utils/tests/createGraphQLError.test.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { ASTNode, GraphQLError, Kind, versionInfo } from 'graphql';
2+
import { createGraphQLError, locatedError, relocatedError } from '../src/errors';
3+
4+
describe('Errors', () => {
5+
describe('relocatedError', () => {
6+
it('should adjust the path of a GraphqlError', () => {
7+
const originalError = createGraphQLError('test', {
8+
path: ['test'],
9+
coordinate: 'Query.test',
10+
});
11+
const newError = relocatedError(originalError, ['test', 1, 'id'], {
12+
fieldName: 'id',
13+
parentType: { name: 'Test' },
14+
});
15+
const expectedError = createGraphQLError('test', {
16+
path: ['test', 1, 'id'],
17+
coordinate: versionInfo.major === 16 ? undefined : 'Test.id',
18+
});
19+
expect(newError).toEqual(expectedError);
20+
});
21+
});
22+
23+
describe('locatedError', () => {
24+
it('should add path, nodes and coordinate to error', () => {
25+
const originalError = createGraphQLError('test');
26+
const nodes: ASTNode[] = [{ kind: Kind.DOCUMENT, definitions: [] }];
27+
const error = locatedError(originalError, nodes, ['test'], {
28+
fieldName: 'test',
29+
parentType: { name: 'Query' },
30+
});
31+
expect(error.nodes).toBe(nodes);
32+
expect(error.path).toEqual(['test']);
33+
if (versionInfo.major !== 16) {
34+
expect(error.coordinate).toEqual('Query.test');
35+
}
36+
});
37+
});
38+
39+
describe('createGraphQLError', () => {
40+
it('should handle non Error originalError', () => {
41+
const error = createGraphQLError('message', {
42+
originalError: {
43+
message: 'originalError',
44+
extensions: { code: 'ORIGINAL_ERROR' },
45+
} as any,
46+
});
47+
expect(error.originalError).toBeInstanceOf(GraphQLError);
48+
expect(error).toMatchObject({
49+
message: 'message',
50+
originalError: {
51+
message: 'originalError',
52+
extensions: { code: 'ORIGINAL_ERROR' },
53+
},
54+
});
55+
});
56+
57+
it('should handle coordinate', () => {
58+
if (versionInfo.major !== 16) {
59+
const error = createGraphQLError('message', { coordinate: 'Query.test' });
60+
expect(error.coordinate).toBe('Query.test');
61+
}
62+
});
63+
});
64+
});

packages/utils/tests/relocatedError.test.ts

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

0 commit comments

Comments
 (0)