error-message-utils 1.2.11 → 1.2.13
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
|
@@ -133,6 +133,29 @@ if (!result.success) {
|
|
|
133
133
|
}
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
+
### Redact Sensitive Values
|
|
137
|
+
|
|
138
|
+
`extractRedactedMessage` extracts a message using the same rules as `extractMessage`, then replaces
|
|
139
|
+
every exact sensitive value with `[redacted]`.
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { extractRedactedMessage } from 'error-message-utils';
|
|
143
|
+
|
|
144
|
+
const error = new Error('Request failed for token abc123.', {
|
|
145
|
+
cause: new Error('The provider rejected abc123.'),
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
extractRedactedMessage(error, ['abc123']);
|
|
149
|
+
// 'Request failed for token [redacted].; [CAUSE]: The provider rejected [redacted].'
|
|
150
|
+
|
|
151
|
+
extractRedactedMessage(error, ['different-value']);
|
|
152
|
+
// 'Request failed for token abc123.; [CAUSE]: The provider rejected abc123.'
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Matching is literal and case-sensitive. Empty values are ignored. The function does not
|
|
156
|
+
automatically identify secrets, so transformed or encoded versions must be supplied separately if
|
|
157
|
+
they also need redaction.
|
|
158
|
+
|
|
136
159
|
### Get an Error Code
|
|
137
160
|
|
|
138
161
|
Use `getErrorCode` when you only need the resolved code.
|
|
@@ -157,6 +180,19 @@ hasErrorCode(exception, 'ACCESS_DENIED'); // true
|
|
|
157
180
|
hasErrorCode(exception, 'PAYMENT_FAILED'); // false
|
|
158
181
|
```
|
|
159
182
|
|
|
183
|
+
Use `hasErrorCodePrefix` when related string codes share a prefix. Empty prefixes and numeric codes
|
|
184
|
+
do not match.
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import { Exception, hasErrorCodePrefix } from 'error-message-utils';
|
|
188
|
+
|
|
189
|
+
const exception = new Exception('User not found', 'USER_NOT_FOUND');
|
|
190
|
+
|
|
191
|
+
hasErrorCodePrefix(exception, 'USER_'); // true
|
|
192
|
+
hasErrorCodePrefix('USER_NOT_FOUND', 'USER_'); // true
|
|
193
|
+
hasErrorCodePrefix(exception, 'PAYMENT_'); // false
|
|
194
|
+
```
|
|
195
|
+
|
|
160
196
|
### Encode and Decode Plain Strings
|
|
161
197
|
|
|
162
198
|
`encodeError` and `decodeError` are lower-level helpers for systems that can only pass string
|
|
@@ -219,8 +255,10 @@ import {
|
|
|
219
255
|
decodeError,
|
|
220
256
|
encodeError,
|
|
221
257
|
extractMessage,
|
|
258
|
+
extractRedactedMessage,
|
|
222
259
|
getErrorCode,
|
|
223
260
|
hasErrorCode,
|
|
261
|
+
hasErrorCodePrefix,
|
|
224
262
|
isDefaultErrorMessage,
|
|
225
263
|
isEncodedError,
|
|
226
264
|
type IDecodedError,
|
|
@@ -241,11 +279,13 @@ import {
|
|
|
241
279
|
| Export | Signature | Description |
|
|
242
280
|
| --- | --- | --- |
|
|
243
281
|
| `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. |
|
|
282
|
+
| `extractRedactedMessage` | `(error: unknown, sensitiveValues: readonly string[]) => string` | Extracts a message and replaces every exact, case-sensitive occurrence of each non-empty sensitive value with `[redacted]`. Returns the extracted message unchanged when no value matches. |
|
|
244
283
|
| `encodeError` | `(error: unknown, code: IErrorCode) => string` | Extracts a message from `error` and appends the wrapped code at the end of the message. |
|
|
245
284
|
| `decodeError` | `(error: unknown) => IDecodedError` | Extracts a message, resolves a code from an encoded message or code-carrying object, and returns `{ message, code, data }`. |
|
|
246
285
|
| `isEncodedError` | `(error: unknown) => boolean` | Returns `true` when `decodeError(error).code` resolves to a non-default code. |
|
|
247
286
|
| `getErrorCode` | `(error: unknown) => IErrorCode \| null` | Returns the resolved non-default code, or `null` when no non-default code is found. |
|
|
248
287
|
| `hasErrorCode` | `(error: unknown, code: IErrorCode) => boolean` | Checks whether an error resolves to the provided code. Raw code values are compared with strict equality. |
|
|
288
|
+
| `hasErrorCodePrefix` | `(error: unknown, prefix: string) => boolean` | Checks whether an error resolves to a string code that starts with the provided non-empty prefix. Raw string codes are supported; numeric codes do not match. |
|
|
249
289
|
| `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
290
|
|
|
251
291
|
### Types
|
|
@@ -274,7 +314,7 @@ type IExceptionRecord = {
|
|
|
274
314
|
| --- | --- |
|
|
275
315
|
| `IErrorCode` | The supported type for application error codes. |
|
|
276
316
|
| `IDecodedError` | The object returned by `decodeError`. |
|
|
277
|
-
| `IErrorCodeCarrier` | A plain object shape that can provide a code to `decodeError`, `getErrorCode`, `hasErrorCode`, and `Exception`. |
|
|
317
|
+
| `IErrorCodeCarrier` | A plain object shape that can provide a code to `decodeError`, `getErrorCode`, `hasErrorCode`, `hasErrorCodePrefix`, and `Exception`. |
|
|
278
318
|
| `IExceptionRecord` | The serializable object returned by `Exception.toRecord()`. |
|
|
279
319
|
|
|
280
320
|
### Constants
|
|
@@ -6,6 +6,13 @@ import type { IErrorCode, IDecodedError } from '../shared/types.js';
|
|
|
6
6
|
* @returns A string containing the extracted message or the default message if extraction fails.
|
|
7
7
|
*/
|
|
8
8
|
export declare const extractMessage: (error: any) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Extracts an error message and replaces exact sensitive values with a redaction marker.
|
|
11
|
+
* @param error The error to extract the message from.
|
|
12
|
+
* @param sensitiveValues The exact case-sensitive values to redact.
|
|
13
|
+
* @returns The extracted message with matching sensitive values redacted.
|
|
14
|
+
*/
|
|
15
|
+
export declare const extractRedactedMessage: (error: unknown, sensitiveValues: string[]) => string;
|
|
9
16
|
/**
|
|
10
17
|
* Encoding / Decoding
|
|
11
18
|
*/
|
|
@@ -38,6 +45,13 @@ export declare const isEncodedError: (error: any) => boolean;
|
|
|
38
45
|
* @returns The error code or null if it matches the default code.
|
|
39
46
|
*/
|
|
40
47
|
export declare const getErrorCode: (error: any) => IErrorCode | null;
|
|
48
|
+
/**
|
|
49
|
+
* Checks if the given error has a string code that starts with the specified prefix.
|
|
50
|
+
* @param error The error to be checked, can be of any type.
|
|
51
|
+
* @param prefix The non-empty prefix to check against.
|
|
52
|
+
* @returns A boolean indicating whether the error code starts with the specified prefix.
|
|
53
|
+
*/
|
|
54
|
+
export declare const hasErrorCodePrefix: (error: unknown, prefix: string) => boolean;
|
|
41
55
|
/**
|
|
42
56
|
* Checks if the given error matches the specified error code.
|
|
43
57
|
* @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,getDecodedErrorCode}from"./utilities.js";const __extractMessage=(r
|
|
1
|
+
import{ZodError}from"zod";import{DEFAULT_CODE,DEFAULT_MESSAGE}from"../shared/constants.js";import{wrapCode,unwrapCode}from"../utils/index.js";import{extractZodErrorMessage,getDecodedErrorCode,redactSensitiveValues}from"./utilities.js";const __extractMessage=(e,r)=>{if("string"==typeof e&&e.length)return e;if(e instanceof ZodError)return extractZodErrorMessage(e);if(e&&"object"==typeof e){if(r.has(e))return DEFAULT_MESSAGE;r.add(e)}if(e instanceof Error&&e.message)return e.cause?`${e.message}; [CAUSE]: ${__extractMessage(e.cause,r)}`:e.message;if(e&&"object"==typeof e){if(e.message)return __extractMessage(e.message,r);if(e.msg)return __extractMessage(e.msg,r);if(e.error)return __extractMessage(e.error,r);if(e.err)return __extractMessage(e.err,r);if(e.errors)return __extractMessage(e.errors,r);if(e.errs)return __extractMessage(e.errs,r);if(e.reason)return __extractMessage(e.reason,r);if(e.reasons)return __extractMessage(e.reasons,r);if(e.issue)return __extractMessage(e.issue,r);if(e.issues)return __extractMessage(e.issues,r);if(e.data)return __extractMessage(e.data,r);try{return JSON.stringify(e)}catch{return DEFAULT_MESSAGE}}return DEFAULT_MESSAGE};export const extractMessage=e=>__extractMessage(e,new WeakSet);export const extractRedactedMessage=(e,r)=>redactSensitiveValues(extractMessage(e),r);export const encodeError=(e,r)=>`${extractMessage(e)}${wrapCode(r)}`;export const decodeError=e=>{const r=extractMessage(e),{code:t,startsAt:s}=unwrapCode(r);return{message:s>0?r.slice(0,s):r,code:getDecodedErrorCode(e,t),data:null!==e&&"object"==typeof e&&"data"in e?e.data:null}};export const isEncodedError=e=>decodeError(e).code!==DEFAULT_CODE;export const getErrorCode=e=>{const{code:r}=decodeError(e);return r!==DEFAULT_CODE?r:null};export const hasErrorCodePrefix=(e,r)=>{if(0===r.length)return!1;const t=getErrorCode(e)??e;return"string"==typeof t&&t.startsWith(r)};export const hasErrorCode=(e,r)=>null!==e&&(e===r||decodeError(e).code===r);export const isDefaultErrorMessage=(e,r=!1)=>r?e===DEFAULT_MESSAGE:"string"==typeof e&&e.includes(DEFAULT_MESSAGE);
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { ZodError } from 'zod';
|
|
2
2
|
import { IErrorCode } from '../shared/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Replaces every literal sensitive value in a message with the redaction marker.
|
|
5
|
+
* @param message The message to redact.
|
|
6
|
+
* @param sensitiveValues The exact case-sensitive values to redact.
|
|
7
|
+
* @returns The message with matching sensitive values redacted.
|
|
8
|
+
*/
|
|
9
|
+
export declare const redactSensitiveValues: (message: string, sensitiveValues: string[]) => string;
|
|
3
10
|
/**
|
|
4
11
|
* Attempts to extract a Zod error message from a ZodError instance. If unable to do so, it returns
|
|
5
12
|
* the default error message.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DEFAULT_CODE,DEFAULT_MESSAGE}from"../shared/constants.js";const
|
|
1
|
+
import{DEFAULT_CODE,DEFAULT_MESSAGE}from"../shared/constants.js";const REDACTION_REPLACEMENT="[redacted]",__collectSensitiveRanges=(e,r)=>{const s=[];return r.forEach((r=>{let t=e.indexOf(r);for(;-1!==t;)s.push({start:t,end:t+r.length}),t=e.indexOf(r,t+1)})),s},__mergeOverlappingRanges=e=>{const r=[...e].sort(((e,r)=>e.start-r.start||r.end-e.end)),s=[];return r.forEach((e=>{const r=s.at(-1);!r||e.start>=r.end?s.push({...e}):e.end>r.end&&(r.end=e.end)})),s};export const redactSensitiveValues=(e,r)=>{const s=[...new Set(r.filter((e=>e.length>0)))];if(!s.length)return e;const t=__mergeOverlappingRanges(__collectSensitiveRanges(e,s));if(!t.length)return e;const n=[];let o=0;return t.forEach((r=>{n.push(e.slice(o,r.start),"[redacted]"),o=r.end})),n.push(e.slice(o)),n.join("")};const __extractPathFromZodError=e=>e&&Array.isArray(e.issues)&&e.issues.length&&Array.isArray(e.issues[0].path)&&e.issues[0].path.length?e.issues[0].path.join("."):"Unknown path";export const extractZodErrorMessage=e=>e&&Array.isArray(e.issues)&&e.issues.length&&Array.isArray(e.issues[0].path)&&e.issues[0].message?`${e.issues[0].message} (${__extractPathFromZodError(e)})`:DEFAULT_MESSAGE;const __isErrorCodeCarrier=e=>"object"==typeof e&&null!==e&&"code"in e&&("string"==typeof e.code||"number"==typeof e.code);export const getDecodedErrorCode=(e,r)=>r!==DEFAULT_CODE?r:__isErrorCodeCarrier(e)?e.code:DEFAULT_CODE;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
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, getErrorCode, hasErrorCode, isDefaultErrorMessage, } from './error-handler/index.js';
|
|
3
|
+
export { extractMessage, extractRedactedMessage, encodeError, decodeError, isEncodedError, getErrorCode, hasErrorCodePrefix, 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,getErrorCode,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,extractRedactedMessage,encodeError,decodeError,isEncodedError,getErrorCode,hasErrorCodePrefix,hasErrorCode,isDefaultErrorMessage}from"./error-handler/index.js";export{Exception}from"./exception/index.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "error-message-utils",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.13",
|
|
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",
|