@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/README.md +11 -6
- package/dist/index.cjs +91 -123
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -36
- package/dist/index.d.ts +43 -36
- package/dist/index.js +91 -123
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,6 @@ yarn add @bombillazo/error-x
|
|
|
36
36
|
|
|
37
37
|
This library uses modern JavaScript features and ES2022 APIs. For browser compatibility, ensure your build tool (e.g., Vite, webpack, esbuild) is configured to target ES2022 or transpile accordingly.
|
|
38
38
|
|
|
39
|
-
|
|
40
39
|
> [!WARNING]
|
|
41
40
|
>
|
|
42
41
|
> This library is currently in pre-v1.0 development. While we strive to minimize breaking changes, the API may evolve based on feedback and real-world usage. We recommend pinning to specific versions and reviewing release notes when updating.
|
|
@@ -87,7 +86,7 @@ try {
|
|
|
87
86
|
### Constructor
|
|
88
87
|
|
|
89
88
|
```typescript
|
|
90
|
-
new ErrorX(
|
|
89
|
+
new ErrorX(input?: string | ErrorXOptions)
|
|
91
90
|
```
|
|
92
91
|
|
|
93
92
|
All parameters are optional. ErrorX uses sensible defaults:
|
|
@@ -149,6 +148,7 @@ All presets use **camelCase naming** and include:
|
|
|
149
148
|
- `type`: Set to `'http'` for all HTTP presets
|
|
150
149
|
|
|
151
150
|
**4xx Client Errors:**
|
|
151
|
+
|
|
152
152
|
`badRequest`, `unauthorized`, `paymentRequired`, `forbidden`, `notFound`, `methodNotAllowed`, `notAcceptable`, `proxyAuthenticationRequired`, `requestTimeout`, `conflict`, `gone`, `lengthRequired`, `preconditionFailed`, `payloadTooLarge`, `uriTooLong`, `unsupportedMediaType`, `rangeNotSatisfiable`, `expectationFailed`, `imATeapot`, `unprocessableEntity`, `locked`, `failedDependency`, `tooEarly`, `upgradeRequired`, `preconditionRequired`, `tooManyRequests`, `requestHeaderFieldsTooLarge`, `unavailableForLegalReasons`
|
|
153
153
|
|
|
154
154
|
**5xx Server Errors:**
|
|
@@ -281,14 +281,19 @@ const enriched = error.withMetadata({ b: 2 })
|
|
|
281
281
|
// enriched.metadata = { a: 1, b: 2 }
|
|
282
282
|
```
|
|
283
283
|
|
|
284
|
-
#### `
|
|
284
|
+
#### `ErrorX.cleanStack(stack?: string, delimiter?: string): string`
|
|
285
285
|
|
|
286
|
-
|
|
286
|
+
Cleans a stack trace by removing ErrorX internal calls and optionally trimming after a delimiter:
|
|
287
287
|
|
|
288
288
|
```typescript
|
|
289
289
|
const error = new ErrorX('test')
|
|
290
|
-
|
|
291
|
-
//
|
|
290
|
+
|
|
291
|
+
// Clean with pattern-based removal only
|
|
292
|
+
const cleaned = ErrorX.cleanStack(error.stack)
|
|
293
|
+
|
|
294
|
+
// Clean and trim after delimiter
|
|
295
|
+
const trimmed = ErrorX.cleanStack(error.stack, 'my-app-boundary')
|
|
296
|
+
// Returns stack trace starting after the line containing 'my-app-boundary'
|
|
292
297
|
```
|
|
293
298
|
|
|
294
299
|
#### `toJSON(): ErrorXSerialized`
|
package/dist/index.cjs
CHANGED
|
@@ -46,6 +46,8 @@ var ErrorX = class _ErrorX extends Error {
|
|
|
46
46
|
docsUrl;
|
|
47
47
|
/** Where the error originated (service name, module, component) */
|
|
48
48
|
source;
|
|
49
|
+
/** Original error that caused this error (preserves error chain) */
|
|
50
|
+
cause;
|
|
49
51
|
/**
|
|
50
52
|
* Creates a new ErrorX instance with enhanced error handling capabilities.
|
|
51
53
|
*
|
|
@@ -89,15 +91,9 @@ var ErrorX = class _ErrorX extends Error {
|
|
|
89
91
|
}
|
|
90
92
|
const envConfig = _ErrorX.getConfig();
|
|
91
93
|
const message = options.message?.trim() ? options.message : "An error occurred";
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
value: options.cause,
|
|
96
|
-
writable: true,
|
|
97
|
-
enumerable: false,
|
|
98
|
-
configurable: true
|
|
99
|
-
});
|
|
100
|
-
}
|
|
94
|
+
const convertedCause = _ErrorX.toErrorXCause(options.cause);
|
|
95
|
+
super(message);
|
|
96
|
+
this.cause = convertedCause;
|
|
101
97
|
this.name = options.name ?? _ErrorX.getDefaultName();
|
|
102
98
|
this.code = options.code != null ? String(options.code) : _ErrorX.generateDefaultCode(options.name);
|
|
103
99
|
this.uiMessage = options.uiMessage;
|
|
@@ -117,8 +113,8 @@ var ErrorX = class _ErrorX extends Error {
|
|
|
117
113
|
}
|
|
118
114
|
}
|
|
119
115
|
this.docsUrl = options.docsUrl ?? generatedDocsUrl;
|
|
120
|
-
if (
|
|
121
|
-
this.stack = _ErrorX.
|
|
116
|
+
if (convertedCause?.stack) {
|
|
117
|
+
this.stack = _ErrorX.preserveOriginalStackFromCause(convertedCause, this);
|
|
122
118
|
} else {
|
|
123
119
|
if (typeof Error.captureStackTrace === "function") {
|
|
124
120
|
Error.captureStackTrace(this, this.constructor);
|
|
@@ -133,6 +129,44 @@ var ErrorX = class _ErrorX extends Error {
|
|
|
133
129
|
static getDefaultName() {
|
|
134
130
|
return "Error";
|
|
135
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Converts any value to ErrorXCause format.
|
|
134
|
+
* @param value - Value to convert to ErrorXCause
|
|
135
|
+
* @returns ErrorXCause object or undefined if value is null/undefined
|
|
136
|
+
*/
|
|
137
|
+
static toErrorXCause(value) {
|
|
138
|
+
if (value === void 0 || value === null) {
|
|
139
|
+
return void 0;
|
|
140
|
+
}
|
|
141
|
+
if (value instanceof Error) {
|
|
142
|
+
const cause = {
|
|
143
|
+
message: value.message
|
|
144
|
+
};
|
|
145
|
+
if (value.name) {
|
|
146
|
+
cause.name = value.name;
|
|
147
|
+
}
|
|
148
|
+
if (value.stack) {
|
|
149
|
+
cause.stack = value.stack;
|
|
150
|
+
}
|
|
151
|
+
return cause;
|
|
152
|
+
}
|
|
153
|
+
if (typeof value === "object") {
|
|
154
|
+
const obj = value;
|
|
155
|
+
const cause = {
|
|
156
|
+
message: String(obj.message || obj)
|
|
157
|
+
};
|
|
158
|
+
if (obj.name) {
|
|
159
|
+
cause.name = String(obj.name);
|
|
160
|
+
}
|
|
161
|
+
if (obj.stack) {
|
|
162
|
+
cause.stack = String(obj.stack);
|
|
163
|
+
}
|
|
164
|
+
return cause;
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
message: String(value)
|
|
168
|
+
};
|
|
169
|
+
}
|
|
136
170
|
/**
|
|
137
171
|
* Configure global ErrorX settings.
|
|
138
172
|
* This method allows you to set defaults for all ErrorX instances.
|
|
@@ -147,7 +181,8 @@ var ErrorX = class _ErrorX extends Error {
|
|
|
147
181
|
* docsMap: {
|
|
148
182
|
* 'AUTH_FAILED': 'authentication-errors',
|
|
149
183
|
* 'DB_ERROR': 'database-errors'
|
|
150
|
-
* }
|
|
184
|
+
* },
|
|
185
|
+
* cleanStackDelimiter: 'app-entry-point' // Trim stack traces after this line
|
|
151
186
|
* })
|
|
152
187
|
* ```
|
|
153
188
|
*/
|
|
@@ -161,6 +196,19 @@ var ErrorX = class _ErrorX extends Error {
|
|
|
161
196
|
static getConfig() {
|
|
162
197
|
return _ErrorX._config;
|
|
163
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Reset global configuration to null.
|
|
201
|
+
* Useful for testing or when you want to clear all configuration.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```typescript
|
|
205
|
+
* ErrorX.resetConfig()
|
|
206
|
+
* const config = ErrorX.getConfig() // null
|
|
207
|
+
* ```
|
|
208
|
+
*/
|
|
209
|
+
static resetConfig() {
|
|
210
|
+
_ErrorX._config = null;
|
|
211
|
+
}
|
|
164
212
|
/**
|
|
165
213
|
* Validates HTTP status code to ensure it's within valid range (100-599)
|
|
166
214
|
*
|
|
@@ -234,27 +282,38 @@ var ErrorX = class _ErrorX extends Error {
|
|
|
234
282
|
}
|
|
235
283
|
/**
|
|
236
284
|
* Preserves the original error's stack trace while updating the error message.
|
|
237
|
-
* Combines the new error's message with the original error's stack trace.
|
|
285
|
+
* Combines the new error's message with the original error's stack trace from ErrorXCause.
|
|
238
286
|
*
|
|
239
|
-
* @param
|
|
287
|
+
* @param cause - The ErrorXCause containing the original stack to preserve
|
|
240
288
|
* @param newError - The new error whose message to use
|
|
241
289
|
* @returns Combined stack trace with new error message and original stack
|
|
242
290
|
*/
|
|
243
|
-
static
|
|
244
|
-
if (!
|
|
291
|
+
static preserveOriginalStackFromCause(cause, newError) {
|
|
292
|
+
if (!cause.stack) return newError.stack || "";
|
|
245
293
|
const newErrorFirstLine = `${newError.name}: ${newError.message}`;
|
|
246
|
-
const originalStackLines =
|
|
294
|
+
const originalStackLines = cause.stack.split("\n");
|
|
247
295
|
const originalStackTrace = originalStackLines.slice(1);
|
|
248
296
|
return [newErrorFirstLine, ...originalStackTrace].join("\n");
|
|
249
297
|
}
|
|
250
298
|
/**
|
|
251
|
-
* Cleans
|
|
299
|
+
* Cleans a stack trace by removing ErrorX internal method calls and optionally trimming after a delimiter.
|
|
252
300
|
* This provides cleaner stack traces that focus on user code.
|
|
253
301
|
*
|
|
254
|
-
* @param stack - Raw stack trace to clean
|
|
255
|
-
* @
|
|
302
|
+
* @param stack - Raw stack trace string to clean
|
|
303
|
+
* @param delimiter - Optional delimiter to trim stack trace after (overrides config delimiter)
|
|
304
|
+
* @returns Cleaned stack trace without internal calls and optionally trimmed after delimiter
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```typescript
|
|
308
|
+
* // Clean with pattern-based removal only
|
|
309
|
+
* const cleaned = ErrorX.cleanStack(error.stack)
|
|
310
|
+
*
|
|
311
|
+
* // Clean and trim after delimiter
|
|
312
|
+
* const trimmed = ErrorX.cleanStack(error.stack, 'my-app-entry')
|
|
313
|
+
* // Returns stack trace starting after the line containing 'my-app-entry'
|
|
314
|
+
* ```
|
|
256
315
|
*/
|
|
257
|
-
static cleanStack(stack) {
|
|
316
|
+
static cleanStack(stack, delimiter) {
|
|
258
317
|
if (!stack) return "";
|
|
259
318
|
const config = _ErrorX.getConfig();
|
|
260
319
|
const cleanStackConfig = config?.cleanStack ?? true;
|
|
@@ -278,30 +337,15 @@ var ErrorX = class _ErrorX extends Error {
|
|
|
278
337
|
}
|
|
279
338
|
cleanedLines.push(line);
|
|
280
339
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
* @param delimiter - String to search for in stack lines
|
|
289
|
-
* @returns Processed stack trace starting after the delimiter
|
|
290
|
-
*
|
|
291
|
-
* @example
|
|
292
|
-
* ```typescript
|
|
293
|
-
* const processed = ErrorX.processErrorStack(error, 'my-app-entry')
|
|
294
|
-
* // Returns stack trace starting after the line containing 'my-app-entry'
|
|
295
|
-
* ```
|
|
296
|
-
*/
|
|
297
|
-
static processErrorStack(error, delimiter) {
|
|
298
|
-
let stack = error.stack ?? "";
|
|
299
|
-
const stackLines = stack.split("\n");
|
|
300
|
-
const delimiterIndex = stackLines.findIndex((line) => line.includes(delimiter));
|
|
301
|
-
if (delimiterIndex !== -1) {
|
|
302
|
-
stack = stackLines.slice(delimiterIndex + 1).join("\n");
|
|
340
|
+
let cleanedStack = cleanedLines.join("\n");
|
|
341
|
+
const activeDelimiter = delimiter ?? config?.cleanStackDelimiter;
|
|
342
|
+
if (activeDelimiter) {
|
|
343
|
+
const delimiterIndex = cleanedLines.findIndex((line) => line.includes(activeDelimiter));
|
|
344
|
+
if (delimiterIndex !== -1) {
|
|
345
|
+
cleanedStack = cleanedLines.slice(delimiterIndex + 1).join("\n");
|
|
346
|
+
}
|
|
303
347
|
}
|
|
304
|
-
return
|
|
348
|
+
return cleanedStack;
|
|
305
349
|
}
|
|
306
350
|
/**
|
|
307
351
|
* Creates a new ErrorX instance with additional metadata merged with existing metadata.
|
|
@@ -466,43 +510,6 @@ var ErrorX = class _ErrorX extends Error {
|
|
|
466
510
|
const options = _ErrorX.convertUnknownToOptions(error);
|
|
467
511
|
return new _ErrorX(options);
|
|
468
512
|
}
|
|
469
|
-
/**
|
|
470
|
-
* Creates a new ErrorX instance with cleaned stack trace using the specified delimiter.
|
|
471
|
-
* Returns the same instance if no delimiter is provided or no stack is available.
|
|
472
|
-
*
|
|
473
|
-
* @param delimiter - Optional string to search for in stack lines
|
|
474
|
-
* @returns New ErrorX instance with cleaned stack trace, or the same instance if no cleaning needed
|
|
475
|
-
*
|
|
476
|
-
* @example
|
|
477
|
-
* ```typescript
|
|
478
|
-
* const error = new ErrorX({ message: 'Database error' })
|
|
479
|
-
* const cleanedError = error.cleanStackTrace('database-layer')
|
|
480
|
-
* // Returns new ErrorX with stack trace starting after 'database-layer'
|
|
481
|
-
* ```
|
|
482
|
-
*/
|
|
483
|
-
cleanStackTrace(delimiter) {
|
|
484
|
-
if (delimiter && this.stack) {
|
|
485
|
-
const options = {
|
|
486
|
-
message: this.message,
|
|
487
|
-
name: this.name,
|
|
488
|
-
code: this.code,
|
|
489
|
-
uiMessage: this.uiMessage,
|
|
490
|
-
cause: this.cause,
|
|
491
|
-
httpStatus: this.httpStatus,
|
|
492
|
-
type: this.type,
|
|
493
|
-
sourceUrl: this.sourceUrl,
|
|
494
|
-
docsUrl: this.docsUrl,
|
|
495
|
-
source: this.source
|
|
496
|
-
};
|
|
497
|
-
if (this.metadata !== void 0) {
|
|
498
|
-
options.metadata = this.metadata;
|
|
499
|
-
}
|
|
500
|
-
const newError = new _ErrorX(options);
|
|
501
|
-
newError.stack = _ErrorX.processErrorStack(this, delimiter);
|
|
502
|
-
return newError;
|
|
503
|
-
}
|
|
504
|
-
return this;
|
|
505
|
-
}
|
|
506
513
|
/**
|
|
507
514
|
* Converts the ErrorX instance to a detailed string representation.
|
|
508
515
|
* Includes error name, message, code, timestamp, metadata, and stack trace.
|
|
@@ -590,34 +597,7 @@ ${this.stack}`;
|
|
|
590
597
|
serialized.stack = this.stack;
|
|
591
598
|
}
|
|
592
599
|
if (this.cause) {
|
|
593
|
-
|
|
594
|
-
const cause = {
|
|
595
|
-
message: this.cause.message
|
|
596
|
-
};
|
|
597
|
-
if (this.cause.name) {
|
|
598
|
-
cause.name = this.cause.name;
|
|
599
|
-
}
|
|
600
|
-
if (this.cause.stack) {
|
|
601
|
-
cause.stack = this.cause.stack;
|
|
602
|
-
}
|
|
603
|
-
serialized.cause = cause;
|
|
604
|
-
} else if (typeof this.cause === "object" && this.cause !== null) {
|
|
605
|
-
const causeObj = this.cause;
|
|
606
|
-
const cause = {
|
|
607
|
-
message: String(causeObj.message || causeObj)
|
|
608
|
-
};
|
|
609
|
-
if (causeObj.name) {
|
|
610
|
-
cause.name = String(causeObj.name);
|
|
611
|
-
}
|
|
612
|
-
if (causeObj.stack) {
|
|
613
|
-
cause.stack = String(causeObj.stack);
|
|
614
|
-
}
|
|
615
|
-
serialized.cause = cause;
|
|
616
|
-
} else {
|
|
617
|
-
serialized.cause = {
|
|
618
|
-
message: String(this.cause)
|
|
619
|
-
};
|
|
620
|
-
}
|
|
600
|
+
serialized.cause = this.cause;
|
|
621
601
|
}
|
|
622
602
|
return serialized;
|
|
623
603
|
}
|
|
@@ -653,7 +633,8 @@ ${this.stack}`;
|
|
|
653
633
|
type: serialized.type,
|
|
654
634
|
sourceUrl: serialized.sourceUrl,
|
|
655
635
|
docsUrl: serialized.docsUrl,
|
|
656
|
-
source: serialized.source
|
|
636
|
+
source: serialized.source,
|
|
637
|
+
cause: serialized.cause
|
|
657
638
|
};
|
|
658
639
|
if (serialized.metadata !== void 0) {
|
|
659
640
|
options.metadata = serialized.metadata;
|
|
@@ -663,19 +644,6 @@ ${this.stack}`;
|
|
|
663
644
|
error.stack = serialized.stack;
|
|
664
645
|
}
|
|
665
646
|
error.timestamp = new Date(serialized.timestamp);
|
|
666
|
-
if (serialized.cause) {
|
|
667
|
-
const causeError = new Error(serialized.cause.message);
|
|
668
|
-
if (serialized.cause.name) {
|
|
669
|
-
causeError.name = serialized.cause.name;
|
|
670
|
-
}
|
|
671
|
-
if (serialized.cause.stack) {
|
|
672
|
-
causeError.stack = serialized.cause.stack;
|
|
673
|
-
}
|
|
674
|
-
Object.defineProperty(error, "cause", {
|
|
675
|
-
value: causeError,
|
|
676
|
-
writable: true
|
|
677
|
-
});
|
|
678
|
-
}
|
|
679
647
|
return error;
|
|
680
648
|
}
|
|
681
649
|
};
|