Skip to content

Commit 1b098fd

Browse files
feat: enhance error handling documentation and improve kakao template service e2e tests
- Update error-handling-production.mdc with improved formatting and code style - Refactor kakaoTemplateService e2e tests to use Effect-based approach - Add comprehensive test cases including pagination, parallel queries, and data validation - Rename vitest.config.ts to vitest.config.mts and improve Node.js 18 compatibility - Add proper alias configurations for test modules
1 parent 30dfbfa commit 1b098fd

3 files changed

Lines changed: 440 additions & 58 deletions

File tree

.cursor/rules/error-handling-production.mdc

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
2-
description:
3-
globs:
2+
description: Reference this document when you need to add errors in specific services or handle failure processing.
43
alwaysApply: false
54
---
5+
66
# Production Error Handling and Stack Trace Optimization
77

88
This is a rule for solving the problem of long error stack traces caused by minified code in production builds.
@@ -12,6 +12,7 @@ This is a rule for solving the problem of long error stack traces caused by mini
1212
Reference: [debug/index.js](mdc:debug/index.js)
1313

1414
Due to tsup's minify option in production environments:
15+
1516
- All code is compressed into a single line
1617
- Long minified code appears in stack traces when errors occur
1718
- Debugging becomes difficult and logs become messy
@@ -33,7 +34,7 @@ export class CustomError extends Data.TaggedError('CustomError')<{
3334
// Production: Only concise messages
3435
return `${this.code}: ${this.message}`;
3536
}
36-
37+
3738
// Development: Include detailed information
3839
return `${this.code}: ${this.message}${
3940
this.context ? `\nContext: ${JSON.stringify(this.context, null, 2)}` : ''
@@ -51,12 +52,12 @@ abstract class BaseError extends Error {
5152
constructor(message: string, name: string) {
5253
super(message);
5354
this.name = name;
54-
55+
5556
// Remove this class's constructor from the stack
5657
if (Error.captureStackTrace) {
5758
Error.captureStackTrace(this, this.constructor);
5859
}
59-
60+
6061
// Simplify stack trace in production
6162
if (process.env.NODE_ENV === 'production') {
6263
this.cleanStackTrace();
@@ -77,7 +78,9 @@ abstract class BaseError extends Error {
7778
Error formatting utilizing Effect's Cause system:
7879

7980
```typescript
80-
export const formatErrorForProduction = (cause: Cause.Cause<unknown>): string => {
81+
export const formatErrorForProduction = (
82+
cause: Cause.Cause<unknown>,
83+
): string => {
8184
if (process.env.NODE_ENV === 'production') {
8285
// Production: Only top-level error messages
8386
const failure = Cause.failureOption(cause);
@@ -90,7 +93,7 @@ export const formatErrorForProduction = (cause: Cause.Cause<unknown>): string =>
9093
}
9194
return 'Unknown error occurred';
9295
}
93-
96+
9497
// Development: Full cause tree
9598
return Cause.pretty(cause);
9699
};
@@ -101,24 +104,22 @@ export const formatErrorForProduction = (cause: Cause.Cause<unknown>): string =>
101104
Apply error formatting when converting Effect to Promise:
102105

103106
```typescript
104-
export const runSafePromise = <E, A>(
105-
effect: Effect.Effect<A, E>
106-
): Promise<A> =>
107+
export const runSafePromise = <E, A>(effect: Effect.Effect<A, E>): Promise<A> =>
107108
Effect.runPromiseExit(effect).then(
108109
Exit.match({
109-
onFailure: (cause) => {
110+
onFailure: cause => {
110111
const formattedError = formatErrorForProduction(cause);
111112
const error = new Error(formattedError);
112-
113+
113114
// Remove stack trace in production
114115
if (process.env.NODE_ENV === 'production') {
115116
error.stack = undefined;
116117
}
117-
118+
118119
return Promise.reject(error);
119120
},
120-
onSuccess: (value) => Promise.resolve(value)
121-
})
121+
onSuccess: value => Promise.resolve(value),
122+
}),
122123
);
123124
```
124125

@@ -137,18 +138,18 @@ export default defineConfig(({watch}) => {
137138

138139
return {
139140
// ... existing configuration ...
140-
141+
141142
// Disable minify in debug mode
142143
minify: isProd && !enableDebug,
143-
144+
144145
// Generate source maps in debug mode
145146
sourcemap: !isProd || enableDebug,
146-
147+
147148
// Define environment variables
148149
define: {
149150
'process.env.NODE_ENV': isProd ? '"production"' : '"development"',
150-
'process.env.EFFECT_DEBUG': enableDebug ? '"true"' : '"false"'
151-
}
151+
'process.env.EFFECT_DEBUG': enableDebug ? '"true"' : '"false"',
152+
},
152153
};
153154
});
154155
```
@@ -238,7 +239,7 @@ send(messages: RequestSendMessagesSchema): Promise<DetailGroupMessageResponse> {
238239
)
239240
);
240241
}
241-
242+
242243
// ... rest of the logic
243244
});
244245

@@ -261,7 +262,7 @@ export class KakaoVariableError extends Data.TaggedError('KakaoVariableError')<{
261262
if (process.env.NODE_ENV === 'production') {
262263
return `KakaoVariableError: Invalid variable names detected`;
263264
}
264-
265+
265266
const variableList = this.invalidVariables.map(v => `\`${v}\``).join(', ');
266267
return `KakaoVariableError: Variable names ${variableList} cannot contain dots(.). Please use underscores(_) or other characters.`;
267268
}
@@ -282,7 +283,7 @@ const logError = (error: unknown, context: Record<string, unknown> = {}) => {
282283
level: 'error',
283284
message: formatErrorForProduction(error),
284285
timestamp: new Date().toISOString(),
285-
...context
286+
...context,
286287
});
287288
} else {
288289
// Development: Detailed information
@@ -291,7 +292,7 @@ const logError = (error: unknown, context: Record<string, unknown> = {}) => {
291292
error: error,
292293
stack: error instanceof Error ? error.stack : undefined,
293294
context,
294-
timestamp: new Date().toISOString()
295+
timestamp: new Date().toISOString(),
295296
});
296297
}
297298
};

0 commit comments

Comments
 (0)