Skip to content

Commit

Permalink
Merge bd94cdc into 305466b
Browse files Browse the repository at this point in the history
  • Loading branch information
hwillson committed Mar 26, 2019
2 parents 305466b + bd94cdc commit c7758dd
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 9 deletions.
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "graphql-tools",
"version": "4.0.4",
"version": "5.0.0-rc.1",
"description": "Useful tools to create and manipulate GraphQL schemas.",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down
6 changes: 5 additions & 1 deletion src/stitching/defaultMergedResolver.ts
Expand Up @@ -15,7 +15,11 @@ const defaultMergedResolver: GraphQLFieldResolver<any, any> = (parent, args, con
const errorResult = getErrorsFromParent(parent, responseKey);

if (errorResult.kind === 'OWN') {
throw locatedError(new Error(errorResult.error.message), info.fieldNodes, responsePathAsArray(info.path));
throw locatedError(
errorResult.error.originalError || new Error(errorResult.error.message),
info.fieldNodes,
responsePathAsArray(info.path),
);
}

let result = parent[responseKey];
Expand Down
17 changes: 11 additions & 6 deletions src/stitching/errors.ts
Expand Up @@ -2,7 +2,6 @@ import {
GraphQLResolveInfo,
responsePathAsArray,
ExecutionResult,
GraphQLFormattedError,
GraphQLError,
} from 'graphql';
import { locatedError } from 'graphql/error';
Expand All @@ -18,7 +17,7 @@ if (
ERROR_SYMBOL = '@@__subSchemaErrors';
}

export function annotateWithChildrenErrors(object: any, childrenErrors: ReadonlyArray<GraphQLFormattedError>): any {
export function annotateWithChildrenErrors(object: any, childrenErrors: ReadonlyArray<GraphQLError>): any {
if (!childrenErrors || childrenErrors.length === 0) {
// Nothing to see here, move along
return object;
Expand All @@ -33,10 +32,16 @@ export function annotateWithChildrenErrors(object: any, childrenErrors: Readonly
}
const index = error.path[1];
const current = byIndex[index] || [];

// It's important to keep the `originalError`, to make sure
// error stacktrace's and custom `extensions` are preserved from
// source schemas, when merged.
current.push({
...error,
path: error.path.slice(1)
path: error.path.slice(1),
originalError: error.originalError,
});

byIndex[index] = current;
});

Expand All @@ -62,10 +67,10 @@ export function getErrorsFromParent(
}
| {
kind: 'CHILDREN';
errors?: Array<GraphQLFormattedError>;
errors?: Array<GraphQLError>;
} {
const errors = (object && object[ERROR_SYMBOL]) || [];
const childrenErrors: Array<GraphQLFormattedError> = [];
const childrenErrors: Array<GraphQLError> = [];

for (const error of errors) {
if (!error.path || (error.path.length === 1 && error.path[0] === fieldName)) {
Expand Down Expand Up @@ -114,7 +119,7 @@ export function checkResultAndHandleErrors(

let resultObject = result.data[responseKey];
if (result.errors) {
resultObject = annotateWithChildrenErrors(resultObject, result.errors as ReadonlyArray<GraphQLFormattedError>);
resultObject = annotateWithChildrenErrors(resultObject, result.errors as ReadonlyArray<GraphQLError>);
}
return resultObject;
}
Expand Down
32 changes: 32 additions & 0 deletions src/test/testMergeSchemas.ts
Expand Up @@ -2315,6 +2315,38 @@ fragment BookingFragment on Booking {
],
});
});

it(
'should preserve custom error extensions from the original schema, ' +
'when merging schemas',
async () => {
const propertyQuery = `
query {
properties(limit: 1) {
error
}
}
`;

const propertyResult = await graphql(
propertySchema,
propertyQuery,
);

const mergedResult = await graphql(
mergedSchema,
propertyQuery,
);

[propertyResult, mergedResult].forEach((result) => {
expect(result.errors).to.exist;
expect(result.errors.length > 0).to.be.true;
const error = result.errors[0];
expect(error.extensions).to.exist;
expect(error.extensions.code).to.equal('SOME_CUSTOM_CODE');
});
}
);
});

describe('types in schema extensions', () => {
Expand Down
6 changes: 5 additions & 1 deletion src/test/testingSchemas.ts
Expand Up @@ -407,7 +407,11 @@ const propertyResolvers: IResolvers = {

Property: {
error() {
throw new Error('Property.error error');
const error = new Error('Property.error error');
(error as any).extensions = {
code: 'SOME_CUSTOM_CODE',
};
throw error;
},
},
};
Expand Down

0 comments on commit c7758dd

Please sign in to comment.