error-message-utils 1.2.8 → 1.2.10

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
@@ -1,192 +1,268 @@
1
1
  # Error Message Utils
2
2
 
3
- The `error-message-utils` package simplifies error management in your web applications and RESTful APIs. It ensures consistent and scalable handling of error messages, saving you time and effort. Moreover, it gives you the ability to assign custom error codes so all possible cases can be handled accordingly.
3
+ `error-message-utils` helps TypeScript and JavaScript apps turn unknown errors into a
4
+ consistent shape:
4
5
 
6
+ - a readable message
7
+ - a stable error code
8
+ - optional extra data
5
9
 
10
+ Use `Exception` for most application code. Use `encodeError` and `decodeError` when you need to
11
+ send or receive an error code inside a plain string.
6
12
 
13
+ ## Install
7
14
 
15
+ ```bash
16
+ npm i -S error-message-utils
17
+ ```
8
18
 
9
- </br>
19
+ ## Recommended Usage: Exception
10
20
 
11
- ## Getting Started
21
+ `Exception` is an `Error` subclass that stores a normalized message, a code, and optional data.
12
22
 
13
- Install the package:
14
- ```bash
15
- npm i -S error-message-utils
23
+ ```typescript
24
+ import { Exception } from 'error-message-utils';
25
+
26
+ throw new Exception('The provided email is already in use.', 'EMAIL_EXISTS', {
27
+ field: 'email',
28
+ });
16
29
  ```
17
30
 
18
- ### Examples
31
+ ```typescript
32
+ const exception = new Exception('Request failed', 'REQUEST_FAILED');
19
33
 
20
- Encode an error:
34
+ exception instanceof Error; // true
35
+ exception instanceof Exception; // true
36
+ exception.name; // 'Exception'
37
+ exception.message; // 'Request failed'
38
+ exception.code; // 'REQUEST_FAILED'
39
+ exception.data; // null
40
+ exception.toString(); // 'Request failed{(REQUEST_FAILED)}'
41
+ exception.toRecord();
42
+ // {
43
+ // message: 'Request failed',
44
+ // code: 'REQUEST_FAILED',
45
+ // data: null,
46
+ // }
47
+ ```
48
+
49
+ ### Wrap Unknown Errors
50
+
51
+ When you catch an unknown error, pass it to `Exception`. The package will extract the best message
52
+ and code it can find.
21
53
 
22
54
  ```typescript
