Skip to content

Commit

Permalink
Expose stacktraces from exceptions thrown in before/after hooks. (#6263)
Browse files Browse the repository at this point in the history
  • Loading branch information
timleslie authored Aug 6, 2021
1 parent b696a95 commit 94435ff
Show file tree
Hide file tree
Showing 5 changed files with 459 additions and 297 deletions.
5 changes: 5 additions & 0 deletions .changeset/little-ads-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@keystone-next/keystone': patch
---

Made the original stacktraces for before/after hooks available on `error.extension.errors`.
15 changes: 12 additions & 3 deletions packages/keystone/src/lib/core/graphql-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,18 @@ export const validationFailureError = (messages: string[]) => {
return new ApolloError(`You provided invalid data for this operation.\n${s}`);
};

export const extensionError = (extension: string, messages: string[]) => {
const s = messages.map(m => ` - ${m}`).join('\n');
return new ApolloError(`An error occured while running "${extension}".\n${s}`);
export const extensionError = (extension: string, things: { error: Error; tag: string }[]) => {
const s = things.map(t => ` - ${t.tag}: ${t.error.message}`).join('\n');
return new ApolloError(
`An error occured while running "${extension}".\n${s}`,
'INTERNAL_SERVER_ERROR',
// Make the original stack traces available in non-production modes.
// TODO: We need to have a way to make these stack traces available
// for logging in production mode.
process.env.NODE_ENV !== 'production'
? { errors: things.map(t => ({ stacktrace: t.error.stack, message: t.error.message })) }
: undefined
);
};

// FIXME: In an upcoming PR we will use these args to construct a better
Expand Down
11 changes: 5 additions & 6 deletions packages/keystone/src/lib/core/mutations/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,13 @@ export async function runSideEffectOnlyHook<
}

// Field hooks
const fieldsErrors = [];
const fieldsErrors: { error: Error; tag: string }[] = [];
for (const [fieldPath, field] of Object.entries(list.fields)) {
if (shouldRunFieldLevelHook(fieldPath)) {
try {
// @ts-ignore
await field.hooks[hookName]?.({ fieldPath, ...args });
} catch (err) {
fieldsErrors.push(`${list.listKey}.${fieldPath}: ${err.message}`);
} catch (error) {
fieldsErrors.push({ error, tag: `${list.listKey}.${fieldPath}` });
}
}
}
Expand All @@ -49,7 +48,7 @@ export async function runSideEffectOnlyHook<
// List hooks
try {
await list.hooks[hookName]?.(args);
} catch (err) {
throw extensionError(hookName, [`${list.listKey}: ${err.message}`]);
} catch (error) {
throw extensionError(hookName, [{ error, tag: list.listKey }]);
}
}
Loading

1 comment on commit 94435ff

@vercel
Copy link

@vercel vercel bot commented on 94435ff Aug 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.