Skip to content

Commit d5661a0

Browse files
committed
formatError: put all extensions inside 'extensions' property
1 parent 92cb4a0 commit d5661a0

File tree

4 files changed

+33
-8
lines changed

4 files changed

+33
-8
lines changed

src/error/GraphQLError.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ declare class GraphQLError extends Error {
8686
/**
8787
* Extension fields to add to the formatted error.
8888
*/
89-
+extensions: ?{ [key: string]: mixed };
89+
+extensions: { [key: string]: mixed } | void;
9090
}
9191

9292
export function GraphQLError( // eslint-disable-line no-redeclare
@@ -135,6 +135,9 @@ export function GraphQLError( // eslint-disable-line no-redeclare
135135
}, []);
136136
}
137137

138+
const _extensions =
139+
extensions || (originalError && (originalError: any).extensions);
140+
138141
Object.defineProperties(this, {
139142
message: {
140143
value: message,
@@ -175,7 +178,13 @@ export function GraphQLError( // eslint-disable-line no-redeclare
175178
value: originalError,
176179
},
177180
extensions: {
178-
value: extensions || (originalError && (originalError: any).extensions),
181+
// Coercing falsey values to undefined ensures they will not be included
182+
// in JSON.stringify() when not provided.
183+
value: _extensions || undefined,
184+
// By being enumerable, JSON.stringify will include `path` in the
185+
// resulting output. This ensures that the simplest possible GraphQL
186+
// service adheres to the spec.
187+
enumerable: Boolean(_extensions),
179188
},
180189
});
181190

src/error/__tests__/GraphQLError-test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ describe('GraphQLError', () => {
136136
message: 'msg',
137137
locations: undefined,
138138
path: ['path', 3, 'to', 'field'],
139+
extensions: undefined,
139140
});
140141
});
141142

@@ -148,7 +149,7 @@ describe('GraphQLError', () => {
148149
message: 'msg',
149150
locations: undefined,
150151
path: undefined,
151-
foo: 'bar',
152+
extensions: { foo: 'bar' },
152153
});
153154
});
154155
});

src/error/formatError.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,16 @@ import type { SourceLocation } from '../language/location';
1818
export function formatError(error: GraphQLError): GraphQLFormattedError {
1919
invariant(error, 'Received null or undefined error.');
2020
return {
21-
...error.extensions,
2221
message: error.message || 'An unknown error occurred.',
2322
locations: error.locations,
2423
path: error.path,
24+
extensions: error.extensions,
2525
};
2626
}
2727

28-
export type GraphQLFormattedError = {
28+
export type GraphQLFormattedError = {|
2929
+message: string,
3030
+locations: $ReadOnlyArray<SourceLocation> | void,
3131
+path: $ReadOnlyArray<string | number> | void,
32-
// Extensions
33-
+[key: string]: mixed,
34-
};
32+
+extensions: { [key: string]: mixed } | void,
33+
|};

src/execution/__tests__/executor-test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ describe('Execute: Handles basic execution tasks', () => {
382382
asyncError
383383
asyncRawError
384384
asyncReturnError
385+
asyncReturnErrorWithExtensions
385386
}`;
386387

387388
const data = {
@@ -435,6 +436,12 @@ describe('Execute: Handles basic execution tasks', () => {
435436
asyncReturnError() {
436437
return Promise.resolve(new Error('Error getting asyncReturnError'));
437438
},
439+
asyncReturnErrorWithExtensions() {
440+
const error = new Error('Error getting asyncReturnErrorWithExtensions');
441+
error.extensions = { foo: 'bar' };
442+
443+
return Promise.resolve(error);
444+
},
438445
};
439446

440447
const ast = parse(doc);
@@ -449,11 +456,13 @@ describe('Execute: Handles basic execution tasks', () => {
449456
syncReturnErrorList: { type: GraphQLList(GraphQLString) },
450457
async: { type: GraphQLString },
451458
asyncReject: { type: GraphQLString },
459+
asyncRejectWithExtensions: { type: GraphQLString },
452460
asyncRawReject: { type: GraphQLString },
453461
asyncEmptyReject: { type: GraphQLString },
454462
asyncError: { type: GraphQLString },
455463
asyncRawError: { type: GraphQLString },
456464
asyncReturnError: { type: GraphQLString },
465+
asyncReturnErrorWithExtensions: { type: GraphQLString },
457466
},
458467
}),
459468
});
@@ -474,6 +483,7 @@ describe('Execute: Handles basic execution tasks', () => {
474483
asyncError: null,
475484
asyncRawError: null,
476485
asyncReturnError: null,
486+
asyncReturnErrorWithExtensions: null,
477487
},
478488
errors: [
479489
{
@@ -531,6 +541,12 @@ describe('Execute: Handles basic execution tasks', () => {
531541
locations: [{ line: 13, column: 7 }],
532542
path: ['asyncReturnError'],
533543
},
544+
{
545+
message: 'Error getting asyncReturnErrorWithExtensions',
546+
locations: [{ line: 14, column: 7 }],
547+
path: ['asyncReturnErrorWithExtensions'],
548+
extensions: { foo: 'bar' },
549+
},
534550
],
535551
});
536552
});

0 commit comments

Comments
 (0)