@bombillazo/error-x 0.3.0 → 0.4.0

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.cts 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
63
  /** Original error that caused this error (preserves error chain) */
205
64
  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) */
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,103 @@ 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;
303
227
  /**
304
228
  * Creates a new ErrorX instance with enhanced error handling capabilities.
305
229
  *
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)
230
+ * @param messageOrOptions - Error message string or ErrorXOptions object (optional)
308
231
  *
309
232
  * @example
310
233
  * ```typescript
234
+ * // Create with default message
235
+ * const error1 = new ErrorX()
236
+ *
311
237
  * // Create with string message only
312
- * const error1 = new ErrorX('Database query failed')
238
+ * const error2 = new ErrorX('Database query failed')
313
239
  *
314
- * // Create with string message and additional options
315
- * const error2 = new ErrorX('Database query failed', {
240
+ * // Create with options object
241
+ * const error3 = new ErrorX({
242
+ * message: 'Database query failed',
316
243
  * name: 'DatabaseError',
317
244
  * code: 'DB_QUERY_FAILED',
318
245
  * uiMessage: 'Unable to load data. Please try again.',
319
246
  * metadata: { query: 'SELECT * FROM users', timeout: 5000 }
320
247
  * })
321
248
  *
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
- * ]
249
+ * // With type-safe metadata
250
+ * type MyMeta = { userId: number };
251
+ * const error4 = new ErrorX<MyMeta>({
252
+ * message: 'User action failed',
253
+ * metadata: { userId: 123 }
330
254
  * })
331
255
  *
332
- * // Create with unknown input (smart conversion)
256
+ * // For converting unknown errors, use ErrorX.from()
333
257
  * 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()
258
+ * const error5 = ErrorX.from(apiError)
338
259
  * ```
339
260
  */
340
- constructor(messageOrOptions?: string | ErrorXOptions | unknown, additionalOptions?: Partial<ErrorXOptions>);
261
+ constructor(messageOrOptions?: string | ErrorXOptions<TMetadata>);
341
262
  /**
342
263
  * Returns the default error name.
343
264
  * @returns Default error name 'Error'
344
265
  */
345
266
  private static getDefaultName;
267
+ /**
268
+ * Configure global ErrorX settings.
269
+ * This method allows you to set defaults for all ErrorX instances.
270
+ *
271
+ * @param config - Configuration object
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * ErrorX.configure({
276
+ * source: 'my-api-service',
277
+ * docsBaseURL: 'https://docs.example.com/errors',
278
+ * docsMap: {
279
+ * 'AUTH_FAILED': 'authentication-errors',
280
+ * 'DB_ERROR': 'database-errors'
281
+ * }
282
+ * })
283
+ * ```
284
+ */
285
+ static configure(config: ErrorXConfig): void;
286
+ /**
287
+ * Get the current global configuration.
288
+ * Returns null if no configuration has been set.
289
+ */
290
+ static getConfig(): ErrorXConfig | null;
346
291
  /**
347
292
  * Validates HTTP status code to ensure it's within valid range (100-599)
348
293
  *
@@ -412,21 +357,6 @@ declare class ErrorX extends Error {
412
357
  * ```
413
358
  */
414
359
  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
360
  /**
431
361
  * Creates a new ErrorX instance with additional metadata merged with existing metadata.
432
362
  * The original error properties are preserved while extending the metadata.
@@ -448,7 +378,7 @@ declare class ErrorX extends Error {
448
378
  * // Result: metadata = { endpoint: '/users', retryCount: 3, userId: 123 }
449
379
  * ```
450
380
  */
451
- withMetadata(additionalMetadata: ErrorMetadata): ErrorX;
381
+ withMetadata(additionalMetadata: Partial<TMetadata>): ErrorX<TMetadata>;
452
382
  /**
453
383
  * Type guard that checks if a value is an ErrorX instance.
454
384
  *
@@ -467,7 +397,7 @@ declare class ErrorX extends Error {
467
397
  * }
468
398
  * ```
469
399
  */