23
- import { encodeError } from 'error-message-utils';
24
-
25
- if (emailExists()) {
26
- throw new Error(encodeError(
27
- 'The provided email is already in use.',
28
- 'EMAIL_EXISTS'
29
- ));
30
- // 'The provided email is already in use.{(EMAIL_EXISTS)}'
55
+ import { Exception } from 'error-message-utils';
56
+
57
+ try {
58
+ await sendReceiptEmail();
59
+ } catch (error) {
60
+ throw new Exception(error, 'RECEIPT_EMAIL_FAILED', {
61
+ operation: 'sendReceiptEmail',
62
+ });
31
63
  }
32
64
  ```
33
65
 
66
+ ### Extend Exception
34
67
 
35
- <br/>
36
-
37
- Decode an error:
68
+ Create small domain-specific exception classes when your app has a stable set of error codes.
38
69
 
39
70
  ```typescript
40
- import { decodeError } from 'error-message-utils';
71
+ import { Exception } from 'error-message-utils';
41
72
 
42
- decodeError('The provided email is already in use.{(EMAIL_EXISTS)}');
43
- // {
44
- // message: 'The provided email is already in use.',
45
- // code: 'EMAIL_EXISTS'
46
- // }
73
+ const USER_ERROR_CODES = {
74
+ EmailTaken: 'USER_EMAIL_TAKEN',
75
+ Unauthorized: 'USER_UNAUTHORIZED',
76
+ } as const;
77
+
78
+ type IUserErrorCode = (typeof USER_ERROR_CODES)[keyof typeof USER_ERROR_CODES];
79
+
80
+ export class UserException extends Exception {
81
+ public constructor(message: string, code: IUserErrorCode, data?: unknown) {
82
+ super(message, code, data);
83
+ this.name = 'UserException';
84
+ }
85
+ }
86
+
87
+ throw new UserException(
88
+ 'The provided email is already in use.',
89
+ USER_ERROR_CODES.EmailTaken,
90
+ { field: 'email' },
91
+ );
47
92
  ```
48
93
 
94
+ ## Common Tasks
49
95
 
50
- <br/>
96
+ ### Extract a Message
51
97
 
52
- Error messages can be extracted recursively from complex structures, including nested `cause` data properties from `Error` instances:
98
+ `extractMessage` accepts any value and returns the best readable message it can find.
53
99
 
54
100
  ```typescript
55
101
  import { extractMessage } from 'error-message-utils';
56
102
 
57
- extractMessage(new Error('Top level error', {
58
- cause: new Error('First nested cause', {
59
- cause: new Error('Second nested cause'),
103
+ extractMessage(
104
+ new Error('Top level error', {
105
+ cause: new Error('First nested cause', {
106
+ cause: new Error('Second nested cause'),
107
+ }),
60
108
  }),
61
- }));
109
+ );
62
110
  // 'Top level error; [CAUSE]: First nested cause; [CAUSE]: Second nested cause'
63
111
 
64
-
65
- extractMessage({
66
- message: {
67
- err: {
68
- message: 'This error message is nested deeply!'
69
- }
70
- }
112
+ extractMessage({
113
+ message: {
114
+ err: {
115
+ message: 'This error message is nested deeply!',
116
+ },
117
+ },
71
118
  });
72
119
  // 'This error message is nested deeply!'
73
120
  ```
74
121
 
75
-
76
- <br/>
77
-
78
- Extract detailed error messages from [Zod](https://zod.dev/basics) parsing errors.
122
+ Zod errors are formatted with their first issue message and path.
79
123
 
80
124
  ```typescript
81
- import { z } from "zod";
125
+ import { z } from 'zod';
82
126
  import { extractMessage } from 'error-message-utils';
83
127
 
84
- z.object({ name: z.string() }).parse({ name: 123 });
85
- // Invalid input: expected string, received number (name)
128
+ const result = z.object({ name: z.string() }).safeParse({ name: 123 });
86
129
 
87
- z.object({
88
- name: z.object({ age: z.number() })
89
- }).parse({ name: { age: 'not a number' } })
90
- // Invalid input: expected string, received number (someDict.innerList.0.someProp)
130
+ if (!result.success) {
131
+ extractMessage(result.error);
132
+ // 'Invalid input: expected string, received number (name)'
133
+ }
91
134
  ```
92
135
 
136
+ ### Get an Error Code
93
137
 
94
- <br/>
95
-
96
- Identify encoded errors:
138
+ Use `getErrorCode` when you only need the resolved code.
97
139
 
98
140
  ```typescript
99
- import { isEncodedError, encodeError, hasErrorCode } from 'error-message-utils';
141
+ import { Exception, getErrorCode } from 'error-message-utils';
142
+
143
+ const exception = new Exception('Access denied', 'ACCESS_DENIED');
100
144
 
101
- isEncodedError('Some random unencoded error');
102
- // false
145
+ getErrorCode(exception); // 'ACCESS_DENIED'
146
+ getErrorCode('Access denied'); // null
147
+ ```
103
148
 
104
- isEncodedError(new Error('Some random unencoded error'));
105
- // false
149
+ Use `hasErrorCode` when you want a direct boolean check.
106
150
 
107
- isEncodedError(encodeError('Some unknown error.', 'NASTY_ERROR'));
108
- // true
151
+ ```typescript
152
+ import { Exception, hasErrorCode } from 'error-message-utils';
109
153
 
110
- isEncodedError(encodeError(new Error('Some unknown error.'), 'NASTY_ERROR'));
111
- // true
154
+ const exception = new Exception('Access denied', 'ACCESS_DENIED');
112
155
 
113
- hasErrorCode(new Error('Oops, something went wrong.'), 'MY_ERROR_CODE'); // false
114
- hasErrorCode(
115
- new Exception('Oops, something went wrong.', 'MY_ERROR_CODE'),
116
- 'MY_ERROR_CODE'
117
- );
118
- // true
156
+ hasErrorCode(exception, 'ACCESS_DENIED'); // true
157
+ hasErrorCode(exception, 'PAYMENT_FAILED'); // false
119
158
  ```
120
159
 
160
+ ### Encode and Decode Plain Strings
121
161
 
122
- <br/>
123
-
124
- In some cases, you may want to check whether the extracted error matches the default message provided by this package:
162
+ `encodeError` and `decodeError` are lower-level helpers for systems that can only pass string
163
+ messages.
125
164
 
126
165
  ```typescript
127
- import { isDefaultErrorMessage } from 'error-message-utils';
166
+ import { decodeError, encodeError } from 'error-message-utils';
128
167
 
129
- const DEFAULT_MESSAGE: string = 'The error message could not be extracted, check the logs for more information.';
168
+ const encodedError = encodeError(
169
+ 'The provided email is already in use.',
170
+ 'EMAIL_EXISTS',
171
+ );
130
172
 
131
- isDefaultErrorMessage(DEFAULT_MESSAGE);
132
- // true
173
+ encodedError;
174
+ // 'The provided email is already in use.{(EMAIL_EXISTS)}'
133
175
 
134
- isDefaultErrorMessage(`${DEFAULT_MESSAGE} and something else...`);
135
- // false
136
-
137
- isDefaultErrorMessage(`${DEFAULT_MESSAGE} and something else...`, true);
138
- // true
176
+ decodeError(encodedError);
177
+ // {
178
+ // message: 'The provided email is already in use.',
179
+ // code: 'EMAIL_EXISTS',
180
+ // data: null,
181
+ // }
139
182
  ```
140
183
 
184
+ ### Detect Resolved Codes with isEncodedError
141
185
 
186
+ `isEncodedError` returns `true` when an error resolves to a non-default code. For direct code
187
+ inspection, prefer `getErrorCode` or `hasErrorCode`.
142
188
 
189
+ ```typescript
190
+ import { encodeError, isEncodedError } from 'error-message-utils';
191
+
192
+ isEncodedError('Some random unencoded error'); // false
193
+ isEncodedError(new Error('Some random unencoded error')); // false
194
+ isEncodedError(encodeError('Some unknown error.', 'UNKNOWN_ERROR')); // true
195
+ ```
143
196
 
144
- <br/>
197
+ ### Check the Default Message
145
198
 
146
- Improve code consistency by handling errors with the `Exception` utility class:
199
+ Use `isDefaultErrorMessage` to detect the fallback message returned when no useful message can be
200
+ extracted.
147
201
 
148
202
  ```typescript
149
- import { Exception } from 'error-message-utils';
203
+ import { DEFAULT_MESSAGE, isDefaultErrorMessage } from 'error-message-utils';
150
204
 
151
- const exception = new Exception('Request failed', 'SOME_ERROR_CODE');
152
- exception instanceof Error; // true
153
- exception instanceof Exception; // true
154
- exception.message; // "Request failed"
155
- exception.code; // "SOME_ERROR_CODE"
156
- exception.toString(); // "Request failed{(SOME_ERROR_CODE)}"
157
- exception.toRecord();
158
- // {
159
- // message: "Request failed",
160
- // code: "SOME_ERROR_CODE",
161
- // data: null,
162
- // }
205
+ isDefaultErrorMessage(DEFAULT_MESSAGE); // true
206
+ isDefaultErrorMessage(`${DEFAULT_MESSAGE} More details.`); // true
207
+ isDefaultErrorMessage(`${DEFAULT_MESSAGE} More details.`, true); // false
208
+ ```
209
+
210
+ ## Public API
211
+
212
+ Import public items from the package root:
213
+
214
+ ```typescript
215
+ import {
216
+ DEFAULT_CODE,
217
+ DEFAULT_MESSAGE,
218
+ Exception,
219
+ decodeError,
220
+ encodeError,
221
+ extractMessage,
222
+ getErrorCode,
223
+ hasErrorCode,
224
+ isDefaultErrorMessage,
225
+ isEncodedError,
226
+ type IDecodedError,
227
+ type IErrorCode,
228
+ type IErrorCodeCarrier,
229
+ type IExceptionRecord,
230
+ } from 'error-message-utils';
163
231
  ```
164
232
 
233
+ ### Classes
234
+
235
+ | Export | Description |
236
+ | --- | --- |
237
+ | `Exception` | An `Error` subclass that normalizes an unknown error into `message`, `code`, and `data`. It can also serialize itself with `toString()` or `toRecord()`. |
165
238
 
166
- <br/>
239
+ ### Functions
167
240
 
168
- ## Types
241
+ | Export | Signature | Description |
242
+ | --- | --- | --- |
243
+ | `extractMessage` | `(error: unknown) => string` | Extracts the best readable message from strings, `Error` instances, nested error-like objects, `Error.cause` chains, arrays, plain objects, and Zod errors. Returns `DEFAULT_MESSAGE` when no useful message can be extracted. |
244
+ | `encodeError` | `(error: unknown, code: IErrorCode) => string` | Extracts a message from `error` and appends the wrapped code at the end of the message. |
245
+ | `decodeError` | `(error: unknown) => IDecodedError` | Extracts a message, resolves a code from an encoded message or code-carrying object, and returns `{ message, code, data }`. |
246
+ | `isEncodedError` | `(error: unknown) => boolean` | Returns `true` when `decodeError(error).code` resolves to a non-default code. |
247
+ | `getErrorCode` | `(error: unknown) => IErrorCode \| null` | Returns the resolved non-default code, or `null` when no non-default code is found. |
248
+ | `hasErrorCode` | `(error: unknown, code: IErrorCode) => boolean` | Checks whether an error resolves to the provided code. Raw code values are compared with strict equality. |
249
+ | `isDefaultErrorMessage` | `(value: string, fullMatch?: boolean) => boolean` | Checks whether a string contains `DEFAULT_MESSAGE`. Pass `true` as the second argument to require an exact match. |
250
+
251
+ ### Types
169
252
 
170
253
  ```typescript
171
- /**
172
- * Error Code
173
- * The code that is inserted when encoding an error. If none is provided or none can be extracted, it defaults to -1.
174
- */
175
254
  type IErrorCode = string | number;
176
255
 
177
- /**
178
- * Decoded Error
179
- * The object obtained when an error is decoded. Keep in mind that if the error message or the code cannot be extracted for any reason, the default values will be set instead.
180
- */
181
256
  type IDecodedError = {
182
- message: string,
183
- code: IErrorCode,
257
+ message: string;
258
+ code: IErrorCode;
259
+ data: unknown | null;
184
260
  };
185
261
 
186
- /**
187
- * Exception Record
188
- * The record type for the Exception class.
189
- */
262
+ type IErrorCodeCarrier = {
263
+ code: IErrorCode;
264
+ } & Record<string, unknown>;
265
+
190
266
  type IExceptionRecord = {
191
267
  message: string;
192
268
  code: IErrorCode;
@@ -194,45 +270,33 @@ type IExceptionRecord = {
194
270
  };
195
271
  ```
196
272
 
273
+ | Export | Description |
274
+ | --- | --- |
275
+ | `IErrorCode` | The supported type for application error codes. |
276
+ | `IDecodedError` | The object returned by `decodeError`. |
277
+ | `IErrorCodeCarrier` | A plain object shape that can provide a code to `decodeError`, `getErrorCode`, `hasErrorCode`, and `Exception`. |
278
+ | `IExceptionRecord` | The serializable object returned by `Exception.toRecord()`. |
197
279
 
198
- <br/>
199
-
200
- ## Constants
280
+ ### Constants
201
281
 
202
282
  ```typescript
203
- // the default message if none can be extracted
204
- const DEFAULT_MESSAGE: string =
205
- 'The error message could not be extracted, check the logs for more information.';
283
+ const DEFAULT_CODE = -1;
206
284
 
207
- // the default code if none was provided or could not be extracted
208
- const DEFAULT_CODE: IErrorCode = -1;
285
+ const DEFAULT_MESSAGE =
286
+ 'The error message could not be extracted, check the logs for more information.';
209
287
  ```
210
288
 
289
+ | Export | Description |
290
+ | --- | --- |
291
+ | `DEFAULT_CODE` | The fallback code used when no code can be resolved. |
292
+ | `DEFAULT_MESSAGE` | The fallback message used when no readable message can be extracted. |
211
293
 
212
-
213
- <br/>
214
-
215
- ## Built With
216
-
217
- - TypeScript
218
-
219
-
220
-
221
-
222
- <br/>
223
-
224
- ## Running the Tests
294
+ ## Running Tests
225
295
 
226
296
  ```bash
227
- npm run test
297
+ npm test
228
298
  ```
229
299
 
230
-
231
-
232
-
233
-
234
- <br/>
235
-
236
300
  ## License
237
301
 
238
302
  [MIT](https://choosealicense.com/licenses/mit/)
@@ -1,7 +1,4 @@
1
- import { IErrorCode, IDecodedError } from '../shared/types.js';
2
- /**
3
- * General errors
4
- */
1
+ import type { IErrorCode, IDecodedError } from '../shared/types.js';
5
2
  /**
6
3
  * Attempts to extract an error message from an error that could be anything. If it fails to do so,
7
4
  * it returns the default message.
@@ -26,6 +23,9 @@ export declare const encodeError: (error: any, code: IErrorCode) => string;
26
23
  * @returns The decoded error, containing the message and the code.
27
24
  */
28
25
  export declare const decodeError: (error: any) => IDecodedError;
26
+ /**
27
+ * Misc helpers
28
+ */
29
29
  /**
30
30
  * Determines if a given error (in any format) is an error encoded by this package.
31
31
  * @param error The error to be checked, can be of any type.
@@ -33,8 +33,11 @@ export declare const decodeError: (error: any) => IDecodedError;
33
33
  */
34
34
  export declare const isEncodedError: (error: any) => boolean;
35
35
  /**
36
- * Misc helpers
36
+ * Retrieves the error code from a given error, or null if it matches the default code.
37
+ * @param error The error to extract the code from.
38
+ * @returns The error code or null if it matches the default code.
37
39
  */
40
+ export declare const getErrorCode: (error: any) => IErrorCode | null;
38
41
  /**
39
42
  * Checks if the given error matches the specified error code.
40
43
  * @param error The error to be checked, can be of any type.
@@ -1 +1 @@
1
- import{ZodError}from"zod";import{DEFAULT_CODE,DEFAULT_MESSAGE}from"../shared/constants.js";import{wrapCode,unwrapCode}from"../utils/index.js";import{extractZodErrorMessage}from"./utilities.js";export const extractMessage=r=>{if("string"==typeof r&&r.length)return r;if(r instanceof ZodError)return extractZodErrorMessage(r);if(r instanceof Error&&r.message)return r.cause?`${r.message}; [CAUSE]: ${extractMessage(r.cause)}`:r.message;if(r&&"object"==typeof r){if(r.message)return extractMessage(r.message);if(r.msg)return extractMessage(r.msg);if(r.error)return extractMessage(r.error);if(r.err)return extractMessage(r.err);if(r.errors)return extractMessage(r.errors);if(r.errs)return extractMessage(r.errs);if(r.reason)return extractMessage(r.reason);if(r.reasons)return extractMessage(r.reasons);if(r.issue)return extractMessage(r.issue);if(r.issues)return extractMessage(r.issues);if(r.data)return extractMessage(r.data);try{return JSON.stringify(r)}catch(e){console.error("Error during extractMessage:"),console.error("Original Error: ",r),console.error("JSON.stringify Error:",e)}}return DEFAULT_MESSAGE};export const encodeError=(r,e)=>`${extractMessage(r)}${wrapCode(e)}`;export const decodeError=r=>{const e=extractMessage(r),{code:s,startsAt:t}=unwrapCode(e);return{message:t>0?e.slice(0,t):e,code:s}};export const isEncodedError=r=>decodeError(r).code!==DEFAULT_CODE;export const hasErrorCode=(r,e)=>null!==r&&(r===e||"object"==typeof r&&"code"in r&&r.code===e||decodeError(r).code===e);export const isDefaultErrorMessage=(r,e=!1)=>e?r===DEFAULT_MESSAGE:"string"==typeof r&&r.includes(DEFAULT_MESSAGE);
1
+ import{ZodError}from"zod";import{DEFAULT_CODE,DEFAULT_MESSAGE}from"../shared/constants.js";import{wrapCode,unwrapCode}from"../utils/index.js";import{extractZodErrorMessage,getDecodedErrorCode}from"./utilities.js";const __extractMessage=(r,e)=>{if("string"==typeof r&&r.length)return r;if(r instanceof ZodError)return extractZodErrorMessage(r);if(r&&"object"==typeof r){if(e.has(r))return DEFAULT_MESSAGE;e.add(r)}if(r instanceof Error&&r.message)return r.cause?`${r.message}; [CAUSE]: ${__extractMessage(r.cause,e)}`:r.message;if(r&&"object"==typeof r){if(r.message)return __extractMessage(r.message,e);if(r.msg)return __extractMessage(r.msg,e);if(r.error)return __extractMessage(r.error,e);if(r.err)return __extractMessage(r.err,e);if(r.errors)return __extractMessage(r.errors,e);if(r.errs)return __extractMessage(r.errs,e);if(r.reason)return __extractMessage(r.reason,e);if(r.reasons)return __extractMessage(r.reasons,e);if(r.issue)return __extractMessage(r.issue,e);if(r.issues)return __extractMessage(r.issues,e);if(r.data)return __extractMessage(r.data,e);try{return JSON.stringify(r)}catch(e){console.error("Error during extractMessage:"),console.error("Original Error: ",r),console.error("JSON.stringify Error:",e)}}return DEFAULT_MESSAGE};export const extractMessage=r=>__extractMessage(r,new WeakSet);export const encodeError=(r,e)=>`${extractMessage(r)}${wrapCode(e)}`;export const decodeError=r=>{const e=extractMessage(r),{code:t,startsAt:s}=unwrapCode(e);return{message:s>0?e.slice(0,s):e,code:getDecodedErrorCode(r,t),data:null!==r&&"object"==typeof r&&"data"in r?r.data:null}};export const isEncodedError=r=>decodeError(r).code!==DEFAULT_CODE;export const getErrorCode=r=>{const{code:e}=decodeError(r);return e!==DEFAULT_CODE?e:null};export const hasErrorCode=(r,e)=>null!==r&&(r===e||decodeError(r).code===e);export const isDefaultErrorMessage=(r,e=!1)=>e?r===DEFAULT_MESSAGE:"string"==typeof r&&r.includes(DEFAULT_MESSAGE);
@@ -1,4 +1,5 @@
1
1
  import { ZodError } from 'zod';
2
+ import { IErrorCode } from '../shared/types.js';
2
3
  /**
3
4
  * Attempts to extract a Zod error message from a ZodError instance. If unable to do so, it returns
4
5
  * the default error message.
@@ -6,3 +7,10 @@ import { ZodError } from 'zod';
6
7
  * @returns The extracted error message or the default message.
7
8
  */
8
9
  export declare const extractZodErrorMessage: (error: ZodError) => string;
10
+ /**
11
+ * Resolves the decoded error code from the unwrapped message code or an Exception-style object.
12
+ * @param error The unknown error object to inspect.
13
+ * @param unwrappedCode The code unwrapped from the extracted error message.
14
+ * @returns The decoded error code or the default code.
15
+ */
16
+ export declare const getDecodedErrorCode: (error: unknown, unwrappedCode: IErrorCode) => IErrorCode;
@@ -1 +1 @@
1
- import{DEFAULT_MESSAGE}from"../shared/constants.js";const __extractPathFromZodError=s=>s&&Array.isArray(s.issues)&&s.issues.length&&Array.isArray(s.issues[0].path)&&s.issues[0].path.length?s.issues[0].path.join("."):"Unknown path";export const extractZodErrorMessage=s=>s&&Array.isArray(s.issues)&&s.issues.length&&Array.isArray(s.issues[0].path)&&s.issues[0].message?`${s.issues[0].message} (${__extractPathFromZodError(s)})`:DEFAULT_MESSAGE;
1
+ import{DEFAULT_CODE,DEFAULT_MESSAGE}from"../shared/constants.js";const __extractPathFromZodError=r=>r&&Array.isArray(r.issues)&&r.issues.length&&Array.isArray(r.issues[0].path)&&r.issues[0].path.length?r.issues[0].path.join("."):"Unknown path";export const extractZodErrorMessage=r=>r&&Array.isArray(r.issues)&&r.issues.length&&Array.isArray(r.issues[0].path)&&r.issues[0].message?`${r.issues[0].message} (${__extractPathFromZodError(r)})`:DEFAULT_MESSAGE;const __isErrorCodeCarrier=r=>"object"==typeof r&&null!==r&&"code"in r&&("string"==typeof r.code||"number"==typeof r.code);export const getDecodedErrorCode=(r,s)=>s!==DEFAULT_CODE?s:__isErrorCodeCarrier(r)?r.code:DEFAULT_CODE;
@@ -1,8 +1,17 @@
1
1
  import { type IErrorCode } from '../shared/types.js';
2
- import { IExceptionRecord } from './types.js';
2
+ import { type IExceptionRecord } from './types.js';
3
+ /**
4
+ * Error subclass that normalizes unknown errors into a message, code, and optional data payload.
5
+ */
3
6
  export declare class Exception extends Error {
4
7
  readonly code: IErrorCode;
5
8
  readonly data: unknown;
9
+ /**
10
+ * Creates an exception from any supported error input.
11
+ * @param error The unknown error or message to normalize.
12
+ * @param code The optional code that overrides any decoded code.
13
+ * @param data The optional data payload that overrides any decoded data.
14
+ */
6
15
  constructor(error: unknown, code?: IErrorCode, data?: unknown);
7
16
  /**
8
17
  * Override the default toString method to return a formatted error message with the code.
@@ -1 +1 @@
1
- import{decodeError,encodeError}from"../error-handler/index.js";export class Exception extends Error{code;data;constructor(e,r,t){const o=decodeError(e);super(o.message),this.name="Exception",this.code=r??o.code,this.data=t}toString(){return encodeError(this.message,this.code)}[Symbol.toPrimitive](e){return"string"===e||"default"===e?this.toString():null}toRecord(){return{message:this.message,code:this.code,data:this.data??null}}}
1
+ import{decodeError,encodeError}from"../error-handler/index.js";export class Exception extends Error{code;data;constructor(e,r,t){const o=decodeError(e);super(o.message),this.name="Exception",this.code=r??o.code,this.data=void 0===t?o.data:t}toString(){return encodeError(this.message,this.code)}[Symbol.toPrimitive](e){return"string"===e||"default"===e?this.toString():null}toRecord(){return{message:this.message,code:this.code,data:this.data??null}}}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { IErrorCode, IDecodedError } from './shared/types.js';
1
+ export type { IErrorCode, IDecodedError, IErrorCodeCarrier } from './shared/types.js';
2
2
  export { DEFAULT_CODE, DEFAULT_MESSAGE } from './shared/constants.js';
3
- export { extractMessage, encodeError, decodeError, isEncodedError, hasErrorCode, isDefaultErrorMessage, } from './error-handler/index.js';
3
+ export { extractMessage, encodeError, decodeError, isEncodedError, getErrorCode, hasErrorCode, isDefaultErrorMessage, } from './error-handler/index.js';
4
4
  export { type IExceptionRecord, Exception } from './exception/index.js';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export{DEFAULT_CODE,DEFAULT_MESSAGE}from"./shared/constants.js";export{extractMessage,encodeError,decodeError,isEncodedError,hasErrorCode,isDefaultErrorMessage}from"./error-handler/index.js";export{Exception}from"./exception/index.js";
1
+ export{DEFAULT_CODE,DEFAULT_MESSAGE}from"./shared/constants.js";export{extractMessage,encodeError,decodeError,isEncodedError,getErrorCode,hasErrorCode,isDefaultErrorMessage}from"./error-handler/index.js";export{Exception}from"./exception/index.js";
@@ -29,4 +29,13 @@ export type IUnwrappedErrorCode = {
29
29
  export type IDecodedError = {
30
30
  message: string;
31
31
  code: IErrorCode;
32
+ data: unknown | null;
32
33
  };
34
+ /**
35
+ * Error Code Carrier
36
+ * An object that carries an error code, typically used to identify errors programmatically. Extra
37
+ * fields are allowed because provider and application errors often carry metadata.
38
+ */
39
+ export type IErrorCodeCarrier = {
40
+ code: IErrorCode;
41
+ } & Record<string, unknown>;
@@ -1 +1 @@
1
- import{CODE_WRAPPER,DEFAULT_CODE}from"../shared/constants.js";export const wrapCode=r=>`${CODE_WRAPPER.prefix}${r??DEFAULT_CODE}${CODE_WRAPPER.suffix}`;const __isEncodedError=r=>new RegExp(`${CODE_WRAPPER.prefix}.+${CODE_WRAPPER.suffix}$`).test(r),__isNumeric=r=>"string"==typeof r&&/^[-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/.test(r);export const unwrapCode=r=>{if(__isEncodedError(r)){const E=r.lastIndexOf(CODE_WRAPPER.prefix),e=r.substring(E+CODE_WRAPPER.prefix.length,r.lastIndexOf(CODE_WRAPPER.suffix));return{code:__isNumeric(e)?Number(e):e,startsAt:E}}return{code:DEFAULT_CODE,startsAt:-1}};
1
+ import{CODE_WRAPPER,DEFAULT_CODE}from"../shared/constants.js";export const wrapCode=t=>`${CODE_WRAPPER.prefix}${t??DEFAULT_CODE}${CODE_WRAPPER.suffix}`;const __isEncodedError=t=>{const e=t.lastIndexOf(CODE_WRAPPER.prefix),r=e+CODE_WRAPPER.prefix.length,E=t.length-CODE_WRAPPER.suffix.length;return e>=0&&r<E&&t.endsWith(CODE_WRAPPER.suffix)},__isNumeric=t=>"string"==typeof t&&/^[-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/.test(t);export const unwrapCode=t=>{if(__isEncodedError(t)){const e=t.lastIndexOf(CODE_WRAPPER.prefix),r=t.substring(e+CODE_WRAPPER.prefix.length,t.lastIndexOf(CODE_WRAPPER.suffix));return{code:__isNumeric(r)?Number(r):r,startsAt:e}}return{code:DEFAULT_CODE,startsAt:-1}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "error-message-utils",
3
- "version": "1.2.8",
3
+ "version": "1.2.10",
4
4
  "description": "The error-message-utils package simplifies error management in your web applications and RESTful APIs. It ensures consistent and scalable handling of error messages, saving you time and effort. Moreover, it gives you the ability to assign custom error codes so all possible cases can be handled accordingly.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",