error-message-utils 1.2.9 → 1.2.11
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 +200 -147
- package/dist/error-handler/index.d.ts +8 -11
- package/dist/error-handler/index.js +1 -1
- package/dist/error-handler/utilities.d.ts +8 -0
- package/dist/error-handler/utilities.js +1 -1
- package/dist/exception/exception.d.ts +10 -1
- package/dist/exception/exception.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/shared/types.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,249 +1,302 @@
|
|
|
1
1
|
# Error Message Utils
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
19
|
+
## Recommended Usage: Exception
|
|
10
20
|
|
|
11
|
-
|
|
21
|
+
`Exception` is an `Error` subclass that stores a normalized message, a code, and optional data.
|
|
12
22
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
const exception = new Exception('Request failed', 'REQUEST_FAILED');
|
|
33
|
+
|
|
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
|
+
// }
|
|
16
47
|
```
|
|
17
48
|
|
|
18
|
-
###
|
|
49
|
+
### Wrap Unknown Errors
|
|
19
50
|
|
|
20
|
-
|
|
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 {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
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 {
|
|
71
|
+
import { Exception } from 'error-message-utils';
|
|
41
72
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
96
|
+
### Extract a Message
|
|
51
97
|
|
|
52
|
-
|
|
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(
|
|
58
|
-
|
|
59
|
-
cause: new Error('
|
|
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
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
|
125
|
+
import { z } from 'zod';
|
|
82
126
|
import { extractMessage } from 'error-message-utils';
|
|
83
127
|
|
|
84
|
-
z.object({ name: z.string() }).
|
|
85
|
-
// Invalid input: expected string, received number (name)
|
|
128
|
+
const result = z.object({ name: z.string() }).safeParse({ name: 123 });
|
|
86
129
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
Identify encoded errors:
|
|
138
|
+
Use `getErrorCode` when you only need the resolved code.
|
|
97
139
|
|
|
98
140
|
```typescript
|
|
99
|
-
import {
|
|
100
|
-
|
|
101
|
-
isEncodedError('Some random unencoded error');
|
|
102
|
-
// false
|
|
141
|
+
import { Exception, getErrorCode } from 'error-message-utils';
|
|
103
142
|
|
|
104
|
-
|
|
105
|
-
// false
|
|
143
|
+
const exception = new Exception('Access denied', 'ACCESS_DENIED');
|
|
106
144
|
|
|
107
|
-
|
|
108
|
-
//
|
|
145
|
+
getErrorCode(exception); // 'ACCESS_DENIED'
|
|
146
|
+
getErrorCode('Access denied'); // null
|
|
147
|
+
```
|
|
109
148
|
|
|
110
|
-
|
|
111
|
-
// true
|
|
149
|
+
Use `hasErrorCode` when you want a direct boolean check.
|
|
112
150
|
|
|
113
|
-
|
|
114
|
-
|
|
151
|
+
```typescript
|
|
152
|
+
import { Exception, hasErrorCode } from 'error-message-utils';
|
|
115
153
|
|
|
116
|
-
|
|
117
|
-
hasErrorCode(error, 'MY_ERROR_CODE'); // false
|
|
154
|
+
const exception = new Exception('Access denied', 'ACCESS_DENIED');
|
|
118
155
|
|
|
119
|
-
|
|
120
|
-
hasErrorCode(exception, '
|
|
156
|
+
hasErrorCode(exception, 'ACCESS_DENIED'); // true
|
|
157
|
+
hasErrorCode(exception, 'PAYMENT_FAILED'); // false
|
|
121
158
|
```
|
|
122
159
|
|
|
160
|
+
### Encode and Decode Plain Strings
|
|
123
161
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
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.
|
|
127
164
|
|
|
128
165
|
```typescript
|
|
129
|
-
import {
|
|
166
|
+
import { decodeError, encodeError } from 'error-message-utils';
|
|
130
167
|
|
|
131
|
-
const
|
|
168
|
+
const encodedError = encodeError(
|
|
169
|
+
'The provided email is already in use.',
|
|
170
|
+
'EMAIL_EXISTS',
|
|
171
|
+
);
|
|
132
172
|
|
|
133
|
-
|
|
134
|
-
//
|
|
173
|
+
encodedError;
|
|
174
|
+
// 'The provided email is already in use.{(EMAIL_EXISTS)}'
|
|
135
175
|
|
|
136
|
-
|
|
137
|
-
//
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
//
|
|
176
|
+
decodeError(encodedError);
|
|
177
|
+
// {
|
|
178
|
+
// message: 'The provided email is already in use.',
|
|
179
|
+
// code: 'EMAIL_EXISTS',
|
|
180
|
+
// data: null,
|
|
181
|
+
// }
|
|
141
182
|
```
|
|
142
183
|
|
|
184
|
+
### Detect Resolved Codes with isEncodedError
|
|
143
185
|
|
|
186
|
+
`isEncodedError` returns `true` when an error resolves to a non-default code. For direct code
|
|
187
|
+
inspection, prefer `getErrorCode` or `hasErrorCode`.
|
|
144
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
|
+
```
|
|
145
196
|
|
|
146
|
-
|
|
197
|
+
### Check the Default Message
|
|
147
198
|
|
|
148
|
-
|
|
199
|
+
Use `isDefaultErrorMessage` to detect the fallback message returned when no useful message can be
|
|
200
|
+
extracted.
|
|
149
201
|
|
|
150
202
|
```typescript
|
|
151
|
-
import {
|
|
203
|
+
import { DEFAULT_MESSAGE, isDefaultErrorMessage } from 'error-message-utils';
|
|
152
204
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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';
|
|
165
231
|
```
|
|
166
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()`. |
|
|
238
|
+
|
|
239
|
+
### Functions
|
|
167
240
|
|
|
168
|
-
|
|
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. |
|
|
169
250
|
|
|
170
|
-
|
|
251
|
+
### Types
|
|
171
252
|
|
|
172
253
|
```typescript
|
|
173
|
-
/**
|
|
174
|
-
* Error Code
|
|
175
|
-
* The code that is inserted when encoding an error. If none is provided or none can be extracted, it defaults to -1.
|
|
176
|
-
*/
|
|
177
254
|
type IErrorCode = string | number;
|
|
178
255
|
|
|
179
|
-
/**
|
|
180
|
-
* Decoded Error
|
|
181
|
-
* 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.
|
|
182
|
-
*/
|
|
183
256
|
type IDecodedError = {
|
|
184
|
-
message: string,
|
|
185
|
-
code: IErrorCode,
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Exception Record
|
|
190
|
-
* The record type for the Exception class.
|
|
191
|
-
*/
|
|
192
|
-
type IExceptionRecord = {
|
|
193
257
|
message: string;
|
|
194
258
|
code: IErrorCode;
|
|
195
259
|
data: unknown | null;
|
|
196
260
|
};
|
|
197
261
|
|
|
198
|
-
/**
|
|
199
|
-
* Error Code Carrier
|
|
200
|
-
* An object that carries an error code, typically used to identify errors programmatically.
|
|
201
|
-
*/
|
|
202
262
|
type IErrorCodeCarrier = {
|
|
203
263
|
code: IErrorCode;
|
|
204
|
-
message: string;
|
|
205
264
|
} & Record<string, unknown>;
|
|
206
|
-
```
|
|
207
265
|
|
|
266
|
+
type IExceptionRecord = {
|
|
267
|
+
message: string;
|
|
268
|
+
code: IErrorCode;
|
|
269
|
+
data: unknown | null;
|
|
270
|
+
};
|
|
271
|
+
```
|
|
208
272
|
|
|
209
|
-
|
|
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()`. |
|
|
210
279
|
|
|
211
|
-
|
|
280
|
+
### Constants
|
|
212
281
|
|
|
213
282
|
```typescript
|
|
214
|
-
|
|
215
|
-
const DEFAULT_MESSAGE: string =
|
|
216
|
-
'The error message could not be extracted, check the logs for more information.';
|
|
283
|
+
const DEFAULT_CODE = -1;
|
|
217
284
|
|
|
218
|
-
|
|
219
|
-
|
|
285
|
+
const DEFAULT_MESSAGE =
|
|
286
|
+
'The error message could not be extracted, check the logs for more information.';
|
|
220
287
|
```
|
|
221
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. |
|
|
222
293
|
|
|
223
|
-
|
|
224
|
-
<br/>
|
|
225
|
-
|
|
226
|
-
## Built With
|
|
227
|
-
|
|
228
|
-
- TypeScript
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
<br/>
|
|
234
|
-
|
|
235
|
-
## Running the Tests
|
|
294
|
+
## Running Tests
|
|
236
295
|
|
|
237
296
|
```bash
|
|
238
|
-
npm
|
|
297
|
+
npm test
|
|
239
298
|
```
|
|
240
299
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
<br/>
|
|
246
|
-
|
|
247
300
|
## License
|
|
248
301
|
|
|
249
302
|
[MIT](https://choosealicense.com/licenses/mit/)
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import type { IErrorCode, IDecodedError
|
|
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,14 +33,11 @@ export declare const decodeError: (error: any) => IDecodedError;
|
|
|
33
33
|
*/
|
|
34
34
|
export declare const isEncodedError: (error: any) => boolean;
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
* Determines whether an unknown value has an inspectable error code property.
|
|
40
|
-
* @param error The unknown value to inspect.
|
|
41
|
-
* @returns True when the value can carry an Exception-style code.
|
|
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.
|
|
42
39
|
*/
|
|
43
|
-
export declare const
|
|
40
|
+
export declare const getErrorCode: (error: any) => IErrorCode | null;
|
|
44
41
|
/**
|
|
45
42
|
* Checks if the given error matches the specified error code.
|
|
46
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";
|
|
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=
|
|
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, IErrorCodeCarrier } 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,
|
|
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,
|
|
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";
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export type IUnwrappedErrorCode = {
|
|
|
29
29
|
export type IDecodedError = {
|
|
30
30
|
message: string;
|
|
31
31
|
code: IErrorCode;
|
|
32
|
+
data: unknown | null;
|
|
32
33
|
};
|
|
33
34
|
/**
|
|
34
35
|
* Error Code Carrier
|
|
@@ -37,5 +38,4 @@ export type IDecodedError = {
|
|
|
37
38
|
*/
|
|
38
39
|
export type IErrorCodeCarrier = {
|
|
39
40
|
code: IErrorCode;
|
|
40
|
-
message: string;
|
|
41
41
|
} & Record<string, unknown>;
|
package/dist/utils/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CODE_WRAPPER,DEFAULT_CODE}from"../shared/constants.js";export const wrapCode=
|
|
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.
|
|
3
|
+
"version": "1.2.11",
|
|
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",
|