470
- static isErrorX(value: unknown): value is ErrorX;
400
+ static isErrorX<TMetadata extends ErrorXMetadata = ErrorXMetadata>(value: unknown): value is ErrorX<TMetadata>;
471
401
  /**
472
402
  * Converts unknown input into ErrorXOptions with intelligent property extraction.
473
403
  * Handles strings, regular Error objects, API response objects, and unknown values.
@@ -488,10 +418,10 @@ declare class ErrorX extends Error {
488
418
  * @example
489
419
  * ```typescript
490
420
  * // Convert string error
491
- * const error1 = ErrorX.toErrorX('Something went wrong')
421
+ * const error1 = ErrorX.from('Something went wrong')
492
422
  *
493
423
  * // Convert regular Error
494
- * const error2 = ErrorX.toErrorX(new Error('Database failed'))
424
+ * const error2 = ErrorX.from(new Error('Database failed'))
495
425
  *
496
426
  * // Convert API response object
497
427
  * const apiError = {
@@ -499,26 +429,13 @@ declare class ErrorX extends Error {
499
429
  * code: 'USER_404',
500
430
  * statusText: 'Not Found'
501
431
  * }
502
- * const error3 = ErrorX.toErrorX(apiError)
432
+ * const error3 = ErrorX.from(apiError)
503
433
  * ```
504
434
  */
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;
435
+ static from<TMetadata extends ErrorXMetadata = ErrorXMetadata>(error: ErrorX<TMetadata>): ErrorX<TMetadata>;
436
+ static from(error: Error): ErrorX;
437
+ static from(error: string): ErrorX;
438
+ static from(error: unknown): ErrorX;
522
439
  /**
523
440
  * Creates a new ErrorX instance with cleaned stack trace using the specified delimiter.
524
441
  * Returns the same instance if no delimiter is provided or no stack is available.
@@ -533,7 +450,7 @@ declare class ErrorX extends Error {
533
450
  * // Returns new ErrorX with stack trace starting after 'database-layer'
534
451
  * ```
535
452
  */
536
- cleanStackTrace(delimiter?: string): ErrorX;
453
+ cleanStackTrace(delimiter?: string): ErrorX<TMetadata>;
537
454
  /**
538
455
  * Converts the ErrorX instance to a detailed string representation.
539
456
  * Includes error name, message, code, timestamp, metadata, and stack trace.
@@ -572,7 +489,7 @@ declare class ErrorX extends Error {
572
489
  * // Can be safely passed to JSON.stringify() or sent over network
573
490
  * ```
574
491
  */
575
- toJSON(): SerializableError;
492
+ toJSON(): ErrorXSerialized;
576
493
  /**
577
494
  * Deserializes a JSON object back into an ErrorX instance.
578
495
  * Recursively reconstructs the error chain and restores all properties.
@@ -595,441 +512,429 @@ declare class ErrorX extends Error {
595
512
  * // Fully restored ErrorX instance with all properties
596
513
  * ```
597
514
  */
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
- };
515
+ static fromJSON<TMetadata extends ErrorXMetadata = ErrorXMetadata>(serialized: ErrorXSerialized): ErrorX<TMetadata>;
1033
516
  }
1034
517
 
