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 +202 -138
- package/dist/error-handler/index.d.ts +8 -5
- 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 +9 -0
- package/dist/utils/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,192 +1,268 @@
|
|
|
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
|
+
});
|
|
16
29
|
```
|
|
17
30
|
|
|
18
|
-
|
|
31
|
+
```typescript
|
|
32
|
+
const exception = new Exception('Request failed', 'REQUEST_FAILED');
|
|
19
33
|
|
|
20
|
-
|
|
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 {
|
|
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 {
|
|
141
|
+
import { Exception, getErrorCode } from 'error-message-utils';
|
|
142
|
+
|
|
143
|
+
const exception = new Exception('Access denied', 'ACCESS_DENIED');
|
|
100
144
|
|
|
101
|
-
|
|
102
|
-
//
|
|
145
|
+
getErrorCode(exception); // 'ACCESS_DENIED'
|
|
146
|
+
getErrorCode('Access denied'); // null
|
|
147
|
+
```
|
|
103
148
|
|
|
104
|
-
|
|
105
|
-
// false
|
|
149
|
+
Use `hasErrorCode` when you want a direct boolean check.
|
|
106
150
|
|
|
107
|
-
|
|
108
|
-
|
|
151
|
+
```typescript
|
|
152
|
+
import { Exception, hasErrorCode } from 'error-message-utils';
|
|
109
153
|
|
|
110
|
-
|
|
111
|
-
// true
|
|
154
|
+
const exception = new Exception('Access denied', 'ACCESS_DENIED');
|
|
112
155
|
|
|
113
|
-
hasErrorCode(
|
|
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
|
-
|
|
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 {
|
|
166
|
+
import { decodeError, encodeError } from 'error-message-utils';
|
|
128
167
|
|
|
129
|
-
const
|
|
168
|
+
const encodedError = encodeError(
|
|
169
|
+
'The provided email is already in use.',
|
|
170
|
+
'EMAIL_EXISTS',
|
|
171
|
+
);
|
|
130
172
|
|
|
131
|
-
|
|
132
|
-
//
|
|
173
|
+
encodedError;
|
|
174
|
+
// 'The provided email is already in use.{(EMAIL_EXISTS)}'
|
|
133
175
|
|
|
134
|
-
|
|
135
|
-
//
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
//
|
|
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
|
-
|
|
197
|
+
### Check the Default Message
|
|
145
198
|
|
|
146
|
-
|
|
199
|
+
Use `isDefaultErrorMessage` to detect the fallback message returned when no useful message can be
|
|
200
|
+
extracted.
|
|
147
201
|
|
|
148
202
|
```typescript
|
|
149
|
-
import {
|
|
203
|
+
import { DEFAULT_MESSAGE, isDefaultErrorMessage } from 'error-message-utils';
|
|
150
204
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
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. |
|
|
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
|
-
|
|
188
|
-
|
|
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
|
-
|
|
199
|
-
|
|
200
|
-
## Constants
|
|
280
|
+
### Constants
|
|
201
281
|
|
|
202
282
|
```typescript
|
|
203
|
-
|
|
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
|
-
|
|
208
|
-
|
|
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
|
|
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
|
-
*
|
|
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";
|
|
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 } 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";
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -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>;
|
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.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",
|