@bombillazo/error-x 0.3.0 → 0.4.1

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.
package/dist/index.d.ts CHANGED
@@ -2,167 +2,22 @@
2
2
  * Metadata object containing additional context information for an error.
3
3
  * Can store any key-value pairs to provide extra debugging or business context.
4
4
  *
5
- * @example
5
+ * Users can use metadata to store application-specific behavior instructions if needed:
6
6
  * ```typescript
7
- * const metadata: ErrorMetadata = {
7
+ * const metadata = {
8
8
  * userId: 123,
9
9
  * operation: 'fetchUser',
10
- * retryCount: 3
11
- * }
12
- * ```
13
- *
14
- * @public
15
- */
16
- type ErrorMetadata = Record<string, any>;
17
- /**
18
- * Predefined display targets for error notifications and UI feedback.
19
- * These enum values provide consistent, type-safe options for where errors should be displayed.
20
- *
21
- * @public
22
- */
23
- declare enum HandlingTargets {
24
- MODAL = "modal",
25
- TOAST = "toast",
26
- INLINE = "inline",
27
- BANNER = "banner",
28
- CONSOLE = "console",
29
- LOGGER = "logger",
30
- NOTIFICATION = "notification"
31
- }
32
- /**
33
- * Display target type that allows both predefined enum values and custom strings.
34
- * This enables flexibility for custom UI components while providing standard options.
35
- *
36
- * @example
37
- * ```typescript
38
- * // Using predefined enum values
39
- * targets: [HandlingTargets.MODAL, HandlingTargets.TOAST]
40
- *
41
- * // Using custom strings
42
- * targets: ['custom-sidebar', 'my-notification-center']
43
- *
44
- * // Mixing both
45
- * targets: [HandlingTargets.MODAL, 'custom-popup', HandlingTargets.CONSOLE]
46
- * ```
47
- *
48
- * @public
49
- */
50
- type HandlingTarget = HandlingTargets | string;
51
- /**
52
- * Action to display notifications in specified UI targets.
53
- * Used to notify applications to handle error messages through the indicated display mechanisms.
54
- *
55
- * @example
56
- * ```typescript
57
- * {
58
- * action: 'notify',
59
- * payload: {
60
- * targets: [HandlingTargets.TOAST, 'custom-sidebar'],
61
- * title: 'Error occurred',
62
- * duration: 5000
63
- * }
64
- * }
65
- * ```
66
- *
67
- * @public
68
- */
69
- type NotifyAction = {
70
- action: 'notify';
71
- payload: {
72
- targets: HandlingTarget[];
73
- [key: string]: any;
74
- };
75
- };
76
- /**
77
- * Action to log out the current user when an error occurs.
78
- * Useful for authentication errors or session expiration.
79
- *
80
- * @example
81
- * ```typescript
82
- * {
83
- * action: 'logout',
84
- * payload: {
85
- * clearStorage: true,
86
- * redirectURL: '/login'
87
- * }
88
- * }
89
- * ```
90
- *
91
- * @public
92
- */
93
- type LogoutAction = {
94
- action: 'logout';
95
- payload?: {
96
- [key: string]: any;
97
- };
98
- };
99
- /**
100
- * Action to redirect the user to a different URL when an error occurs.
101
- * Commonly used for navigation after authentication errors or access denied scenarios.
102
- *
103
- * @example
104
- * ```typescript
105
- * {
106
- * action: 'redirect',
107
- * payload: {
108
- * redirectURL: '/login',
109
- * delay: 2000,
110
- * replace: true,
111
- * }
112
- * }
113
- * ```
114
- *
115
- * @public
116
- */
117
- type RedirectAction = {
118
- action: 'redirect';
119
- payload: {
120
- redirectURL: string;
121
- [key: string]: any;
122
- };
123
- };
124
- /**
125
- * Custom action type for application-specific actions.
126
- * This type is essential for proper TypeScript discrimination in the ErrorAction union.
127
- * Without this, TypeScript cannot properly distinguish between predefined and custom actions.
128
- *
129
- * @example
130
- * ```typescript
131
- * {
132
- * action: 'custom',
133
- * payload: {
134
- * type: 'analytics',
135
- * event: 'error_occurred',
136
- * category: 'authentication',
137
- * severity: 'high'
138
- * }
139
- * }
140
- *
141
- * {
142
- * action: 'custom',
143
- * payload: {
144
- * type: 'show-modal',
145
- * modalId: 'error-modal',
146
- * title: 'Error',
147
- * message: 'Something went wrong'
148
- * }
10
+ * retryCount: 3,
11
+ * // Application-specific behavior can be stored here:
12
+ * shouldNotify: true,
13
+ * notifyTargets: ['toast', 'banner'],
14
+ * redirectTo: '/login'
149
15
  * }
150
16
  * ```
151
17
  *
152
18
  * @public
153
19
  */
154
- type CustomAction = {
155
- action: 'custom';
156
- payload?: Record<string, any>;
157
- };
158
- /**
159
- * Union type of all possible error actions.
160
- * Includes predefined actions (NotifyAction, LogoutAction, RedirectAction)
161
- * and CustomAction for application-specific actions.
162
- *
163
- * @public
164
- */
165
- type ErrorAction = NotifyAction | LogoutAction | RedirectAction | CustomAction;
20
+ type ErrorXMetadata = Record<string, unknown>;
166
21
  /**
167
22
  * Configuration options for creating an ErrorX instance.
168
23
  * All properties are optional with sensible defaults.
@@ -178,6 +33,10 @@ type ErrorAction = NotifyAction | LogoutAction | RedirectAction | CustomAction;
178
33
  * // ✅ Works - object literal
179
34
  * const opts = { message: 'Error' }
180
35
  * new ErrorX(opts)
36
+ *
37
+ * // ✅ Works - with type-safe metadata
38
+ * type MyMeta = { userId: number; action: string };
39
+ * new ErrorX<MyMeta>({ metadata: { userId: 123, action: 'login' } })
181
40
  * ```
182
41
  *
183
42
  * If ErrorXOptions were a class, you would need to instantiate it:
@@ -192,25 +51,43 @@ type ErrorAction = NotifyAction | LogoutAction | RedirectAction | CustomAction;
192
51
  *
193
52
  * @public
194
53
  */
