@dangao/bun-server 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,462 @@
1
+ # Error Handling Guide
2
+
3
+ This document introduces the error handling system of Bun Server Framework,
4
+ including error code specifications, internationalization support, and best
5
+ practices.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Error Code System](#error-code-system)
10
+ - [Error Message Internationalization](#error-message-internationalization)
11
+ - [Exception Filters](#exception-filters)
12
+ - [Best Practices](#best-practices)
13
+ - [Example Code](#example-code)
14
+
15
+ ---
16
+
17
+ ## Error Code System
18
+
19
+ ### Error Code Specification
20
+
21
+ Error codes follow a unified naming convention:
22
+
23
+ - **Format**: `MODULE_ERROR_TYPE_SPECIFIC_ERROR`
24
+ - **Use uppercase letters and underscores**
25
+ - **Module prefixes**:
26
+ - `AUTH` - Authentication and authorization
27
+ - `VALIDATION` - Validation
28
+ - `DATABASE` - Database
29
+ - `FILE` - File operations
30
+ - `MIDDLEWARE` - Middleware
31
+ - `OAUTH2` - OAuth2
32
+ - `CONFIG` - Configuration
33
+
34
+ **Examples**:
35
+
36
+ - `AUTH_INVALID_TOKEN` - Invalid authentication token
37
+ - `VALIDATION_REQUIRED_FIELD` - Required field missing
38
+ - `DATABASE_CONNECTION_FAILED` - Database connection failed
39
+
40
+ ### Error Code Categories
41
+
42
+ Error codes are categorized by functional modules, each category corresponds to
43
+ a numeric range:
44
+
45
+ - **1000-1999**: General errors
46
+ - **2000-2999**: Authentication and authorization errors
47
+ - **3000-3999**: Validation errors
48
+ - **4000-4999**: OAuth2 errors
49
+ - **5000-5999**: Database errors
50
+ - **6000-6999**: File operation errors
51
+ - **7000-7999**: Middleware errors
52
+ - **8000-8999**: Configuration errors
53
+
54
+ ### Using Error Codes
55
+
56
+ ```typescript
57
+ import { ErrorCode, HttpException } from "@dangao/bun-server";
58
+
59
+ // Method 1: Use HttpException.withCode()
60
+ throw HttpException.withCode(ErrorCode.RESOURCE_NOT_FOUND);
61
+
62
+ // Method 2: Use exception class with error code
63
+ throw new NotFoundException(
64
+ "User not found",
65
+ undefined,
66
+ ErrorCode.RESOURCE_NOT_FOUND,
67
+ );
68
+
69
+ // Method 3: With custom message and details
70
+ throw HttpException.withCode(
71
+ ErrorCode.VALIDATION_FAILED,
72
+ "Custom validation message",
73
+ { field: "email", reason: "Invalid format" },
74
+ );
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Error Message Internationalization
80
+
81
+ ### Supported Languages
82
+
83
+ The framework supports the following languages:
84
+
85
+ - `en` - English (default)
86
+ - `zh-CN` - Simplified Chinese
87
+ - `ja` - Japanese (partial)
88
+ - `ko` - Korean (partial)
89
+
90
+ ### Automatic Language Detection
91
+
92
+ The framework automatically detects user language based on the HTTP
93
+ `Accept-Language` header:
94
+
95
+ ```typescript
96
+ // Request header example
97
+ Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
98
+ ```
99
+
100
+ ### Message Template System
101
+
102
+ Error messages support template parameters using `{key}` as placeholders:
103
+
104
+ ```typescript
105
+ import { ErrorCode, HttpException } from "@dangao/bun-server";
106
+
107
+ // If error message template is 'Resource {resource} not found'
108
+ throw HttpException.withCode(
109
+ ErrorCode.RESOURCE_NOT_FOUND,
110
+ undefined,
111
+ undefined,
112
+ { resource: "User" }, // Message template parameters
113
+ );
114
+ // Returns: 'Resource User not found' (English) or '资源 User 未找到' (Chinese)
115
+ ```
116
+
117
+ ### Manual Language Setting
118
+
119
+ ```typescript
120
+ import { ErrorMessageI18n } from "@dangao/bun-server";
121
+
122
+ // Set global language
123
+ ErrorMessageI18n.setLanguage("zh-CN");
124
+
125
+ // Get error message for specific language
126
+ const message = ErrorMessageI18n.getMessage(
127
+ ErrorCode.RESOURCE_NOT_FOUND,
128
+ "zh-CN",
129
+ { resource: "User" },
130
+ );
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Exception Filters
136
+
137
+ Exception filters allow you to customize error handling logic, handling specific
138
+ exception types or error codes.
139
+
140
+ ### Creating Exception Filters
141
+
142
+ ```typescript
143
+ import type { ExceptionFilter } from "@dangao/bun-server";
144
+ import type { Context } from "@dangao/bun-server";
145
+ import { ErrorCode, HttpException } from "@dangao/bun-server";
146
+
147
+ class CustomExceptionFilter implements ExceptionFilter {
148
+ public catch(error: unknown, context: Context): Response | undefined {
149
+ if (
150
+ error instanceof HttpException &&
151
+ error.code === ErrorCode.DATABASE_CONNECTION_FAILED
152
+ ) {
153
+ // Custom handling for database connection errors
154
+ context.setStatus(503);
155
+ return context.createResponse({
156
+ error: "Database service temporarily unavailable",
157
+ code: error.code,
158
+ retryAfter: 60, // Suggest retry after 60 seconds
159
+ });
160
+ }
161
+
162
+ // Return undefined to pass to next filter
163
+ return undefined;
164
+ }
165
+ }
166
+ ```
167
+
168
+ ### Registering Exception Filters
169
+
170
+ ```typescript
171
+ import { ExceptionFilterRegistry } from "@dangao/bun-server";
172
+
173
+ const registry = ExceptionFilterRegistry.getInstance();
174
+ registry.register(new CustomExceptionFilter());
175
+ ```
176
+
177
+ ### Filter Execution Order
178
+
179
+ Exception filters execute in registration order, the first filter returning a
180
+ non-`undefined` result will be used.
181
+
182
+ ---
183
+
184
+ ## Best Practices
185
+
186
+ ### 1. Use Error Codes
187
+
188
+ **Recommended** ✅:
189
+
190
+ ```typescript
191
+ throw HttpException.withCode(ErrorCode.RESOURCE_NOT_FOUND);
192
+ ```
193
+
194
+ **Not Recommended** ❌:
195
+
196
+ ```typescript
197
+ throw new Error("Resource not found");
198
+ ```
199
+
200
+ ### 2. Provide Error Details
201
+
202
+ For validation errors, provide detailed error information:
203
+
204
+ ```typescript
205
+ throw HttpException.withCode(
206
+ ErrorCode.VALIDATION_FAILED,
207
+ "Validation failed",
208
+ {
209
+ field: "email",
210
+ reason: "Invalid email format",
211
+ value: userInput.email,
212
+ },
213
+ );
214
+ ```
215
+
216
+ ### 3. Use Message Template Parameters
217
+
218
+ For error messages requiring dynamic information, use message template
219
+ parameters:
220
+
221
+ ```typescript
222
+ throw HttpException.withCode(
223
+ ErrorCode.RESOURCE_NOT_FOUND,
224
+ undefined,
225
+ undefined,
226
+ { resource: "User", id: userId },
227
+ );
228
+ ```
229
+
230
+ ### 4. Custom Exception Filters
231
+
232
+ For errors requiring special handling, use exception filters:
233
+
234
+ ```typescript
235
+ class DatabaseExceptionFilter implements ExceptionFilter {
236
+ public catch(error: unknown, context: Context): Response | undefined {
237
+ if (
238
+ error instanceof HttpException &&
239
+ error.code?.startsWith("DATABASE_")
240
+ ) {
241
+ // Unified handling for all database errors
242
+ return context.createResponse({
243
+ error: "Database error occurred",
244
+ code: error.code,
245
+ timestamp: new Date().toISOString(),
246
+ });
247
+ }
248
+ return undefined;
249
+ }
250
+ }
251
+ ```
252
+
253
+ ### 5. Production Error Handling
254
+
255
+ In production environments, avoid exposing sensitive information:
256
+
257
+ ```typescript
258
+ // Error handler automatically handles this
259
+ // In production, non-HttpException errors won't expose detailed information
260
+ if (process.env.NODE_ENV === "production") {
261
+ // Only return generic error message
262
+ return context.createResponse({
263
+ error: "Internal Server Error",
264
+ });
265
+ }
266
+ ```
267
+
268
+ ### 6. Error Logging
269
+
270
+ Log errors in exception filters:
271
+
272
+ ```typescript
273
+ class LoggingExceptionFilter implements ExceptionFilter {
274
+ public catch(error: unknown, context: Context): Response | undefined {
275
+ // Log error
276
+ console.error("Error occurred:", {
277
+ error,
278
+ path: context.getPath(),
279
+ method: context.getMethod(),
280
+ timestamp: new Date().toISOString(),
281
+ });
282
+
283
+ return undefined; // Continue to next filter
284
+ }
285
+ }
286
+ ```
287
+
288
+ ---
289
+
290
+ ## Example Code
291
+
292
+ ### Complete Error Handling Example
293
+
294
+ ```typescript
295
+ import {
296
+ Application,
297
+ type Context,
298
+ Controller,
299
+ ErrorCode,
300
+ ExceptionFilter,
301
+ ExceptionFilterRegistry,
302
+ GET,
303
+ HttpException,
304
+ Param,
305
+ } from "@dangao/bun-server";
306
+
307
+ // 1. Create custom exception filter
308
+ class ApiExceptionFilter implements ExceptionFilter {
309
+ public catch(error: unknown, context: Context): Response | undefined {
310
+ if (error instanceof HttpException) {
311
+ // Add request ID and timestamp
312
+ return context.createResponse({
313
+ error: error.message,
314
+ code: error.code,
315
+ details: error.details,
316
+ requestId: context.getHeader("x-request-id"),
317
+ timestamp: new Date().toISOString(),
318
+ });
319
+ }
320
+ return undefined;
321
+ }
322
+ }
323
+
324
+ // 2. Register exception filter
325
+ const registry = ExceptionFilterRegistry.getInstance();
326
+ registry.register(new ApiExceptionFilter());
327
+
328
+ // 3. Use error codes in controller
329
+ @Controller("/api/users")
330
+ class UserController {
331
+ @GET("/:id")
332
+ public async getUser(@Param("id") id: string) {
333
+ const userId = parseInt(id, 10);
334
+
335
+ if (isNaN(userId)) {
336
+ throw HttpException.withCode(
337
+ ErrorCode.VALIDATION_INVALID_FORMAT,
338
+ "Invalid user ID format",
339
+ { field: "id", value: id },
340
+ );
341
+ }
342
+
343
+ const user = await this.userService.findById(userId);
344
+
345
+ if (!user) {
346
+ throw HttpException.withCode(
347
+ ErrorCode.RESOURCE_NOT_FOUND,
348
+ undefined,
349
+ undefined,
350
+ { resource: "User", id: userId },
351
+ );
352
+ }
353
+
354
+ return user;
355
+ }
356
+ }
357
+
358
+ // 4. Start application
359
+ const app = new Application();
360
+ app.registerController(UserController);
361
+ app.listen();
362
+ ```
363
+
364
+ ### Database Error Handling Example
365
+
366
+ ```typescript
367
+ import { ErrorCode, HttpException } from "@dangao/bun-server";
368
+
369
+ try {
370
+ await database.query("SELECT * FROM users WHERE id = ?", [userId]);
371
+ } catch (error) {
372
+ if (error.code === "SQLITE_ERROR") {
373
+ throw HttpException.withCode(
374
+ ErrorCode.DATABASE_QUERY_FAILED,
375
+ "Failed to query user",
376
+ { sql: error.sql, params: [userId] },
377
+ );
378
+ }
379
+ throw error;
380
+ }
381
+ ```
382
+
383
+ ### Validation Error Handling Example
384
+
385
+ ```typescript
386
+ import { ErrorCode, HttpException } from "@dangao/bun-server";
387
+
388
+ if (!email || !isValidEmail(email)) {
389
+ throw HttpException.withCode(
390
+ ErrorCode.VALIDATION_INVALID_FORMAT,
391
+ "Invalid email format",
392
+ {
393
+ field: "email",
394
+ value: email,
395
+ expected: "valid email address",
396
+ },
397
+ );
398
+ }
399
+ ```
400
+
401
+ ---
402
+
403
+ ## Error Code Reference
404
+
405
+ ### General Errors (1000-1999)
406
+
407
+ - `INTERNAL_ERROR` - Internal server error
408
+ - `INVALID_REQUEST` - Invalid request
409
+ - `RESOURCE_NOT_FOUND` - Resource not found
410
+ - `METHOD_NOT_ALLOWED` - Method not allowed
411
+ - `RATE_LIMIT_EXCEEDED` - Rate limit exceeded
412
+ - `SERVICE_UNAVAILABLE` - Service unavailable
413
+ - `TIMEOUT` - Request timeout
414
+
415
+ ### Authentication and Authorization Errors (2000-2999)
416
+
417
+ - `AUTH_REQUIRED` - Authentication required
418
+ - `AUTH_INVALID_TOKEN` - Invalid authentication token
419
+ - `AUTH_TOKEN_EXPIRED` - Authentication token expired
420
+ - `AUTH_INSUFFICIENT_PERMISSIONS` - Insufficient permissions
421
+ - `AUTH_INVALID_CREDENTIALS` - Invalid credentials
422
+ - `AUTH_ACCOUNT_LOCKED` - Account locked
423
+ - `AUTH_ACCOUNT_DISABLED` - Account disabled
424
+
425
+ ### Validation Errors (3000-3999)
426
+
427
+ - `VALIDATION_FAILED` - Validation failed
428
+ - `VALIDATION_REQUIRED_FIELD` - Required field missing
429
+ - `VALIDATION_INVALID_FORMAT` - Invalid format
430
+ - `VALIDATION_OUT_OF_RANGE` - Value out of range
431
+ - `VALIDATION_TYPE_MISMATCH` - Type mismatch
432
+ - `VALIDATION_CONSTRAINT_VIOLATION` - Constraint violation
433
+
434
+ ### Database Errors (5000-5999)
435
+
436
+ - `DATABASE_CONNECTION_FAILED` - Database connection failed
437
+ - `DATABASE_QUERY_FAILED` - Database query failed
438
+ - `DATABASE_TRANSACTION_FAILED` - Database transaction failed
439
+ - `DATABASE_CONSTRAINT_VIOLATION` - Database constraint violation
440
+ - `DATABASE_TIMEOUT` - Database timeout
441
+ - `DATABASE_POOL_EXHAUSTED` - Database connection pool exhausted
442
+ - `DATABASE_MIGRATION_FAILED` - Database migration failed
443
+
444
+ ### File Operation Errors (6000-6999)
445
+
446
+ - `FILE_NOT_FOUND` - File not found
447
+ - `FILE_UPLOAD_FAILED` - File upload failed
448
+ - `FILE_DOWNLOAD_FAILED` - File download failed
449
+ - `FILE_SIZE_EXCEEDED` - File size exceeded
450
+ - `FILE_TYPE_NOT_ALLOWED` - File type not allowed
451
+ - `FILE_ACCESS_DENIED` - File access denied
452
+ - `FILE_PATH_TRAVERSAL` - Path traversal attack detected
453
+
454
+ For a complete list of error codes, refer to `src/error/error-codes.ts`.
455
+
456
+ ---
457
+
458
+ ## Related Resources
459
+
460
+ - [API Documentation](./api.md)
461
+ - [User Guide](./guide.md)
462
+ - [Best Practices](./best-practices.md)