@bombillazo/error-x 0.5.0 → 0.5.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/README.md CHANGED
@@ -100,7 +100,7 @@ The base error class that extends the native `Error` with enhanced capabilities.
100
100
  | `chain` | `readonly ErrorX[]` | Full error sequence: `[this, parent, grandparent, ..., root]` |
101
101
  | `root` | `ErrorX \| undefined` | Error that started the whole error chain |
102
102
  | `parent` | `ErrorX \| undefined` | Error that immediately precedes this error in the chain |
103
- | `original` | `ErrorXCause \| undefined` | Stores the original non-ErrorX error used to create this error |
103
+ | `original` | `ErrorXSnapshot \| undefined` | Stores the original non-ErrorX error used to create this error |
104
104
 
105
105
  #### Static Methods
106
106
 
@@ -158,15 +158,79 @@ new ErrorX<UserMeta>({
158
158
 
159
159
  ### ErrorXOptions
160
160
 
161
- | Property | Type | Default | Description |
162
- | ---------- | --------------------------------- | --------------------- | ----------------------------------------- |
163
- | message | `string` | `'An error occurred'` | Technical error message |
164
- | name | `string` | `'Error'` | Error type/name |
165
- | code | `string \| number` | Auto-generated | Error identifier (UPPER_SNAKE_CASE) |
166
- | uiMessage | `string` | `undefined` | User-friendly message |
167
- | httpStatus | `number` | `undefined` | HTTP status code |
168
- | metadata | `TMetadata` | `undefined` | Additional context |
169
- | cause | `ErrorXCause \| Error \| unknown` | `undefined` | Error that caused this (builds the chain) |
161
+ | Property | Type | Default | Description |
162
+ | ---------- | ------------------ | --------------------- | ----------------------------------------- |
163
+ | message | `string` | `'An error occurred'` | Technical error message |
164
+ | name | `string` | `'Error'` | Error type/name |
165
+ | code | `string \| number` | Auto-generated | Error identifier (UPPER_SNAKE_CASE) |
166
+ | uiMessage | `string` | `undefined` | User-friendly message |
167
+ | httpStatus | `number` | `undefined` | HTTP status code |
168
+ | metadata | `TMetadata` | `undefined` | Additional context |
169
+ | cause | `unknown` | `undefined` | Error that caused this (builds the chain) |
170
+
171
+ ## Global Configuration
172
+
173
+ Configure stack trace cleaning and other global settings.
174
+
175
+ ```typescript
176
+ import { ErrorX } from "@bombillazo/error-x";
177
+
178
+ // Enable stack cleaning with custom delimiter
179
+ ErrorX.configure({
180
+ cleanStack: true,
181
+ cleanStackDelimiter: "my-app-entry",
182
+ });
183
+
184
+ // Custom patterns to remove from stack traces
185
+ ErrorX.configure({
186
+ cleanStack: ["node_modules", "internal/"],
187
+ });
188
+
189
+ // Disable stack cleaning
190
+ ErrorX.configure({ cleanStack: false });
191
+
192
+ // Get current config
193
+ const config = ErrorX.getConfig();
194
+
195
+ // Reset to defaults
196
+ ErrorX.resetConfig();
197
+ ```
198
+
199
+ ### Auto Code Generation
200
+
201
+ Error codes are automatically generated from names in UPPER_SNAKE_CASE when not provided:
202
+
203
+ ```typescript
204
+ new ErrorX({ name: "DatabaseError" });
205
+ // → code: 'DATABASE_ERROR'
206
+
207
+ new ErrorX({ name: "userAuthError" });
208
+ // → code: 'USER_AUTH_ERROR'
209
+
210
+ new ErrorX({ name: "API Timeout" });
211
+ // → code: 'API_TIMEOUT'
212
+ ```
213
+
214
+ ### Message Formatting
215
+
216
+ ErrorX does NOT auto-format messages. Messages are passed through as-is:
217
+
218
+ ```typescript
219
+ new ErrorX({ message: "test error" });
220
+ // → message: 'test error'
221
+
222
+ new ErrorX({ message: "Test error." });
223
+ // → message: 'Test error.'
224
+ ```
225
+
226
+ Empty or whitespace-only messages default to `'An error occurred'`:
227
+
228
+ ```typescript
229
+ new ErrorX({ message: "" });
230
+ // → message: 'An error occurred'
231
+ ```
232
+
233
+ Preset messages in specialized classes (HTTPErrorX, DBErrorX) are properly formatted with sentence casing and periods.
170
234
 
171
235
  ---
172
236
 
@@ -288,7 +352,7 @@ try {
288
352
  if (ErrorX.isErrorX(error)) {
289
353
  console.log(
290
354
  "Error chain:",
291
- error.chain.map((e) => e.name)
355
+ error.chain.map((e) => e.name),
292
356
  );
293
357
  console.log("Root cause:", error.root?.original);
294
358
  }
@@ -492,12 +556,12 @@ export class PaymentErrorX extends ErrorX<PaymentMetadata> {
492
556
  // Override create for proper typing
493
557
  static override create(
494
558
  presetKey?: PaymentPresetKey,
495
- overrides?: Partial<ErrorXOptions<PaymentMetadata>>
559
+ overrides?: Partial<ErrorXOptions<PaymentMetadata>>,
496
560
  ): PaymentErrorX {
497
561
  return ErrorX.create.call(
498
562
  PaymentErrorX,
499
563
  presetKey,
500
- overrides
564
+ overrides,
501
565
  ) as PaymentErrorX;
502
566
  }
503
567
  }
@@ -514,76 +578,6 @@ if (error instanceof PaymentErrorX) {
514
578
  }
515
579
  ```
516
580
 
517
- ---
518
-
519
- ## Other Usage
520
-
521
- ### Global Configuration
522
-
523
- Configure stack trace cleaning and other global settings.
524
-
525
- ```typescript
526
- import { ErrorX } from "@bombillazo/error-x";
527
-
528
- // Enable stack cleaning with custom delimiter
529
- ErrorX.configure({
530
- cleanStack: true,
531
- cleanStackDelimiter: "my-app-entry",
532
- });
533
-
534
- // Custom patterns to remove from stack traces
535
- ErrorX.configure({
536
- cleanStack: ["node_modules", "internal/"],
537
- });
538
-
539
- // Disable stack cleaning
540
- ErrorX.configure({ cleanStack: false });
541
-
542
- // Get current config
543
- const config = ErrorX.getConfig();
544
-
545
- // Reset to defaults
546
- ErrorX.resetConfig();
547
- ```
548
-
549
- ### Auto Code Generation
550
-
551
- Error codes are automatically generated from names in UPPER_SNAKE_CASE when not provided:
552
-
553
- ```typescript
554
- new ErrorX({ name: "DatabaseError" });
555
- // → code: 'DATABASE_ERROR'
556
-
557
- new ErrorX({ name: "userAuthError" });
558
- // → code: 'USER_AUTH_ERROR'
559
-
560
- new ErrorX({ name: "API Timeout" });
561
- // → code: 'API_TIMEOUT'
562
- ```
563
-
564
- ### Message Formatting
565
-
566
- ErrorX does NOT auto-format messages. Messages are passed through as-is:
567
-
568
- ```typescript
569
- new ErrorX({ message: "test error" });
570
- // → message: 'test error'
571
-
572
- new ErrorX({ message: "Test error." });
573
- // → message: 'Test error.'
574
- ```
575
-
576
- Empty or whitespace-only messages default to `'An error occurred'`:
577
-
578
- ```typescript
579
- new ErrorX({ message: "" });
580
- // → message: 'An error occurred'
581
- ```
582
-
583
- Preset messages in specialized classes (HTTPErrorX, DBErrorX) are properly formatted with sentence casing and periods.
584
-
585
- ---
586
-
587
581
  ## License
588
582
 
589
583
  MIT
package/dist/index.cjs CHANGED
@@ -132,38 +132,38 @@ var ErrorX = class _ErrorX extends Error {
132
132
  return "Error";
133
133
  }
134
134
  /**
135
- * Converts any value to ErrorXCause format.
136
- * @param value - Value to convert to ErrorXCause
137
- * @returns ErrorXCause object or undefined if value is null/undefined
135
+ * Converts any value to ErrorXSnapshot format.
136
+ * @param value - Value to convert to ErrorXSnapshot
137
+ * @returns ErrorXSnapshot object or undefined if value is null/undefined
138
138
  */
139
- static toErrorXCause(value) {
139
+ static toErrorXSnapshot(value) {
140
140
  if (value === void 0 || value === null) {
141
141
  return void 0;
142
142
  }
143
143
  if (value instanceof Error) {
144
- const cause = {
144
+ const snapshot = {
145
145
  message: value.message
146
146
  };
147
147
  if (value.name) {
148
- cause.name = value.name;
148
+ snapshot.name = value.name;
149
149
  }
150
150
  if (value.stack) {
151
- cause.stack = value.stack;
151
+ snapshot.stack = value.stack;
152
152
  }
153
- return cause;
153
+ return snapshot;
154
154
  }
155
155
  if (typeof value === "object") {
156
156
  const obj = value;
157
- const cause = {
157
+ const snapshot = {
158
158
  message: String(obj.message || obj)
159
159
  };
160
160
  if (obj.name) {
161
- cause.name = String(obj.name);
161
+ snapshot.name = String(obj.name);
162
162
  }
163
163
  if (obj.stack) {
164
- cause.stack = String(obj.stack);
164
+ snapshot.stack = String(obj.stack);
165
165
  }
166
- return cause;
166
+ return snapshot;
167
167
  }
168
168
  return {
169
169
  message: String(value)
@@ -324,7 +324,10 @@ var ErrorX = class _ErrorX extends Error {
324
324
  name: this.name,
325
325
  code: this.code,
326
326
  uiMessage: this.uiMessage,
327
- metadata: { ...this.metadata ?? {}, ...additionalMetadata },
327
+ metadata: {
328
+ ...this.metadata ?? {},
329
+ ...additionalMetadata
330
+ },
328
331
  httpStatus: this.httpStatus
329
332
  };
330
333
  const newError = new _ErrorX(options);
@@ -444,7 +447,7 @@ var ErrorX = class _ErrorX extends Error {
444
447
  metadata: extractedOptions.metadata || overrides.metadata ? deepmergeTs.deepmerge(extractedOptions.metadata ?? {}, overrides.metadata ?? {}) : void 0
445
448
  } : extractedOptions;
446
449
  const error = new _ErrorX(finalOptions);
447
- error.original = _ErrorX.toErrorXCause(payload);
450
+ error.original = _ErrorX.toErrorXSnapshot(payload);
448
451
  if (payload instanceof Error && payload.stack) {
449
452
  error.stack = payload.stack;
450
453
  }
@@ -530,16 +533,22 @@ ${this.stack}`;
530
533
  }
531
534
  if (this._chain.length > 1) {
532
535
  serialized.chain = this._chain.map((err) => {
533
- const causeEntry = {
534
- message: err.message
535
- };
536
- if (err.name) {
537
- causeEntry.name = err.name;
536
+ let safeMetadata2;
537
+ if (err.metadata) {
538
+ safeMetadata2 = JSON.parse(safeStringify__default.default(err.metadata));
538
539
  }
539
- if (err.stack) {
540
- causeEntry.stack = err.stack;
541
- }
542
- return causeEntry;
540
+ const chainEntry = {
541
+ name: err.name,
542
+ message: err.message,
543
+ code: err.code,
544
+ uiMessage: err.uiMessage,
545
+ metadata: safeMetadata2,
546
+ timestamp: err.timestamp
547
+ };
548
+ if (err.httpStatus !== void 0) chainEntry.httpStatus = err.httpStatus;
549
+ if (err.stack) chainEntry.stack = err.stack;
550
+ if (err.original) chainEntry.original = err.original;
551
+ return chainEntry;
543
552
  });
544
553
  }
545
554
  return serialized;
@@ -593,16 +602,28 @@ ${this.stack}`;
593
602
  const chainErrorOptions = {
594
603
  message: causeData.message
595
604
  };
596
- if (causeData.name) {
597
- chainErrorOptions.name = causeData.name;
598
- }
605
+ if (causeData.name) chainErrorOptions.name = causeData.name;
606
+ if ("code" in causeData && causeData.code !== void 0)
607
+ chainErrorOptions.code = causeData.code;
608
+ if ("uiMessage" in causeData && causeData.uiMessage !== void 0)
609
+ chainErrorOptions.uiMessage = causeData.uiMessage;
610
+ if ("metadata" in causeData && causeData.metadata !== void 0)
611
+ chainErrorOptions.metadata = causeData.metadata;
612
+ if ("httpStatus" in causeData && causeData.httpStatus !== void 0)
613
+ chainErrorOptions.httpStatus = causeData.httpStatus;
599
614
  const chainError = new _ErrorX(chainErrorOptions);
600
- if (causeData.stack) {
601
- chainError.stack = causeData.stack;
602
- }
615
+ if (causeData.stack) chainError.stack = causeData.stack;
616
+ if ("timestamp" in causeData && causeData.timestamp !== void 0)
617
+ chainError.timestamp = causeData.timestamp;
618
+ if ("original" in causeData && causeData.original) chainError.original = causeData.original;
603
619
  chainErrors.push(chainError);
604
620
  }
605
- error._chain = chainErrors;
621
+ for (let i = 0; i < chainErrors.length; i++) {
622
+ const chainError = chainErrors[i];
623
+ if (chainError) {
624
+ chainError._chain = chainErrors.slice(i);
625
+ }
626
+ }
606
627
  }
607
628
  return error;
608
629
  }