195
- type ErrorXOptions = {
54
+ type ErrorXOptions<TMetadata extends ErrorXMetadata = ErrorXMetadata> = {
196
55
  /** Technical error message (default: 'An error occurred') */
197
56
  message?: string;
198
57
  /** Error type/name (default: 'Error') */
199
58
  name?: string;
200
59
  /** Error identifier code (auto-generated from name if not provided) */
201
60
  code?: string | number;
202
- /** User-friendly message for UI display (default: undefined) */
61
+ /** User-friendly message for UI display */
203
62
  uiMessage?: string | undefined;
204
- /** Original error that caused this error (preserves error chain) */
205
- cause?: Error | unknown;
206
- /** Additional context and debugging information (default: undefined) */
207
- metadata?: ErrorMetadata;
208
- /** Actions to perform when this error occurs (default: undefined) */
209
- actions?: ErrorAction[];
210
- /** HTTP status code (100-599) for HTTP-related errors (default: undefined) */
63
+ /** Original error that caused this error (preserves error chain, will be converted to ErrorXCause format) */
64
+ cause?: ErrorXCause | Error | unknown;
65
+ /** Additional context and debugging information */
66
+ metadata?: TMetadata | undefined;
67
+ /** HTTP status code (100-599) for HTTP-related errors */
211
68
  httpStatus?: number | undefined;
212
69
  /** Error type for categorization */
213
70
  type?: string | undefined;
71
+ /** Source URL related to the error (API endpoint, page URL, resource URL) */
72
+ sourceUrl?: string | undefined;
73
+ /** Documentation URL for this specific error */
74
+ docsUrl?: string | undefined;
75
+ /** Where the error originated (service name, module, component) */
76
+ source?: string | undefined;
77
+ };
78
+ /**
79
+ * Simplified representation of an error cause for serialization.
80
+ * Used to store error chain information without circular references.
81
+ *
82
+ * @public
83
+ */
84
+ type ErrorXCause = {
85
+ /** Error message */
86
+ message: string;
87
+ /** Error name (optional) */
88
+ name?: string;
89
+ /** Stack trace (optional) */
90
+ stack?: string;
214
91
  };
215
92
  /**
216
93
  * JSON-serializable representation of an ErrorX instance.
@@ -226,21 +103,20 @@ type ErrorXOptions = {
226
103
  * stack: 'Error: Authentication failed.\n at login (auth.ts:42:15)',
227
104
  * metadata: { userId: 123, loginAttempt: 3 },
228
105
  * timestamp: '2024-01-15T10:30:45.123Z',
229
- * actions: [
230
- * { action: 'logout', payload: { clearStorage: true } }
231
- * ],
232
106
  * cause: {
233
107
  * name: 'NetworkError',
234
108
  * message: 'Request timeout.',
235
- * code: 'NETWORK_TIMEOUT',
236
- * // ... other error properties
237
- * }
109
+ * stack: '...'
110
+ * },
111
+ * sourceUrl: 'https://api.example.com/auth',
112
+ * docsUrl: 'https://docs.example.com/errors#auth-failed',
113
+ * source: 'auth-service'
238
114
  * }
239
115
  * ```
240
116
  *
241
117
  * @public
242
118
  */
243
- type SerializableError = {
119
+ type ErrorXSerialized = {
244
120
  /** Error type/name */
245
121
  name: string;
246
122
  /** Technical error message */
@@ -252,24 +128,58 @@ type SerializableError = {
252
128
  /** Stack trace (optional) */
253
129
  stack?: string;
254
130
  /** Additional context and debugging information */
255
- metadata: ErrorMetadata | undefined;
131
+ metadata: ErrorXMetadata | undefined;
256
132
  /** ISO timestamp when error was created */
257
133
  timestamp: string;
258
- /** Actions to perform when this error occurs */
259
- actions?: ErrorAction[];
260
- /** Serialized cause error (for error chaining) */
261
- cause?: SerializableError;
134
+ /** Simplified cause error (for error chaining) */
135
+ cause?: ErrorXCause;
262
136
  /** HTTP status code for HTTP-related errors */
263
137
  httpStatus?: number;
264
138
  /** Error type for categorization */
265
139
  type?: string;
140
+ /** Source URL related to the error */
141
+ sourceUrl?: string;
142
+ /** Documentation URL for this error */
143
+ docsUrl?: string;
144
+ /** Where the error originated */
145
+ source?: string;
266
146
  };
267
147
 
148
+ /**
149
+ * Configuration interface for ErrorX global settings
150
+ *
151
+ * @public
152
+ */
153
+ interface ErrorXConfig {
154
+ /** Default source identifier for all errors (e.g., service name, module name) */
155
+ source?: string;
156
+ /** Base URL for error documentation */
157
+ docsBaseURL?: string;
158
+ /** Mapping of error codes to documentation paths */
159
+ docsMap?: Record<string, string>;
160
+ /**
161
+ * Control stack trace cleaning behavior
162
+ * - true: Enable automatic stack trace cleaning (default)
163
+ * - false: Disable stack trace cleaning entirely
164
+ * - string[]: Custom patterns to match and remove from stack traces
165
+ */
166
+ cleanStack?: boolean | string[];
167
+ }
268
168
  /**
269
169
  * Enhanced Error class with rich metadata, type-safe error handling, and intelligent error conversion.
270
170
  *
271
171
  * @example
272
172
  * ```typescript
173
+ * // Configure globally (optional)
174
+ * ErrorX.configure({
175
+ * source: 'my-service',
176
+ * docsBaseURL: 'https://docs.example.com',
177
+ * docsMap: {
178
+ * 'AUTH_FAILED': 'errors/authentication',
179
+ * 'DB_ERROR': 'errors/database'
180
+ * }
181
+ * })
182
+ *
273
183
  * // Basic usage
274
184
  * const error = new ErrorX({ message: 'Database connection failed' })
275
185
  *
@@ -281,68 +191,111 @@ type SerializableError = {
281
191
  * uiMessage: 'Please check your credentials',
282
192
  * metadata: { userId: 123, loginAttempt: 3 }
283
193
  * })
194
+ *
195
+ * // With type-safe metadata
196
+ * type MyMetadata = { userId: number; action: string };
197
+ * const error = new ErrorX<MyMetadata>({
198
+ * message: 'Action failed',
199
+ * metadata: { userId: 123, action: 'delete' }
200
+ * })
201
+ * // error.metadata?.userId is typed as number
284
202
  * ```
285
203
  *
286
204
  * @public
287
205
  */
288
- declare class ErrorX extends Error {
206
+ declare class ErrorX<TMetadata extends ErrorXMetadata = ErrorXMetadata> extends Error {
207
+ /** Global configuration for all ErrorX instances */
208
+ private static _config;
289
209
  /** Error identifier code, auto-generated from name if not provided */
290
- readonly code: string;
210
+ code: string;
291
211
  /** User-friendly message suitable for display in UI */
292
- readonly uiMessage: string | undefined;
212
+ uiMessage: string | undefined;
293
213
  /** Additional context and metadata associated with the error */
294
- readonly metadata: ErrorMetadata | undefined;
214
+ metadata: TMetadata | undefined;
295
215
  /** Timestamp when the error was created */
296
- readonly timestamp: Date;
297
- /** Error actions for UI behavior and handling */
298
- readonly actions: ErrorAction[] | undefined;
216
+ timestamp: Date;
299
217
  /** HTTP status code (100-599) for HTTP-related errors */
300
- readonly httpStatus: number | undefined;
218
+ httpStatus: number | undefined;
301
219
  /** Error type for categorization */
302
- readonly type: string | undefined;
220
+ type: string | undefined;
221
+ /** Source URL related to the error (API endpoint, page URL, resource URL) */
222
+ sourceUrl: string | undefined;
223
+ /** Documentation URL for this specific error */
224
+ docsUrl: string | undefined;
225
+ /** Where the error originated (service name, module, component) */
226
+ source: string | undefined;
227
+ /** Original error that caused this error (preserves error chain) */
228
+ cause: ErrorXCause | undefined;
303
229
  /**
304
230
  * Creates a new ErrorX instance with enhanced error handling capabilities.
305
231
  *
306
- * @param messageOrOptions - Error message string, ErrorXOptions object, or any value to convert to ErrorX
307
- * @param additionalOptions - Additional options when first parameter is a string (optional)
232
+ * @param messageOrOptions - Error message string or ErrorXOptions object (optional)
308
233
  *
309
234
  * @example
310
235
  * ```typescript
236
+ * // Create with default message
237
+ * const error1 = new ErrorX()
238
+ *
311
239
  * // Create with string message only
312
- * const error1 = new ErrorX('Database query failed')
240
+ * const error2 = new ErrorX('Database query failed')
313
241
  *
314
- * // Create with string message and additional options
315
- * const error2 = new ErrorX('Database query failed', {
242
+ * // Create with options object
243
+ * const error3 = new ErrorX({
244
+ * message: 'Database query failed',
316
245
  * name: 'DatabaseError',
317
246
  * code: 'DB_QUERY_FAILED',
318
247
  * uiMessage: 'Unable to load data. Please try again.',
319
248
  * metadata: { query: 'SELECT * FROM users', timeout: 5000 }
320
249
  * })
321
250
  *
322
- * // Create with options object (backward compatible)
323
- * const error3 = new ErrorX({
324
- * message: 'Database query failed',
325
- * name: 'DatabaseError',
326
- * code: 'DB_QUERY_FAILED',
327
- * actions: [
328
- * { action: 'notify', payload: { targets: [HandlingTargets.TOAST] } }
329
- * ]
251
+ * // With type-safe metadata
252
+ * type MyMeta = { userId: number };
253
+ * const error4 = new ErrorX<MyMeta>({
254
+ * message: 'User action failed',
255
+ * metadata: { userId: 123 }
330
256
  * })
331
257
  *
332
- * // Create with unknown input (smart conversion)
258
+ * // For converting unknown errors, use ErrorX.from()
333
259
  * const apiError = { message: 'User not found', code: 404 }
334
- * const error4 = new ErrorX(apiError)
335
- *
336
- * // Create with no options (uses defaults)
337
- * const error5 = new ErrorX()
260
+ * const error5 = ErrorX.from(apiError)
338
261
  * ```
339
262
  */
340
- constructor(messageOrOptions?: string | ErrorXOptions | unknown, additionalOptions?: Partial<ErrorXOptions>);
263
+ constructor(messageOrOptions?: string | ErrorXOptions<TMetadata>);
341
264
  /**
342
265
  * Returns the default error name.
343
266
  * @returns Default error name 'Error'
344
267
  */
345
268
  private static getDefaultName;
269
+ /**
270
+ * Converts any value to ErrorXCause format.
271
+ * @param value - Value to convert to ErrorXCause
272
+ * @returns ErrorXCause object or undefined if value is null/undefined
273
+ */
274
+ private static toErrorXCause;
275
+ /**
276
+ * Configure global ErrorX settings.
277
+ * This method allows you to set defaults for all ErrorX instances.
278
+ *
279
+ * @param config - Configuration object
280
+ *
281
+ * @example
282
+ * ```typescript
283
+ * ErrorX.configure({
284
+ * source: 'my-api-service',
285
+ * docsBaseURL: 'https://docs.example.com/errors',
286
+ * docsMap: {
287
+ * 'AUTH_FAILED': 'authentication-errors',
288
+ * 'DB_ERROR': 'database-errors'
289
+ * }
290
+ * })
291
+ * ```
292
+ */
293
+ static configure(config: ErrorXConfig): void;
294
+ /**
295
+ * Get the current global configuration.
296
+ * Returns null if no configuration has been set.
297
+ */
298
+ static getConfig(): ErrorXConfig | null;
346
299
  /**
347
300
  * Validates HTTP status code to ensure it's within valid range (100-599)
348
301
  *
@@ -382,13 +335,13 @@ declare class ErrorX extends Error {
382
335
  private static generateDefaultCode;
383
336
  /**
384
337
  * Preserves the original error's stack trace while updating the error message.
385
- * Combines the new error's message with the original error's stack trace.
338
+ * Combines the new error's message with the original error's stack trace from ErrorXCause.
386
339
  *
387
- * @param originalError - The original error whose stack to preserve
340
+ * @param cause - The ErrorXCause containing the original stack to preserve
388
341
  * @param newError - The new error whose message to use
389
342
  * @returns Combined stack trace with new error message and original stack
390
343
  */
391
- private static preserveOriginalStack;
344
+ private static preserveOriginalStackFromCause;
392
345
  /**
393
346
  * Cleans the stack trace by removing ErrorX internal method calls.
394
347
  * This provides cleaner stack traces that focus on user code.
@@ -412,21 +365,6 @@ declare class ErrorX extends Error {
412
365
  * ```
413
366
  */
414
367
  private static processErrorStack;
415
- /**
416
- * Formats error messages with proper capitalization and punctuation.
417
- * Ensures consistent message formatting across all ErrorX instances.
418
- *
419
- * @param message - Raw error message to format (optional)
420
- * @returns Formatted message with proper capitalization and punctuation
421
- *
422
- * @example
423
- * ```typescript
424
- * formatMessage('database connection failed') // 'Database connection failed.'
425
- * formatMessage('user not found. please check credentials') // 'User not found. Please check credentials.'
426
- * formatMessage() // 'An error occurred'
427
- * ```
428
- */
429
- private static formatMessage;
430
368
  /**
431
369
  * Creates a new ErrorX instance with additional metadata merged with existing metadata.
432
370
  * The original error properties are preserved while extending the metadata.
@@ -448,7 +386,7 @@ declare class ErrorX extends Error {
448
386
  * // Result: metadata = { endpoint: '/users', retryCount: 3, userId: 123 }
449
387
  * ```
450
388
  */
451
- withMetadata(additionalMetadata: ErrorMetadata): ErrorX;
389
+ withMetadata(additionalMetadata: Partial<TMetadata>): ErrorX<TMetadata>;
452
390
  /**
453
391
  * Type guard that checks if a value is an ErrorX instance.
454
392
  *
@@ -467,7 +405,7 @@ declare class ErrorX extends Error {
467
405
  * }
468
406
  * ```
469
407
  */
470
- static isErrorX(value: unknown): value is ErrorX;
408
+ static isErrorX<TMetadata extends ErrorXMetadata = ErrorXMetadata>(value: unknown): value is ErrorX<TMetadata>;
471
409
  /**
472
410
  * Converts unknown input into ErrorXOptions with intelligent property extraction.
473
411
  * Handles strings, regular Error objects, API response objects, and unknown values.
@@ -488,10 +426,10 @@ declare class ErrorX extends Error {
488
426
  * @example
489
427
  * ```typescript
490
428
  * // Convert string error
491
- * const error1 = ErrorX.toErrorX('Something went wrong')
429
+ * const error1 = ErrorX.from('Something went wrong')
492
430
  *
493
431
  * // Convert regular Error
494
- * const error2 = ErrorX.toErrorX(new Error('Database failed'))
432
+ * const error2 = ErrorX.from(new Error('Database failed'))
495
433
  *
496
434
  * // Convert API response object
497
435
  * const apiError = {
@@ -499,26 +437,13 @@ declare class ErrorX extends Error {
499
437
  * code: 'USER_404',
500
438
  * statusText: 'Not Found'
501
439
  * }
502
- * const error3 = ErrorX.toErrorX(apiError)
440
+ * const error3 = ErrorX.from(apiError)
503
441
  * ```
504
442
  */
505
- static toErrorX(error: unknown): ErrorX;
506
- /**
507
- * Public wrapper for processing error stack traces with delimiter.
508
- * Delegates to the private processErrorStack method for implementation.
509
- *
510
- * @param error - Error whose stack to process
511
- * @param delimiter - String to search for in stack lines
512
- * @returns Processed stack trace starting after the delimiter
513
- *
514
- * @example
515
- * ```typescript
516
- * const error = new Error('Something failed')
517
- * const cleanStack = ErrorX.processStack(error, 'my-app-entry')
518
- * // Returns stack trace starting after the line containing 'my-app-entry'
519
- * ```
520
- */
521
- static processStack(error: Error, delimiter: string): string;
443
+ static from<TMetadata extends ErrorXMetadata = ErrorXMetadata>(error: ErrorX<TMetadata>): ErrorX<TMetadata>;
444
+ static from(error: Error): ErrorX;
445
+ static from(error: string): ErrorX;
446
+ static from(error: unknown): ErrorX;
522
447
  /**
523
448
  * Creates a new ErrorX instance with cleaned stack trace using the specified delimiter.
524
449
  * Returns the same instance if no delimiter is provided or no stack is available.
@@ -533,7 +458,7 @@ declare class ErrorX extends Error {
533
458
  * // Returns new ErrorX with stack trace starting after 'database-layer'
534
459
  * ```
535
460
  */
536
- cleanStackTrace(delimiter?: string): ErrorX;
461
+ cleanStackTrace(delimiter?: string): ErrorX<TMetadata>;
537
462
  /**
538
463
  * Converts the ErrorX instance to a detailed string representation.
539
464
  * Includes error name, message, code, timestamp, metadata, and stack trace.
@@ -572,7 +497,7 @@ declare class ErrorX extends Error {
572
497
  * // Can be safely passed to JSON.stringify() or sent over network
573
498
  * ```
574
499
  */
575
- toJSON(): SerializableError;
500
+ toJSON(): ErrorXSerialized;
576
501
  /**
577
502
  * Deserializes a JSON object back into an ErrorX instance.
578
503
  * Recursively reconstructs the error chain and restores all properties.
@@ -595,441 +520,429 @@ declare class ErrorX extends Error {
595
520
  * // Fully restored ErrorX instance with all properties
596
521
  * ```
597
522
  */
598
- static fromJSON(serialized: SerializableError): ErrorX;
599
- /**
600
- * HTTP error presets for common HTTP status codes.
601
- *
602
- * ## Features
603
- * - **Pre-configured error templates** for common HTTP status codes (400-511)
604
- * - **Type-safe** with TypeScript support
605
- * - **Fully customizable** via destructuring and override pattern
606
- * - **User-friendly messages** included for all presets
607
- * - **Categorized by type** - all HTTP presets include `type: 'http'`
608
- *
609
- * ## Usage Patterns
610
- *
611
- * ### 1. Direct Usage
612
- * Use a preset as-is without any modifications:
613
- * ```typescript
614
- * throw new ErrorX(ErrorX.HTTP.NOT_FOUND)
615
- * // Result: 404 error with default message and UI message
616
- * ```
617
- *
618
- * ### 2. Override Specific Fields
619
- * Customize the error while keeping other preset values:
620
- * ```typescript
621
- * throw new ErrorX({
622
- * ...ErrorX.HTTP.NOT_FOUND,
623
- * message: 'User not found',
624
- * metadata: { userId: 123 }
625
- * })
626
- * // Result: 404 error with custom message but keeps httpStatus, code, name, uiMessage, type
627
- * ```
628
- *
629
- * ### 3. Add Metadata and Actions
630
- * Enhance presets with additional context and behaviors:
631
- * ```typescript
632
- * throw new ErrorX({
633
- * ...ErrorX.HTTP.UNAUTHORIZED,
634
- * metadata: { attemptedAction: 'viewProfile', userId: 456 },
635
- * actions: [
636
- * { action: 'logout', payload: { clearStorage: true } },
637
- * { action: 'redirect', payload: { redirectURL: '/login' } }
638
- * ]
639
- * })
640
- * ```
641
- *
642
- * ### 4. Add Error Cause
643
- * Chain errors by adding a cause:
644
- * ```typescript
645
- * try {
646
- * // some operation
647
- * } catch (originalError) {
648
- * throw new ErrorX({
649
- * ...ErrorX.HTTP.INTERNAL_SERVER_ERROR,
650
- * cause: originalError,
651
- * metadata: { operation: 'database-query' }
652
- * })
653
- * }
654
- * ```
655
- *
656
- * ## Common HTTP Presets
657
- *
658
- * ### 4xx Client Errors
659
- * - `BAD_REQUEST` (400) - Invalid request data
660
- * - `UNAUTHORIZED` (401) - Authentication required
661
- * - `FORBIDDEN` (403) - Insufficient permissions
662
- * - `NOT_FOUND` (404) - Resource not found
663
- * - `METHOD_NOT_ALLOWED` (405) - HTTP method not allowed
664
- * - `CONFLICT` (409) - Resource conflict
665
- * - `UNPROCESSABLE_ENTITY` (422) - Validation failed
666
- * - `TOO_MANY_REQUESTS` (429) - Rate limit exceeded
667
- *
668
- * ### 5xx Server Errors
669
- * - `INTERNAL_SERVER_ERROR` (500) - Unexpected server error
670
- * - `NOT_IMPLEMENTED` (501) - Feature not implemented
671
- * - `BAD_GATEWAY` (502) - Upstream server error
672
- * - `SERVICE_UNAVAILABLE` (503) - Service temporarily down
673
- * - `GATEWAY_TIMEOUT` (504) - Upstream timeout
674
- *
675
- * @example
676
- * ```typescript
677
- * // API endpoint example
678
- * app.get('/users/:id', async (req, res) => {
679
- * const user = await db.users.findById(req.params.id)
680
- *
681
- * if (!user) {
682
- * throw new ErrorX({
683
- * ...ErrorX.HTTP.NOT_FOUND,
684
- * message: 'User not found',
685
- * metadata: { userId: req.params.id }
686
- * })
687
- * }
688
- *
689
- * res.json(user)
690
- * })
691
- *
692
- * // Authentication middleware example
693
- * const requireAuth = (req, res, next) => {
694
- * if (!req.user) {
695
- * throw new ErrorX({
696
- * ...ErrorX.HTTP.UNAUTHORIZED,
697
- * actions: [
698
- * { action: 'redirect', payload: { redirectURL: '/login' } }
699
- * ]
700
- * })
701
- * }
702
- * next()
703
- * }
704
- *
705
- * // Rate limiting example
706
- * if (isRateLimited(req.ip)) {
707
- * throw new ErrorX({
708
- * ...ErrorX.HTTP.TOO_MANY_REQUESTS,
709
- * metadata: {
710
- * ip: req.ip,
711
- * retryAfter: 60
712
- * }
713
- * })
714
- * }
715
- * ```
716
- *
717
- * @public
718
- */
719
- static readonly HTTP: {
720
- readonly BAD_REQUEST: {
721
- httpStatus: number;
722
- code: string;
723
- name: string;
724
- message: string;
725
- uiMessage: string;
726
- type: string;
727
- };
728
- readonly UNAUTHORIZED: {
729
- httpStatus: number;
730
- code: string;
731
- name: string;
732
- message: string;
733
- uiMessage: string;
734
- type: string;
735
- };
736
- readonly PAYMENT_REQUIRED: {
737
- httpStatus: number;
738
- code: string;
739
- name: string;
740
- message: string;
741
- uiMessage: string;
742
- type: string;
743
- };
744
- readonly FORBIDDEN: {
745
- httpStatus: number;
746
- code: string;
747
- name: string;
748
- message: string;
749
- uiMessage: string;
750
- type: string;
751
- };
752
- readonly NOT_FOUND: {
753
- httpStatus: number;
754
- code: string;
755
- name: string;
756
- message: string;
757
- uiMessage: string;
758
- type: string;
759
- };
760
- readonly METHOD_NOT_ALLOWED: {
761
- httpStatus: number;
762
- code: string;
763
- name: string;
764
- message: string;
765
- uiMessage: string;
766
- type: string;
767
- };
768
- readonly NOT_ACCEPTABLE: {
769
- httpStatus: number;
770
- code: string;
771
- name: string;
772
- message: string;
773
- uiMessage: string;
774
- type: string;
775
- };
776
- readonly PROXY_AUTHENTICATION_REQUIRED: {
777
- httpStatus: number;
778
- code: string;
779
- name: string;
780
- message: string;
781
- uiMessage: string;
782
- type: string;
783
- };
784
- readonly REQUEST_TIMEOUT: {
785
- httpStatus: number;
786
- code: string;
787
- name: string;
788
- message: string;
789
- uiMessage: string;
790
- type: string;
791
- };
792
- readonly CONFLICT: {
793
- httpStatus: number;
794
- code: string;
795
- name: string;
796
- message: string;
797
- uiMessage: string;
798
- type: string;
799
- };
800
- readonly GONE: {
801
- httpStatus: number;
802
- code: string;
803
- name: string;
804
- message: string;
805
- uiMessage: string;
806
- type: string;
807
- };
808
- readonly LENGTH_REQUIRED: {
809
- httpStatus: number;
810
- code: string;
811
- name: string;
812
- message: string;
813
- uiMessage: string;
814
- type: string;
815
- };
816
- readonly PRECONDITION_FAILED: {
817
- httpStatus: number;
818
- code: string;
819
- name: string;
820
- message: string;
821
- uiMessage: string;
822
- type: string;
823
- };
824
- readonly PAYLOAD_TOO_LARGE: {
825
- httpStatus: number;
826
- code: string;
827
- name: string;
828
- message: string;
829
- uiMessage: string;
830
- type: string;
831
- };
832
- readonly URI_TOO_LONG: {
833
- httpStatus: number;
834
- code: string;
835
- name: string;
836
- message: string;
837
- uiMessage: string;
838
- type: string;
839
- };
840
- readonly UNSUPPORTED_MEDIA_TYPE: {
841
- httpStatus: number;
842
- code: string;
843
- name: string;
844
- message: string;
845
- uiMessage: string;
846
- type: string;
847
- };
848
- readonly RANGE_NOT_SATISFIABLE: {
849
- httpStatus: number;
850
- code: string;
851
- name: string;
852
- message: string;
853
- uiMessage: string;
854
- type: string;
855
- };
856
- readonly EXPECTATION_FAILED: {
857
- httpStatus: number;
858
- code: string;
859
- name: string;
860
- message: string;
861
- uiMessage: string;
862
- type: string;
863
- };
864
- readonly IM_A_TEAPOT: {
865
- httpStatus: number;
866
- code: string;
867
- name: string;
868
- message: string;
869
- uiMessage: string;
870
- type: string;
871
- };
872
- readonly UNPROCESSABLE_ENTITY: {
873
- httpStatus: number;
874
- code: string;
875
- name: string;
876
- message: string;
877
- uiMessage: string;
878
- type: string;
879
- };
880
- readonly LOCKED: {
881
- httpStatus: number;
882
- code: string;
883
- name: string;
884
- message: string;
885
- uiMessage: string;
886
- type: string;
887
- };
888
- readonly FAILED_DEPENDENCY: {
889
- httpStatus: number;
890
- code: string;
891
- name: string;
892
- message: string;
893
- uiMessage: string;
894
- type: string;
895
- };
896
- readonly TOO_EARLY: {
897
- httpStatus: number;
898
- code: string;
899
- name: string;
900
- message: string;
901
- uiMessage: string;
902
- type: string;
903
- };
904
- readonly UPGRADE_REQUIRED: {
905
- httpStatus: number;
906
- code: string;
907
- name: string;
908
- message: string;
909
- uiMessage: string;
910
- type: string;
911
- };
912
- readonly PRECONDITION_REQUIRED: {
913
- httpStatus: number;
914
- code: string;
915
- name: string;
916
- message: string;
917
- uiMessage: string;
918
- type: string;
919
- };
920
- readonly TOO_MANY_REQUESTS: {
921
- httpStatus: number;
922
- code: string;
923
- name: string;
924
- message: string;
925
- uiMessage: string;
926
- type: string;
927
- };
928
- readonly REQUEST_HEADER_FIELDS_TOO_LARGE: {
929
- httpStatus: number;
930
- code: string;
931
- name: string;
932
- message: string;
933
- uiMessage: string;
934
- type: string;
935
- };
936
- readonly UNAVAILABLE_FOR_LEGAL_REASONS: {
937
- httpStatus: number;
938
- code: string;
939
- name: string;
940
- message: string;
941
- uiMessage: string;
942
- type: string;
943
- };
944
- readonly INTERNAL_SERVER_ERROR: {
945
- httpStatus: number;
946
- code: string;
947
- name: string;
948
- message: string;
949
- uiMessage: string;
950
- type: string;
951
- };
952
- readonly NOT_IMPLEMENTED: {
953
- httpStatus: number;
954
- code: string;
955
- name: string;
956
- message: string;
957
- uiMessage: string;
958
- type: string;
959
- };
960
- readonly BAD_GATEWAY: {
961
- httpStatus: number;
962
- code: string;
963
- name: string;
964
- message: string;
965
- uiMessage: string;
966
- type: string;
967
- };
968
- readonly SERVICE_UNAVAILABLE: {
969
- httpStatus: number;
970
- code: string;
971
- name: string;
972
- message: string;
973
- uiMessage: string;
974
- type: string;
975
- };
976
- readonly GATEWAY_TIMEOUT: {
977
- httpStatus: number;
978
- code: string;
979
- name: string;
980
- message: string;
981
- uiMessage: string;
982
- type: string;
983
- };
984
- readonly HTTP_VERSION_NOT_SUPPORTED: {
985
- httpStatus: number;
986
- code: string;
987
- name: string;
988
- message: string;
989
- uiMessage: string;
990
- type: string;
991
- };
992
- readonly VARIANT_ALSO_NEGOTIATES: {
993
- httpStatus: number;
994
- code: string;
995
- name: string;
996
- message: string;
997
- uiMessage: string;
998
- type: string;
999
- };
1000
- readonly INSUFFICIENT_STORAGE: {
1001
- httpStatus: number;
1002
- code: string;
1003
- name: string;
1004
- message: string;
1005
- uiMessage: string;
1006
- type: string;
1007
- };
1008
- readonly LOOP_DETECTED: {
1009
- httpStatus: number;
1010
- code: string;
1011
- name: string;
1012
- message: string;
1013
- uiMessage: string;
1014
- type: string;
1015
- };
1016
- readonly NOT_EXTENDED: {
1017
- httpStatus: number;
1018
- code: string;
1019
- name: string;
1020
- message: string;
1021
- uiMessage: string;
1022
- type: string;
1023
- };
1024
- readonly NETWORK_AUTHENTICATION_REQUIRED: {
1025
- httpStatus: number;
1026
- code: string;
1027
- name: string;
1028
- message: string;
1029
- uiMessage: string;
1030
- type: string;
1031
- };
1032
- };
523
+ static fromJSON<TMetadata extends ErrorXMetadata = ErrorXMetadata>(serialized: ErrorXSerialized): ErrorX<TMetadata>;
1033
524
  }
1034
525
 
1035
- export { type CustomAction, type ErrorAction, type ErrorMetadata, ErrorX, type ErrorXOptions, type HandlingTarget, HandlingTargets, type LogoutAction, type NotifyAction, type RedirectAction, type SerializableError };
526
+ /**
527
+ * HTTP error presets for common HTTP status codes.
528
+ *
529
+ * These presets provide pre-configured error options for standard HTTP error responses,
530
+ * including appropriate status codes, error codes, names, messages (sentence case), and user-friendly UI messages.
531
+ *
532
+ * ## Usage Patterns
533
+ *
534
+ * ### 1. Use Preset Directly
535
+ * Create an error with all preset values:
536
+ * ```typescript
537
+ * throw new ErrorX(http.notFound)
538
+ * // Result: 404 error with message "Not found.", code, name, uiMessage, and type
539
+ * ```
540
+ *
541
+ * ### 2. Override Specific Fields
542
+ * Customize the error while keeping other preset values:
543
+ * ```typescript
544
+ * throw new ErrorX({
545
+ * ...http.notFound,
546
+ * message: 'User not found',
547
+ * metadata: { userId: 123 }
548
+ * })
549
+ * // Result: 404 error with custom message but keeps httpStatus, code, name, uiMessage, type
550
+ * ```
551
+ *
552
+ * ### 3. Add Metadata
553
+ * Enhance presets with additional context:
554
+ * ```typescript
555
+ * throw new ErrorX({
556
+ * ...http.unauthorized,
557
+ * metadata: { attemptedAction: 'viewProfile', userId: 456 }
558
+ * })
559
+ * ```
560
+ *
561
+ * ### 4. Add Error Cause
562
+ * Chain errors by adding a cause:
563
+ * ```typescript
564
+ * try {
565
+ * // some operation
566
+ * } catch (originalError) {
567
+ * throw new ErrorX({
568
+ * ...http.internalServerError,
569
+ * cause: originalError,
570
+ * metadata: { operation: 'database-query' }
571
+ * })
572
+ * }
573
+ * ```
574
+ *
575
+ * ## Common HTTP Presets
576
+ *
577
+ * ### 4xx Client Errors
578
+ * - `badRequest` (400) - Invalid request data
579
+ * - `unauthorized` (401) - Authentication required
580
+ * - `forbidden` (403) - Insufficient permissions
581
+ * - `notFound` (404) - Resource not found
582
+ * - `methodNotAllowed` (405) - HTTP method not allowed
583
+ * - `conflict` (409) - Resource conflict
584
+ * - `unprocessableEntity` (422) - Validation failed
585
+ * - `tooManyRequests` (429) - Rate limit exceeded
586
+ *
587
+ * ### 5xx Server Errors
588
+ * - `internalServerError` (500) - Unexpected server error
589
+ * - `notImplemented` (501) - Feature not implemented
590
+ * - `badGateway` (502) - Upstream server error
591
+ * - `serviceUnavailable` (503) - Service temporarily down
592
+ * - `gatewayTimeout` (504) - Upstream timeout
593
+ *
594
+ * @example
595
+ * ```typescript
596
+ * // API endpoint example
597
+ * app.get('/users/:id', async (req, res) => {
598
+ * const user = await db.users.findById(req.params.id)
599
+ *
600
+ * if (!user) {
601
+ * throw new ErrorX({
602
+ * ...http.notFound,
603
+ * message: 'User not found',
604
+ * metadata: { userId: req.params.id }
605
+ * })
606
+ * }
607
+ *
608
+ * res.json(user)
609
+ * })
610
+ *
611
+ * // Authentication middleware example
612
+ * const requireAuth = (req, res, next) => {
613
+ * if (!req.user) {
614
+ * throw new ErrorX(http.unauthorized)
615
+ * }
616
+ * next()
617
+ * }
618
+ *
619
+ * // Rate limiting example
620
+ * if (isRateLimited(req.ip)) {
621
+ * throw new ErrorX({
622
+ * ...http.tooManyRequests,
623
+ * metadata: {
624
+ * ip: req.ip,
625
+ * retryAfter: 60
626
+ * }
627
+ * })
628
+ * }
629
+ * ```
630
+ *
631
+ * @public
632
+ */
633
+ declare const http: {
634
+ readonly badRequest: {
635
+ httpStatus: number;
636
+ code: string;
637
+ name: string;
638
+ message: string;
639
+ uiMessage: string;
640
+ type: string;
641
+ };
642
+ readonly unauthorized: {
643
+ httpStatus: number;
644
+ code: string;
645
+ name: string;
646
+ message: string;
647
+ uiMessage: string;
648
+ type: string;
649
+ };
650
+ readonly paymentRequired: {
651
+ httpStatus: number;
652
+ code: string;
653
+ name: string;
654
+ message: string;
655
+ uiMessage: string;
656
+ type: string;
657
+ };
658
+ readonly forbidden: {
659
+ httpStatus: number;
660
+ code: string;
661
+ name: string;
662
+ message: string;
663
+ uiMessage: string;
664
+ type: string;
665
+ };
666
+ readonly notFound: {
667
+ httpStatus: number;
668
+ code: string;
669
+ name: string;
670
+ message: string;
671
+ uiMessage: string;
672
+ type: string;
673
+ };
674
+ readonly methodNotAllowed: {
675
+ httpStatus: number;
676
+ code: string;
677
+ name: string;
678
+ message: string;
679
+ uiMessage: string;
680
+ type: string;
681
+ };
682
+ readonly notAcceptable: {
683
+ httpStatus: number;
684
+ code: string;
685
+ name: string;
686
+ message: string;
687
+ uiMessage: string;
688
+ type: string;
689
+ };
690
+ readonly proxyAuthenticationRequired: {
691
+ httpStatus: number;
692
+ code: string;
693
+ name: string;
694
+ message: string;
695
+ uiMessage: string;
696
+ type: string;
697
+ };
698
+ readonly requestTimeout: {
699
+ httpStatus: number;
700
+ code: string;
701
+ name: string;
702
+ message: string;
703
+ uiMessage: string;
704
+ type: string;
705
+ };
706
+ readonly conflict: {
707
+ httpStatus: number;
708
+ code: string;
709
+ name: string;
710
+ message: string;
711
+ uiMessage: string;
712
+ type: string;
713
+ };
714
+ readonly gone: {
715
+ httpStatus: number;
716
+ code: string;
717
+ name: string;
718
+ message: string;
719
+ uiMessage: string;
720
+ type: string;
721
+ };
722
+ readonly lengthRequired: {
723
+ httpStatus: number;
724
+ code: string;
725
+ name: string;
726
+ message: string;
727
+ uiMessage: string;
728
+ type: string;
729
+ };
730
+ readonly preconditionFailed: {
731
+ httpStatus: number;
732
+ code: string;
733
+ name: string;
734
+ message: string;
735
+ uiMessage: string;
736
+ type: string;
737
+ };
738
+ readonly payloadTooLarge: {
739
+ httpStatus: number;
740
+ code: string;
741
+ name: string;
742
+ message: string;
743
+ uiMessage: string;
744
+ type: string;
745
+ };
746
+ readonly uriTooLong: {
747
+ httpStatus: number;
748
+ code: string;
749
+ name: string;
750
+ message: string;
751
+ uiMessage: string;
752
+ type: string;
753
+ };
754
+ readonly unsupportedMediaType: {
755
+ httpStatus: number;
756
+ code: string;
757
+ name: string;
758
+ message: string;
759
+ uiMessage: string;
760
+ type: string;
761
+ };
762
+ readonly rangeNotSatisfiable: {
763
+ httpStatus: number;
764
+ code: string;
765
+ name: string;
766
+ message: string;
767
+ uiMessage: string;
768
+ type: string;
769
+ };
770
+ readonly expectationFailed: {
771
+ httpStatus: number;
772
+ code: string;
773
+ name: string;
774
+ message: string;
775
+ uiMessage: string;
776
+ type: string;
777
+ };
778
+ readonly imATeapot: {
779
+ httpStatus: number;
780
+ code: string;
781
+ name: string;
782
+ message: string;
783
+ uiMessage: string;
784
+ type: string;
785
+ };
786
+ readonly unprocessableEntity: {
787
+ httpStatus: number;
788
+ code: string;
789
+ name: string;
790
+ message: string;
791
+ uiMessage: string;
792
+ type: string;
793
+ };
794
+ readonly locked: {
795
+ httpStatus: number;
796
+ code: string;
797
+ name: string;
798
+ message: string;
799
+ uiMessage: string;
800
+ type: string;
801
+ };
802
+ readonly failedDependency: {
803
+ httpStatus: number;
804
+ code: string;
805
+ name: string;
806
+ message: string;
807
+ uiMessage: string;
808
+ type: string;
809
+ };
810
+ readonly tooEarly: {
811
+ httpStatus: number;
812
+ code: string;
813
+ name: string;
814
+ message: string;
815
+ uiMessage: string;
816
+ type: string;
817
+ };
818
+ readonly upgradeRequired: {
819
+ httpStatus: number;
820
+ code: string;
821
+ name: string;
822
+ message: string;
823
+ uiMessage: string;
824
+ type: string;
825
+ };
826
+ readonly preconditionRequired: {
827
+ httpStatus: number;
828
+ code: string;
829
+ name: string;
830
+ message: string;
831
+ uiMessage: string;
832
+ type: string;
833
+ };
834
+ readonly tooManyRequests: {
835
+ httpStatus: number;
836
+ code: string;
837
+ name: string;
838
+ message: string;
839
+ uiMessage: string;
840
+ type: string;
841
+ };
842
+ readonly requestHeaderFieldsTooLarge: {
843
+ httpStatus: number;
844
+ code: string;
845
+ name: string;
846
+ message: string;
847
+ uiMessage: string;
848
+ type: string;
849
+ };
850
+ readonly unavailableForLegalReasons: {
851
+ httpStatus: number;
852
+ code: string;
853
+ name: string;
854
+ message: string;
855
+ uiMessage: string;
856
+ type: string;
857
+ };
858
+ readonly internalServerError: {
859
+ httpStatus: number;
860
+ code: string;
861
+ name: string;
862
+ message: string;
863
+ uiMessage: string;
864
+ type: string;
865
+ };
866
+ readonly notImplemented: {
867
+ httpStatus: number;
868
+ code: string;
869
+ name: string;
870
+ message: string;
871
+ uiMessage: string;
872
+ type: string;
873
+ };
874
+ readonly badGateway: {
875
+ httpStatus: number;
876
+ code: string;
877
+ name: string;
878
+ message: string;
879
+ uiMessage: string;
880
+ type: string;
881
+ };
882
+ readonly serviceUnavailable: {
883
+ httpStatus: number;
884
+ code: string;
885
+ name: string;
886
+ message: string;
887
+ uiMessage: string;
888
+ type: string;
889
+ };
890
+ readonly gatewayTimeout: {
891
+ httpStatus: number;
892
+ code: string;
893
+ name: string;
894
+ message: string;
895
+ uiMessage: string;
896
+ type: string;
897
+ };
898
+ readonly httpVersionNotSupported: {
899
+ httpStatus: number;
900
+ code: string;
901
+ name: string;
902
+ message: string;
903
+ uiMessage: string;
904
+ type: string;
905
+ };
906
+ readonly variantAlsoNegotiates: {
907
+ httpStatus: number;
908
+ code: string;
909
+ name: string;
910
+ message: string;
911
+ uiMessage: string;
912
+ type: string;
913
+ };
914
+ readonly insufficientStorage: {
915
+ httpStatus: number;
916
+ code: string;
917
+ name: string;
918
+ message: string;
919
+ uiMessage: string;
920
+ type: string;
921
+ };
922
+ readonly loopDetected: {
923
+ httpStatus: number;
924
+ code: string;
925
+ name: string;
926
+ message: string;
927
+ uiMessage: string;
928
+ type: string;
929
+ };
930
+ readonly notExtended: {
931
+ httpStatus: number;
932
+ code: string;
933
+ name: string;
934
+ message: string;
935
+ uiMessage: string;
936
+ type: string;
937
+ };
938
+ readonly networkAuthenticationRequired: {
939
+ httpStatus: number;
940
+ code: string;
941
+ name: string;
942
+ message: string;
943
+ uiMessage: string;
944
+ type: string;
945
+ };
946
+ };
947
+
948
+ export { ErrorX, type ErrorXCause, type ErrorXConfig, type ErrorXMetadata, type ErrorXOptions, type ErrorXSerialized, http };