Skip to content

Commit

Permalink
Handle AggregateErrors by expanding them to result errors (#6354)
Browse files Browse the repository at this point in the history
  • Loading branch information
enisdenjo authored Jul 18, 2024
1 parent 8b4930a commit 97c88a0
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 90 deletions.
5 changes: 5 additions & 0 deletions .changeset/strange-points-carry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-tools/executor-http': patch
---

Handle AggregateErrors by expanding them to result errors
201 changes: 112 additions & 89 deletions packages/executors/http/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,15 +316,18 @@ export function buildHTTPExecutor(
) {
return {
errors: [
createGraphQLError('Unexpected empty "data" and "errors" fields', {
extensions: {
requestBody: {
query,
operationName: request.operationName,
createGraphQLError(
'Unexpected empty "data" and "errors" fields in result: ' + result,
{
extensions: {
requestBody: {
query,
operationName: request.operationName,
},
responseDetails: responseDetailsForError,
},
responseDetails: responseDetailsForError,
},
}),
),
],
};
}
Expand Down Expand Up @@ -372,82 +375,30 @@ export function buildHTTPExecutor(
}
})
.catch((e: any) => {
if (typeof e === 'string') {
if (e.name === 'AggregateError') {
return {
errors: [
createGraphQLError(e, {
extensions: {
requestBody: {
query,
operationName: request.operationName,
},
responseDetails: responseDetailsForError,
},
}),
],
};
} else if (e.name === 'GraphQLError') {
return {
errors: [e],
};
} else if (e.name === 'TypeError' && e.message === 'fetch failed') {
return {
errors: [
createGraphQLError(`fetch failed to ${endpoint}`, {
extensions: {
requestBody: {
query,
operationName: request.operationName,
},
responseDetails: responseDetailsForError,
},
originalError: e,
}),
],
};
} else if (e.name === 'AbortError' && signal?.reason) {
return createResultForAbort(
signal,
{
requestBody: {
errors: e.errors.map((e: any) =>
coerceFetchError(e, {
signal,
query,
operationName: request.operationName,
},
responseDetails: responseDetailsForError,
},
e,
);
} else if (e.message) {
return {
errors: [
createGraphQLError(e.message, {
extensions: {
requestBody: {
query,
operationName: request.operationName,
},
responseDetails: responseDetailsForError,
},
originalError: e,
endpoint,
request,
responseDetailsForError,
}),
],
};
} else {
return {
errors: [
createGraphQLError('Unknown error', {
extensions: {
requestBody: {
query,
operationName: request.operationName,
},
responseDetails: responseDetailsForError,
},
originalError: e,
}),
],
),
};
}
return {
errors: [
coerceFetchError(e, {
signal,
query,
endpoint,
request,
responseDetailsForError,
}),
],
};
})
.resolve();
};
Expand Down Expand Up @@ -512,22 +463,94 @@ export function buildHTTPExecutor(
return executor;
}

function coerceFetchError(
e: any,
{
signal,
query,
endpoint,
request,
responseDetailsForError,
}: {
signal: AbortSignal | undefined;
query: string;
endpoint: string;
request: ExecutionRequest;
responseDetailsForError: {
status?: number;
statusText?: string;
};
},
) {
if (typeof e === 'string') {
return createGraphQLError(e, {
extensions: {
requestBody: {
query,
operationName: request.operationName,
},
responseDetails: responseDetailsForError,
},
});
} else if (e.name === 'GraphQLError') {
return e;
} else if (e.name === 'TypeError' && e.message === 'fetch failed') {
return createGraphQLError(`fetch failed to ${endpoint}`, {
extensions: {
requestBody: {
query,
operationName: request.operationName,
},
responseDetails: responseDetailsForError,
},
originalError: e,
});
} else if (e.name === 'AbortError' && signal?.reason) {
return createGraphQLErrorForAbort(signal, {
requestBody: {
query,
operationName: request.operationName,
},
responseDetails: responseDetailsForError,
});
} else if (e.message) {
return createGraphQLError(e.message, {
extensions: {
requestBody: {
query,
operationName: request.operationName,
},
responseDetails: responseDetailsForError,
},
originalError: e,
});
} else {
return createGraphQLError('Unknown error', {
extensions: {
requestBody: {
query,
operationName: request.operationName,
},
responseDetails: responseDetailsForError,
},
originalError: e,
});
}
}

function createAbortErrorReason() {
return new Error('Executor was disposed.');
}

function createResultForAbort(
signal: AbortSignal,
extensions?: Record<string, any>,
originalError?: Error,
) {
function createGraphQLErrorForAbort(signal: AbortSignal, extensions?: Record<string, any>) {
return createGraphQLError('The operation was aborted. reason: ' + signal.reason, {
extensions,
});
}

function createResultForAbort(signal: AbortSignal, extensions?: Record<string, any>) {
return {
errors: [
createGraphQLError('The operation was aborted. reason: ' + signal.reason, {
extensions,
originalError,
}),
],
errors: [createGraphQLErrorForAbort(signal, extensions)],
};
}

Expand Down
2 changes: 1 addition & 1 deletion packages/executors/http/tests/buildHTTPExecutor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ describe('buildHTTPExecutor', () => {
expect(result).toMatchObject({
errors: [
{
message: 'Unexpected empty "data" and "errors" fields',
message: expect.stringContaining('Unexpected empty "data" and "errors" fields'),
},
],
});
Expand Down

0 comments on commit 97c88a0

Please sign in to comment.