Skip to content

Commit 177f6e7

Browse files
s1gr1donurtemizkan
andauthored
fix(remix): Change handleError in server entry (#621)
* fix(remix): Change `handleError` in server entry * add changelog * Update the codemod. --------- Co-authored-by: Onur Temizkan <[email protected]>
1 parent 02eafb0 commit 177f6e7

File tree

3 files changed

+64
-40
lines changed

3 files changed

+64
-40
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
- fix(remix): Change `handleError` in server entry (#621)
6+
37
## 3.25.0
48

59
- feat(react-native): Add support for Expo projects (#505)

src/remix/codemods/handle-error.ts

+57-37
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,29 @@ export function instrumentHandleError(
2222
): boolean {
2323
const originalEntryServerModAST = originalEntryServerMod.$ast as Program;
2424

25-
const handleErrorFunction = originalEntryServerModAST.body.find(
26-
(node) =>
27-
node.type === 'ExportNamedDeclaration' &&
28-
node.declaration?.type === 'FunctionDeclaration' &&
29-
node.declaration.id?.name === 'handleError',
25+
const handleErrorFunctionExport = originalEntryServerModAST.body.find(
26+
(node) => {
27+
return (
28+
node.type === 'ExportNamedDeclaration' &&
29+
node.declaration?.type === 'FunctionDeclaration' &&
30+
node.declaration.id?.name === 'handleError'
31+
);
32+
},
3033
);
3134

32-
if (!handleErrorFunction) {
35+
const handleErrorFunctionVariableDeclarationExport =
36+
originalEntryServerModAST.body.find(
37+
(node) =>
38+
node.type === 'ExportNamedDeclaration' &&
39+
node.declaration?.type === 'VariableDeclaration' &&
40+
// @ts-expect-error - id should always have a name in this case
41+
node.declaration.declarations[0].id.name === 'handleError',
42+
);
43+
44+
if (
45+
!handleErrorFunctionExport &&
46+
!handleErrorFunctionVariableDeclarationExport
47+
) {
3348
clack.log.warn(
3449
`Could not find function ${chalk.cyan('handleError')} in ${chalk.cyan(
3550
serverEntryFilename,
@@ -48,50 +63,55 @@ export function instrumentHandleError(
4863
recast.types.builders.exportNamedDeclaration(implementation),
4964
);
5065
} else if (
51-
hasSentryContent(
52-
generateCode(handleErrorFunction).code,
53-
originalEntryServerMod.$code,
54-
'captureRemixServerException',
55-
)
66+
(handleErrorFunctionExport &&
67+
['wrapHandleErrorWithSentry', 'sentryHandleError'].some((util) =>
68+
hasSentryContent(
69+
generateCode(handleErrorFunctionExport).code,
70+
originalEntryServerMod.$code,
71+
util,
72+
),
73+
)) ||
74+
(handleErrorFunctionVariableDeclarationExport &&
75+
['wrapHandleErrorWithSentry', 'sentryHandleError'].some((util) =>
76+
hasSentryContent(
77+
generateCode(handleErrorFunctionVariableDeclarationExport).code,
78+
originalEntryServerMod.$code,
79+
util,
80+
),
81+
))
5682
) {
5783
return false;
58-
} else {
84+
} else if (handleErrorFunctionExport) {
5985
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
6086
const implementation = recast.parse(HANDLE_ERROR_TEMPLATE_V2).program
6187
.body[0];
6288

63-
// @ts-expect-error - string works here because the AST is proxified by magicast
89+
// If the current handleError function has a body, we need to merge the new implementation with the existing one
6490
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
65-
handleErrorFunction.declaration.body.body.unshift(
91+
implementation.declarations[0].init.arguments[0].body.body.unshift(
92+
// @ts-expect-error - declaration works here because the AST is proxified by magicast
6693
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
67-
recast.parse(HANDLE_ERROR_TEMPLATE_V2).program.body[0].body.body[0],
94+
...handleErrorFunctionExport.declaration.body.body,
6895
);
6996

70-
// First parameter is the error
71-
//
72-
// @ts-expect-error - string works here because the AST is proxified by magicast
97+
// @ts-expect-error - declaration works here because the AST is proxified by magicast
98+
handleErrorFunctionExport.declaration = implementation;
99+
} else if (handleErrorFunctionVariableDeclarationExport) {
73100
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
74-
handleErrorFunction.declaration.params[0] = implementation.params[0];
101+
const implementation = recast.parse(HANDLE_ERROR_TEMPLATE_V2).program
102+
.body[0];
75103

76-
// Second parameter is the request inside an object
77-
// Merging the object properties to make sure it includes request
78-
//
79-
// @ts-expect-error - string works here because the AST is proxified by magicast
80-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
81-
if (handleErrorFunction.declaration.params?.[1]?.properties) {
82-
// @ts-expect-error - string works here because the AST is proxified by magicast
83-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
84-
handleErrorFunction.declaration.params[1].properties.push(
85-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
86-
implementation.params[1].properties[0],
87-
);
88-
} else {
89-
// Create second parameter if it doesn't exist
90-
//
91-
// @ts-expect-error - string works here because the AST is proxified by magicast
104+
// If the current handleError function has a body, we need to merge the new implementation with the existing one
105+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
106+
implementation.declarations[0].init.arguments[0].body.body.unshift(
107+
// @ts-expect-error - declaration works here because the AST is proxified by magicast
92108
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
93-
handleErrorFunction.declaration.params[1] = implementation.params[1];
94-
}
109+
...handleErrorFunctionVariableDeclarationExport.declaration
110+
.declarations[0].init.body.body,
111+
);
112+
113+
// @ts-expect-error - declaration works here because the AST is proxified by magicast
114+
handleErrorFunctionVariableDeclarationExport.declaration = implementation;
95115
}
96116

97117
return true;

src/remix/templates.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export const ERROR_BOUNDARY_TEMPLATE_V2 = `const ErrorBoundary = () => {
55
};
66
`;
77

8-
export const HANDLE_ERROR_TEMPLATE_V2 = `function handleError(error, { request }) {
9-
Sentry.captureRemixServerException(error, 'remix.server', request, true);
10-
}
8+
export const HANDLE_ERROR_TEMPLATE_V2 = `const handleError = Sentry.wrapHandleErrorWithSentry((error, { request }) => {
9+
// Custom handleError implementation
10+
});
1111
`;

0 commit comments

Comments
 (0)