@bombillazo/error-x 0.4.0 → 0.4.2

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
@@ -60,8 +60,8 @@ type ErrorXOptions<TMetadata extends ErrorXMetadata = ErrorXMetadata> = {
60
60
  code?: string | number;
61
61
  /** User-friendly message for UI display */
62
62
  uiMessage?: string | undefined;
63
- /** Original error that caused this error (preserves error chain) */
64
- cause?: Error | unknown;
63
+ /** Original error that caused this error (preserves error chain, will be converted to ErrorXCause format) */
64
+ cause?: ErrorXCause | Error | unknown;
65
65
  /** Additional context and debugging information */
66
66
  metadata?: TMetadata | undefined;
67
67
  /** HTTP status code (100-599) for HTTP-related errors */
@@ -164,6 +164,11 @@ interface ErrorXConfig {
164
164
  * - string[]: Custom patterns to match and remove from stack traces
165
165
  */
166
166
  cleanStack?: boolean | string[];
167
+ /**
168
+ * Delimiter to trim stack traces after a specified line
169
+ * When set, stack traces will be trimmed to start after the first line containing this string
170
+ */
171
+ cleanStackDelimiter?: string;
167
172
  }
168
173
  /**
169
174
  * Enhanced Error class with rich metadata, type-safe error handling, and intelligent error conversion.
@@ -177,7 +182,8 @@ interface ErrorXConfig {
177
182
  * docsMap: {
178
183
  * 'AUTH_FAILED': 'errors/authentication',
179
184
  * 'DB_ERROR': 'errors/database'
180
- * }
185
+ * },
186
+ * cleanStackDelimiter: 'my-app-entry' // Clean stack traces after this line
181
187
  * })
182
188
  *
183
189
  * // Basic usage
@@ -224,6 +230,8 @@ declare class ErrorX<TMetadata extends ErrorXMetadata = ErrorXMetadata> extends
224
230
  docsUrl: string | undefined;
225
231
  /** Where the error originated (service name, module, component) */
226
232
  source: string | undefined;
233
+ /** Original error that caused this error (preserves error chain) */
234
+ cause: ErrorXCause | undefined;
227
235
  /**
228
236
  * Creates a new ErrorX instance with enhanced error handling capabilities.
229
237
  *
@@ -264,6 +272,12 @@ declare class ErrorX<TMetadata extends ErrorXMetadata = ErrorXMetadata> extends
264
272
  * @returns Default error name 'Error'
265
273
  */
266
274
  private static getDefaultName;
275
+ /**
276
+ * Converts any value to ErrorXCause format.
277
+ * @param value - Value to convert to ErrorXCause
278
+ * @returns ErrorXCause object or undefined if value is null/undefined
279
+ */
280
+ private static toErrorXCause;
267
281
  /**
268
282
  * Configure global ErrorX settings.
269
283
  * This method allows you to set defaults for all ErrorX instances.
@@ -278,7 +292,8 @@ declare class ErrorX<TMetadata extends ErrorXMetadata = ErrorXMetadata> extends
278
292
  * docsMap: {
279
293
  * 'AUTH_FAILED': 'authentication-errors',
280
294
  * 'DB_ERROR': 'database-errors'
281
- * }
295
+ * },
296
+ * cleanStackDelimiter: 'app-entry-point' // Trim stack traces after this line
282
297
  * })
283
298
  * ```
284
299
  */
@@ -288,6 +303,17 @@ declare class ErrorX<TMetadata extends ErrorXMetadata = ErrorXMetadata> extends
288
303
  * Returns null if no configuration has been set.
289
304
  */
290
305
  static getConfig(): ErrorXConfig | null;
306
+ /**
307
+ * Reset global configuration to null.
308
+ * Useful for testing or when you want to clear all configuration.
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * ErrorX.resetConfig()
313
+ * const config = ErrorX.getConfig() // null
314
+ * ```
315
+ */
316
+ static resetConfig(): void;
291
317
  /**
292
318
  * Validates HTTP status code to ensure it's within valid range (100-599)
293
319
  *
@@ -327,36 +353,32 @@ declare class ErrorX<TMetadata extends ErrorXMetadata = ErrorXMetadata> extends
327
353
  private static generateDefaultCode;
328
354
  /**
329
355
  * Preserves the original error's stack trace while updating the error message.
330
- * Combines the new error's message with the original error's stack trace.
356
+ * Combines the new error's message with the original error's stack trace from ErrorXCause.
331
357
  *
332
- * @param originalError - The original error whose stack to preserve
358
+ * @param cause - The ErrorXCause containing the original stack to preserve
333
359
  * @param newError - The new error whose message to use
334
360
  * @returns Combined stack trace with new error message and original stack
335
361
  */
336
- private static preserveOriginalStack;
362
+ private static preserveOriginalStackFromCause;
337
363
  /**
338
- * Cleans the stack trace by removing ErrorX internal method calls.
364
+ * Cleans a stack trace by removing ErrorX internal method calls and optionally trimming after a delimiter.
339
365
  * This provides cleaner stack traces that focus on user code.
340
366
  *
341
- * @param stack - Raw stack trace to clean
342
- * @returns Cleaned stack trace without ErrorX internal calls
343
- */
344
- private static cleanStack;
345
- /**
346
- * Processes an error's stack trace to trim it after a specified delimiter.
347
- * Useful for removing irrelevant stack frames before a specific function.
348
- *
349
- * @param error - Error whose stack to process
350
- * @param delimiter - String to search for in stack lines
351
- * @returns Processed stack trace starting after the delimiter
367
+ * @param stack - Raw stack trace string to clean
368
+ * @param delimiter - Optional delimiter to trim stack trace after (overrides config delimiter)
369
+ * @returns Cleaned stack trace without internal calls and optionally trimmed after delimiter
352
370
  *
353
371
  * @example
354
372
  * ```typescript
355
- * const processed = ErrorX.processErrorStack(error, 'my-app-entry')
373
+ * // Clean with pattern-based removal only
374
+ * const cleaned = ErrorX.cleanStack(error.stack)
375
+ *
376
+ * // Clean and trim after delimiter
377
+ * const trimmed = ErrorX.cleanStack(error.stack, 'my-app-entry')
356
378
  * // Returns stack trace starting after the line containing 'my-app-entry'
357
379
  * ```
358
380
  */
359
- private static processErrorStack;
381
+ static cleanStack(stack?: string, delimiter?: string): string;
360
382
  /**
361
383
  * Creates a new ErrorX instance with additional metadata merged with existing metadata.
362
384
  * The original error properties are preserved while extending the metadata.
@@ -436,21 +458,6 @@ declare class ErrorX<TMetadata extends ErrorXMetadata = ErrorXMetadata> extends
436
458
  static from(error: Error): ErrorX;
437
459
  static from(error: string): ErrorX;
438
460
  static from(error: unknown): ErrorX;
439
- /**
440
- * Creates a new ErrorX instance with cleaned stack trace using the specified delimiter.
441
- * Returns the same instance if no delimiter is provided or no stack is available.
442
- *
443
- * @param delimiter - Optional string to search for in stack lines
444
- * @returns New ErrorX instance with cleaned stack trace, or the same instance if no cleaning needed
445
- *
446
- * @example
447
- * ```typescript
448
- * const error = new ErrorX({ message: 'Database error' })
449
- * const cleanedError = error.cleanStackTrace('database-layer')
450
- * // Returns new ErrorX with stack trace starting after 'database-layer'
451
- * ```
452
- */
453
- cleanStackTrace(delimiter?: string): ErrorX<TMetadata>;
454
461
  /**
455
462
  * Converts the ErrorX instance to a detailed string representation.
456
463
  * Includes error name, message, code, timestamp, metadata, and stack trace.
package/dist/index.js CHANGED
@@ -40,6 +40,8 @@ var ErrorX = class _ErrorX extends Error {
40
40
  docsUrl;
41
41
  /** Where the error originated (service name, module, component) */
42
42
  source;
43
+ /** Original error that caused this error (preserves error chain) */
44
+ cause;
43
45
  /**
44
46
  * Creates a new ErrorX instance with enhanced error handling capabilities.
45
47
  *
@@ -83,15 +85,9 @@ var ErrorX = class _ErrorX extends Error {
83
85
  }
84
86
  const envConfig = _ErrorX.getConfig();
85
87
  const message = options.message?.trim() ? options.message : "An error occurred";
86
- super(message, { cause: options.cause });
87
- if (options.cause !== void 0 && !Object.hasOwn(this, "cause")) {
88
- Object.defineProperty(this, "cause", {
89
- value: options.cause,
90
- writable: true,
91
- enumerable: false,
92
- configurable: true
93
- });
94
- }
88
+ const convertedCause = _ErrorX.toErrorXCause(options.cause);
89
+ super(message);
90
+ this.cause = convertedCause;
95
91
  this.name = options.name ?? _ErrorX.getDefaultName();
96
92
  this.code = options.code != null ? String(options.code) : _ErrorX.generateDefaultCode(options.name);
97
93
  this.uiMessage = options.uiMessage;
@@ -111,8 +107,8 @@ var ErrorX = class _ErrorX extends Error {
111
107
  }
112
108
  }
113
109
  this.docsUrl = options.docsUrl ?? generatedDocsUrl;
114
- if (options.cause instanceof Error) {
115
- this.stack = _ErrorX.preserveOriginalStack(options.cause, this);
110
+ if (convertedCause?.stack) {
111
+ this.stack = _ErrorX.preserveOriginalStackFromCause(convertedCause, this);
116
112
  } else {
117
113
  if (typeof Error.captureStackTrace === "function") {
118
114
  Error.captureStackTrace(this, this.constructor);
@@ -127,6 +123,44 @@ var ErrorX = class _ErrorX extends Error {
127
123
  static getDefaultName() {
128
124
  return "Error";
129
125
  }
126
+ /**
127
+ * Converts any value to ErrorXCause format.
128
+ * @param value - Value to convert to ErrorXCause
129
+ * @returns ErrorXCause object or undefined if value is null/undefined
130
+ */
131
+ static toErrorXCause(value) {
132
+ if (value === void 0 || value === null) {
133
+ return void 0;
134
+ }
135
+ if (value instanceof Error) {
136
+ const cause = {
137
+ message: value.message
138
+ };
139
+ if (value.name) {
140
+ cause.name = value.name;
141
+ }
142
+ if (value.stack) {
143
+ cause.stack = value.stack;
144
+ }
145
+ return cause;
146
+ }
147
+ if (typeof value === "object") {
148
+ const obj = value;
149
+ const cause = {
150
+ message: String(obj.message || obj)
151
+ };
152
+ if (obj.name) {
153
+ cause.name = String(obj.name);
154
+ }
155
+ if (obj.stack) {
156
+ cause.stack = String(obj.stack);
157
+ }
158
+ return cause;
159
+ }
160
+ return {
161
+ message: String(value)
162
+ };
163
+ }
130
164
  /**
131
165
  * Configure global ErrorX settings.
132
166
  * This method allows you to set defaults for all ErrorX instances.
@@ -141,7 +175,8 @@ var ErrorX = class _ErrorX extends Error {
141
175
  * docsMap: {
142
176
  * 'AUTH_FAILED': 'authentication-errors',
143
177
  * 'DB_ERROR': 'database-errors'
144
- * }
178
+ * },
179
+ * cleanStackDelimiter: 'app-entry-point' // Trim stack traces after this line
145
180
  * })
146
181
  * ```
147
182
  */
@@ -155,6 +190,19 @@ var ErrorX = class _ErrorX extends Error {
155
190
  static getConfig() {
156
191
  return _ErrorX._config;
157
192
  }
193
+ /**
194
+ * Reset global configuration to null.
195
+ * Useful for testing or when you want to clear all configuration.
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * ErrorX.resetConfig()
200
+ * const config = ErrorX.getConfig() // null
201
+ * ```
202
+ */
203
+ static resetConfig() {
204
+ _ErrorX._config = null;
205
+ }
158
206
  /**
159
207
  * Validates HTTP status code to ensure it's within valid range (100-599)
160
208
  *
@@ -228,27 +276,38 @@ var ErrorX = class _ErrorX extends Error {
228
276
  }
229
277
  /**
230
278
  * Preserves the original error's stack trace while updating the error message.
231
- * Combines the new error's message with the original error's stack trace.
279
+ * Combines the new error's message with the original error's stack trace from ErrorXCause.
232
280
  *
233
- * @param originalError - The original error whose stack to preserve
281
+ * @param cause - The ErrorXCause containing the original stack to preserve
234
282
  * @param newError - The new error whose message to use
235
283
  * @returns Combined stack trace with new error message and original stack
236
284
  */
237
- static preserveOriginalStack(originalError, newError) {
238
- if (!originalError.stack) return newError.stack || "";
285
+ static preserveOriginalStackFromCause(cause, newError) {
286
+ if (!cause.stack) return newError.stack || "";
239
287
  const newErrorFirstLine = `${newError.name}: ${newError.message}`;
240
- const originalStackLines = originalError.stack.split("\n");
288
+ const originalStackLines = cause.stack.split("\n");
241
289
  const originalStackTrace = originalStackLines.slice(1);
242
290
  return [newErrorFirstLine, ...originalStackTrace].join("\n");
243
291
  }
244
292
  /**
245
- * Cleans the stack trace by removing ErrorX internal method calls.
293
+ * Cleans a stack trace by removing ErrorX internal method calls and optionally trimming after a delimiter.
246
294
  * This provides cleaner stack traces that focus on user code.
247
295
  *
248
- * @param stack - Raw stack trace to clean
249
- * @returns Cleaned stack trace without ErrorX internal calls
296
+ * @param stack - Raw stack trace string to clean
297
+ * @param delimiter - Optional delimiter to trim stack trace after (overrides config delimiter)
298
+ * @returns Cleaned stack trace without internal calls and optionally trimmed after delimiter
299
+ *
300
+ * @example
301
+ * ```typescript
302
+ * // Clean with pattern-based removal only
303
+ * const cleaned = ErrorX.cleanStack(error.stack)
304
+ *
305
+ * // Clean and trim after delimiter
306
+ * const trimmed = ErrorX.cleanStack(error.stack, 'my-app-entry')
307
+ * // Returns stack trace starting after the line containing 'my-app-entry'
308
+ * ```
250
309
  */
251
- static cleanStack(stack) {
310
+ static cleanStack(stack, delimiter) {
252
311
  if (!stack) return "";
253
312
  const config = _ErrorX.getConfig();
254
313
  const cleanStackConfig = config?.cleanStack ?? true;
@@ -272,30 +331,15 @@ var ErrorX = class _ErrorX extends Error {
272
331
  }
273
332
  cleanedLines.push(line);
274
333
  }
275
- return cleanedLines.join("\n");
276
- }
277
- /**
278
- * Processes an error's stack trace to trim it after a specified delimiter.
279
- * Useful for removing irrelevant stack frames before a specific function.
280
- *
281
- * @param error - Error whose stack to process
282
- * @param delimiter - String to search for in stack lines
283
- * @returns Processed stack trace starting after the delimiter
284
- *
285
- * @example
286
- * ```typescript
287
- * const processed = ErrorX.processErrorStack(error, 'my-app-entry')
288
- * // Returns stack trace starting after the line containing 'my-app-entry'
289
- * ```
290
- */
291
- static processErrorStack(error, delimiter) {
292
- let stack = error.stack ?? "";
293
- const stackLines = stack.split("\n");
294
- const delimiterIndex = stackLines.findIndex((line) => line.includes(delimiter));
295
- if (delimiterIndex !== -1) {
296
- stack = stackLines.slice(delimiterIndex + 1).join("\n");
334
+ let cleanedStack = cleanedLines.join("\n");
335
+ const activeDelimiter = delimiter ?? config?.cleanStackDelimiter;
336
+ if (activeDelimiter) {
337
+ const delimiterIndex = cleanedLines.findIndex((line) => line.includes(activeDelimiter));
338
+ if (delimiterIndex !== -1) {
339
+ cleanedStack = cleanedLines.slice(delimiterIndex + 1).join("\n");
340
+ }
297
341
  }
298
- return stack;
342
+ return cleanedStack;
299
343
  }
300
344
  /**
301
345
  * Creates a new ErrorX instance with additional metadata merged with existing metadata.
@@ -460,43 +504,6 @@ var ErrorX = class _ErrorX extends Error {
460
504
  const options = _ErrorX.convertUnknownToOptions(error);
461
505
  return new _ErrorX(options);
462
506
  }
463
- /**
464
- * Creates a new ErrorX instance with cleaned stack trace using the specified delimiter.
465
- * Returns the same instance if no delimiter is provided or no stack is available.
466
- *
467
- * @param delimiter - Optional string to search for in stack lines
468
- * @returns New ErrorX instance with cleaned stack trace, or the same instance if no cleaning needed
469
- *
470
- * @example
471
- * ```typescript
472
- * const error = new ErrorX({ message: 'Database error' })
473
- * const cleanedError = error.cleanStackTrace('database-layer')
474
- * // Returns new ErrorX with stack trace starting after 'database-layer'
475
- * ```
476
- */
477
- cleanStackTrace(delimiter) {
478
- if (delimiter && this.stack) {
479
- const options = {
480
- message: this.message,
481
- name: this.name,
482
- code: this.code,
483
- uiMessage: this.uiMessage,
484
- cause: this.cause,
485
- httpStatus: this.httpStatus,
486
- type: this.type,
487
- sourceUrl: this.sourceUrl,
488
- docsUrl: this.docsUrl,
489
- source: this.source
490
- };
491
- if (this.metadata !== void 0) {
492
- options.metadata = this.metadata;
493
- }
494
- const newError = new _ErrorX(options);
495
- newError.stack = _ErrorX.processErrorStack(this, delimiter);
496
- return newError;
497
- }
498
- return this;
499
- }
500
507
  /**
501
508
  * Converts the ErrorX instance to a detailed string representation.
502
509
  * Includes error name, message, code, timestamp, metadata, and stack trace.
@@ -584,34 +591,7 @@ ${this.stack}`;
584
591
  serialized.stack = this.stack;
585
592
  }
586
593
  if (this.cause) {
587
- if (this.cause instanceof Error) {
588
- const cause = {
589
- message: this.cause.message
590
- };
591
- if (this.cause.name) {
592
- cause.name = this.cause.name;
593
- }
594
- if (this.cause.stack) {
595
- cause.stack = this.cause.stack;
596
- }
597
- serialized.cause = cause;
598
- } else if (typeof this.cause === "object" && this.cause !== null) {
599
- const causeObj = this.cause;
600
- const cause = {
601
- message: String(causeObj.message || causeObj)
602
- };
603
- if (causeObj.name) {
604
- cause.name = String(causeObj.name);
605
- }
606
- if (causeObj.stack) {
607
- cause.stack = String(causeObj.stack);
608
- }
609
- serialized.cause = cause;
610
- } else {
611
- serialized.cause = {
612
- message: String(this.cause)
613
- };
614
- }
594
+ serialized.cause = this.cause;
615
595
  }
616
596
  return serialized;
617
597
  }
@@ -647,7 +627,8 @@ ${this.stack}`;
647
627
  type: serialized.type,
648
628
  sourceUrl: serialized.sourceUrl,
649
629
  docsUrl: serialized.docsUrl,
650
- source: serialized.source
630
+ source: serialized.source,
631
+ cause: serialized.cause
651
632
  };
652
633
  if (serialized.metadata !== void 0) {
653
634
  options.metadata = serialized.metadata;
@@ -657,19 +638,6 @@ ${this.stack}`;
657
638
  error.stack = serialized.stack;
658
639
  }
659
640
  error.timestamp = new Date(serialized.timestamp);
660
- if (serialized.cause) {
661
- const causeError = new Error(serialized.cause.message);
662
- if (serialized.cause.name) {
663
- causeError.name = serialized.cause.name;
664
- }
665
- if (serialized.cause.stack) {
666
- causeError.stack = serialized.cause.stack;
667
- }
668
- Object.defineProperty(error, "cause", {
669
- value: causeError,
670
- writable: true
671
- });
672
- }
673
641
  return error;
674
642
  }
675
643
  };