error-message-utils 1.2.12 → 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.
@@ -232,6 +255,7 @@ import {
232
255
  decodeError,
233
256
  encodeError,
234
257
  extractMessage,
258
+ extractRedactedMessage,
235
259
  getErrorCode,
236
260
  hasErrorCode,
237
261
  hasErrorCodePrefix,
@@ -255,6 +279,7 @@ import {
255
279
  | Export | Signature | Description |
256
280
  | --- | --- | --- |
257
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. |
258
283
  | `encodeError` | `(error: unknown, code: IErrorCode) => string` | Extracts a message from `error` and appends the wrapped code at the end of the message. |
259
284
  | `decodeError` | `(error: unknown) => IDecodedError` | Extracts a message, resolves a code from an encoded message or code-carrying object, and returns `{ message, code, data }`. |
260
285
  | `isEncodedError` | `(error: unknown) => boolean` | Returns `true` when `decodeError(error).code` resolves to a non-default code. |
@@ -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
  */
@@ -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,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 hasErrorCodePrefix=(r,e)=>{if(0===e.length)return!1;const t=getErrorCode(r)??r;return"string"==typeof t&&t.startsWith(e)};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
+ 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 __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
+ 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, hasErrorCodePrefix, 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,hasErrorCodePrefix,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.12",
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",