1035
- export { type CustomAction, type ErrorAction, type ErrorMetadata, ErrorX, type ErrorXOptions, type HandlingTarget, HandlingTargets, type LogoutAction, type NotifyAction, type RedirectAction, type SerializableError };
518
+ /**
519
+ * HTTP error presets for common HTTP status codes.
520
+ *
521
+ * These presets provide pre-configured error options for standard HTTP error responses,
522
+ * including appropriate status codes, error codes, names, messages (sentence case), and user-friendly UI messages.
523
+ *
524
+ * ## Usage Patterns
525
+ *
526
+ * ### 1. Use Preset Directly
527
+ * Create an error with all preset values:
528
+ * ```typescript
529
+ * throw new ErrorX(http.notFound)
530
+ * // Result: 404 error with message "Not found.", code, name, uiMessage, and type
531
+ * ```
532
+ *
533
+ * ### 2. Override Specific Fields
534
+ * Customize the error while keeping other preset values:
535
+ * ```typescript
536
+ * throw new ErrorX({
537
+ * ...http.notFound,
538
+ * message: 'User not found',
539
+ * metadata: { userId: 123 }
540
+ * })
541
+ * // Result: 404 error with custom message but keeps httpStatus, code, name, uiMessage, type
542
+ * ```
543
+ *
544
+ * ### 3. Add Metadata
545
+ * Enhance presets with additional context:
546
+ * ```typescript
547
+ * throw new ErrorX({
548
+ * ...http.unauthorized,
549
+ * metadata: { attemptedAction: 'viewProfile', userId: 456 }
550
+ * })
551
+ * ```
552
+ *
553
+ * ### 4. Add Error Cause
554
+ * Chain errors by adding a cause:
555
+ * ```typescript
556
+ * try {
557
+ * // some operation
558
+ * } catch (originalError) {
559
+ * throw new ErrorX({
560
+ * ...http.internalServerError,
561
+ * cause: originalError,
562
+ * metadata: { operation: 'database-query' }
563
+ * })
564
+ * }
565
+ * ```
566
+ *
567
+ * ## Common HTTP Presets
568
+ *
569
+ * ### 4xx Client Errors
570
+ * - `badRequest` (400) - Invalid request data
571
+ * - `unauthorized` (401) - Authentication required
572
+ * - `forbidden` (403) - Insufficient permissions
573
+ * - `notFound` (404) - Resource not found
574
+ * - `methodNotAllowed` (405) - HTTP method not allowed
575
+ * - `conflict` (409) - Resource conflict
576
+ * - `unprocessableEntity` (422) - Validation failed
577
+ * - `tooManyRequests` (429) - Rate limit exceeded
578
+ *
579
+ * ### 5xx Server Errors
580
+ * - `internalServerError` (500) - Unexpected server error
581
+ * - `notImplemented` (501) - Feature not implemented
582
+ * - `badGateway` (502) - Upstream server error
583
+ * - `serviceUnavailable` (503) - Service temporarily down
584
+ * - `gatewayTimeout` (504) - Upstream timeout
585
+ *
586
+ * @example
587
+ * ```typescript
588
+ * // API endpoint example
589
+ * app.get('/users/:id', async (req, res) => {
590
+ * const user = await db.users.findById(req.params.id)
591
+ *
592
+ * if (!user) {
593
+ * throw new ErrorX({
594
+ * ...http.notFound,
595
+ * message: 'User not found',
596
+ * metadata: { userId: req.params.id }
597
+ * })
598
+ * }
599
+ *
600
+ * res.json(user)
601
+ * })
602
+ *
603
+ * // Authentication middleware example
604
+ * const requireAuth = (req, res, next) => {
605
+ * if (!req.user) {
606
+ * throw new ErrorX(http.unauthorized)
607
+ * }
608
+ * next()
609
+ * }
610
+ *
611
+ * // Rate limiting example
612
+ * if (isRateLimited(req.ip)) {
613
+ * throw new ErrorX({
614
+ * ...http.tooManyRequests,
615
+ * metadata: {
616
+ * ip: req.ip,
617
+ * retryAfter: 60
618
+ * }
619
+ * })
620
+ * }
621
+ * ```
622
+ *
623
+ * @public
624
+ */
625
+ declare const http: {
626
+ readonly badRequest: {
627
+ httpStatus: number;
628
+ code: string;
629
+ name: string;
630
+ message: string;
631
+ uiMessage: string;
632
+ type: string;
633
+ };
634
+ readonly unauthorized: {
635
+ httpStatus: number;
636
+ code: string;
637
+ name: string;
638
+ message: string;
639
+ uiMessage: string;
640
+ type: string;
641
+ };
642
+ readonly paymentRequired: {
643
+ httpStatus: number;
644
+ code: string;
645
+ name: string;
646
+ message: string;
647
+ uiMessage: string;
648
+ type: string;
649
+ };
650
+ readonly forbidden: {
651
+ httpStatus: number;
652
+ code: string;
653
+ name: string;
654
+ message: string;
655
+ uiMessage: string;
656
+ type: string;
657
+ };
658
+ readonly notFound: {
659
+ httpStatus: number;
660
+ code: string;
661
+ name: string;
662
+ message: string;
663
+ uiMessage: string;
664
+ type: string;
665
+ };
666
+ readonly methodNotAllowed: {
667
+ httpStatus: number;
668
+ code: string;
669
+ name: string;
670
+ message: string;
671
+ uiMessage: string;
672
+ type: string;
673
+ };
674
+ readonly notAcceptable: {
675
+ httpStatus: number;
676
+ code: string;
677
+ name: string;
678
+ message: string;
679
+ uiMessage: string;
680
+ type: string;
681
+ };
682
+ readonly proxyAuthenticationRequired: {
683
+ httpStatus: number;
684
+ code: string;
685
+ name: string;
686
+ message: string;
687
+ uiMessage: string;
688
+ type: string;
689
+ };
690
+ readonly requestTimeout: {
691
+ httpStatus: number;
692
+ code: string;
693
+ name: string;
694
+ message: string;
695
+ uiMessage: string;
696
+ type: string;
697
+ };
698
+ readonly conflict: {
699
+ httpStatus: number;
700
+ code: string;
701
+ name: string;
702
+ message: string;
703
+ uiMessage: string;
704
+ type: string;
705
+ };
706
+ readonly gone: {
707
+ httpStatus: number;
708
+ code: string;
709
+ name: string;
710
+ message: string;
711
+ uiMessage: string;
712
+ type: string;
713
+ };
714
+ readonly lengthRequired: {
715
+ httpStatus: number;
716
+ code: string;
717
+ name: string;
718
+ message: string;
719
+ uiMessage: string;
720
+ type: string;
721
+ };
722
+ readonly preconditionFailed: {
723
+ httpStatus: number;
724
+ code: string;
725
+ name: string;
726
+ message: string;
727
+ uiMessage: string;
728
+ type: string;
729
+ };
730
+ readonly payloadTooLarge: {
731
+ httpStatus: number;
732
+ code: string;
733
+ name: string;
734
+ message: string;
735
+ uiMessage: string;
736
+ type: string;
737
+ };
738
+ readonly uriTooLong: {
739
+ httpStatus: number;
740
+ code: string;
741
+ name: string;
742
+ message: string;
743
+ uiMessage: string;
744
+ type: string;
745
+ };
746
+ readonly unsupportedMediaType: {
747
+ httpStatus: number;
748
+ code: string;
749
+ name: string;
750
+ message: string;
751
+ uiMessage: string;
752
+ type: string;
753
+ };
754
+ readonly rangeNotSatisfiable: {
755
+ httpStatus: number;
756
+ code: string;
757
+ name: string;
758
+ message: string;
759
+ uiMessage: string;
760
+ type: string;
761
+ };
762
+ readonly expectationFailed: {
763
+ httpStatus: number;
764
+ code: string;
765
+ name: string;
766
+ message: string;
767
+ uiMessage: string;
768
+ type: string;
769
+ };
770
+ readonly imATeapot: {
771
+ httpStatus: number;
772
+ code: string;
773
+ name: string;
774
+ message: string;
775
+ uiMessage: string;
776
+ type: string;
777
+ };
778
+ readonly unprocessableEntity: {
779
+ httpStatus: number;
780
+ code: string;
781
+ name: string;
782
+ message: string;
783
+ uiMessage: string;
784
+ type: string;
785
+ };
786
+ readonly locked: {
787
+ httpStatus: number;
788
+ code: string;
789
+ name: string;
790
+ message: string;
791
+ uiMessage: string;
792
+ type: string;
793
+ };
794
+ readonly failedDependency: {
795
+ httpStatus: number;
796
+ code: string;
797
+ name: string;
798
+ message: string;
799
+ uiMessage: string;
800
+ type: string;
801
+ };
802
+ readonly tooEarly: {
803
+ httpStatus: number;
804
+ code: string;
805
+ name: string;
806
+ message: string;
807
+ uiMessage: string;
808
+ type: string;
809
+ };
810
+ readonly upgradeRequired: {
811
+ httpStatus: number;
812
+ code: string;
813
+ name: string;
814
+ message: string;
815
+ uiMessage: string;
816
+ type: string;
817
+ };
818
+ readonly preconditionRequired: {
819
+ httpStatus: number;
820
+ code: string;
821
+ name: string;
822
+ message: string;
823
+ uiMessage: string;
824
+ type: string;
825
+ };
826
+ readonly tooManyRequests: {
827
+ httpStatus: number;
828
+ code: string;
829
+ name: string;
830
+ message: string;
831
+ uiMessage: string;
832
+ type: string;
833
+ };
834
+ readonly requestHeaderFieldsTooLarge: {
835
+ httpStatus: number;
836
+ code: string;
837
+ name: string;
838
+ message: string;
839
+ uiMessage: string;
840
+ type: string;
841
+ };
842
+ readonly unavailableForLegalReasons: {
843
+ httpStatus: number;
844
+ code: string;
845
+ name: string;
846
+ message: string;
847
+ uiMessage: string;
848
+ type: string;
849
+ };
850
+ readonly internalServerError: {
851
+ httpStatus: number;
852
+ code: string;
853
+ name: string;
854
+ message: string;
855
+ uiMessage: string;
856
+ type: string;
857
+ };
858
+ readonly notImplemented: {
859
+ httpStatus: number;
860
+ code: string;
861
+ name: string;
862
+ message: string;
863
+ uiMessage: string;
864
+ type: string;
865
+ };
866
+ readonly badGateway: {
867
+ httpStatus: number;
868
+ code: string;
869
+ name: string;
870
+ message: string;
871
+ uiMessage: string;
872
+ type: string;
873
+ };
874
+ readonly serviceUnavailable: {
875
+ httpStatus: number;
876
+ code: string;
877
+ name: string;
878
+ message: string;
879
+ uiMessage: string;
880
+ type: string;
881
+ };
882
+ readonly gatewayTimeout: {
883
+ httpStatus: number;
884
+ code: string;
885
+ name: string;
886
+ message: string;
887
+ uiMessage: string;
888
+ type: string;
889
+ };
890
+ readonly httpVersionNotSupported: {
891
+ httpStatus: number;
892
+ code: string;
893
+ name: string;
894
+ message: string;
895
+ uiMessage: string;
896
+ type: string;
897
+ };
898
+ readonly variantAlsoNegotiates: {
899
+ httpStatus: number;
900
+ code: string;
901
+ name: string;
902
+ message: string;
903
+ uiMessage: string;
904
+ type: string;
905
+ };
906
+ readonly insufficientStorage: {
907
+ httpStatus: number;
908
+ code: string;
909
+ name: string;
910
+ message: string;
911
+ uiMessage: string;
912
+ type: string;
913
+ };
914
+ readonly loopDetected: {
915
+ httpStatus: number;
916
+ code: string;
917
+ name: string;
918
+ message: string;
919
+ uiMessage: string;
920
+ type: string;
921
+ };
922
+ readonly notExtended: {
923
+ httpStatus: number;
924
+ code: string;
925
+ name: string;
926
+ message: string;
927
+ uiMessage: string;
928
+ type: string;
929
+ };
930
+ readonly networkAuthenticationRequired: {
931
+ httpStatus: number;
932
+ code: string;
933
+ name: string;
934
+ message: string;
935
+ uiMessage: string;
936
+ type: string;
937
+ };
938
+ };
939
+
940
+ export { ErrorX, type ErrorXCause, type ErrorXConfig, type ErrorXMetadata, type ErrorXOptions, type ErrorXSerialized, http };