payload-guard-filter 1.4.0 → 1.5.0

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
@@ -115,6 +115,16 @@ Creates a string builder with chained constraints:
115
115
 
116
116
  ---
117
117
 
118
+ ## 🛡️ "Never Crash" Policy
119
+
120
+ Payload Guard is designed for mission-critical enterprise environments where uptime is non-negotiable.
121
+
122
+ - **Circular Reference Safety**: Automatically detects and handles circular objects without infinite loops or stack overflows.
123
+ - **Hook Isolation**: Custom `.transform()` and `.validate()` callbacks are wrapped in internal try/catch blocks. If your code fails, the library logs the error and safely continues using fallback values.
124
+ - **Middleware Fail-Open**: If internal filtering logic hits an unexpected edge case, `failOpen: true` ensures the original request/response still reaches its destination.
125
+
126
+ ---
127
+
118
128
  ## ⚡ Performance
119
129
 
120
130
  | Benchmark | ops/sec | avg (ms) |
@@ -2,7 +2,7 @@
2
2
  * Deep clone utility that avoids mutating original objects
3
3
  * Uses structuredClone when available, falls back to JSON
4
4
  */
5
- export declare function deepClone<T>(value: T): T;
5
+ export declare function deepClone<T>(value: T, seen?: WeakSet<object>): T;
6
6
  /**
7
7
  * Shallow clone for performance when deep clone isn't needed
8
8
  */
@@ -6,33 +6,42 @@ exports.shallowClone = shallowClone;
6
6
  * Deep clone utility that avoids mutating original objects
7
7
  * Uses structuredClone when available, falls back to JSON
8
8
  */
9
- function deepClone(value) {
9
+ function deepClone(value, seen = new WeakSet()) {
10
10
  if (value === null || value === undefined)
11
11
  return value;
12
12
  if (typeof value !== 'object')
13
13
  return value;
14
+ // Circular ref check
15
+ if (seen.has(value)) {
16
+ return value; // Return as-is if circular
17
+ }
14
18
  // Try structuredClone first (Node 17+, modern browsers)
15
19
  if (typeof structuredClone === 'function') {
16
20
  try {
17
21
  return structuredClone(value);
18
22
  }
19
23
  catch {
20
- // Fall through to JSON method
24
+ // Fall through
21
25
  }
22
26
  }
23
- // Fallback to JSON parse/stringify
27
+ // Handle Arrays
28
+ if (Array.isArray(value)) {
29
+ seen.add(value);
30
+ return value.map(item => deepClone(item, seen));
31
+ }
32
+ // Handle Objects
24
33
  try {
25
- return JSON.parse(JSON.stringify(value));
34
+ seen.add(value);
35
+ const result = {};
36
+ for (const key in value) {
37
+ if (Object.prototype.hasOwnProperty.call(value, key)) {
38
+ result[key] = deepClone(value[key], seen);
39
+ }
40
+ }
41
+ return result;
26
42
  }
27
43
  catch {
28
- // If deep clone fails (circular refs or other), return a shallow clone
29
- // to avoid mutating the original object downstream.
30
- try {
31
- return shallowClone(value);
32
- }
33
- catch {
34
- return value;
35
- }
44
+ return value;
36
45
  }
37
46
  }
38
47
  /**
@@ -62,7 +62,7 @@ function compile(shape, opts = {}) {
62
62
  }
63
63
  catch (e) {
64
64
  if (opts.dev)
65
- (opts.logger ?? console.warn)('[payload-guard] transform error: ' + String(e));
65
+ (opts.logger ?? console.warn)('[payload-guard] transform error: ' + String(e), 'warn');
66
66
  }
67
67
  }
68
68
  }
@@ -114,7 +114,7 @@ function compile(shape, opts = {}) {
114
114
  }
115
115
  catch (e) {
116
116
  if (opts.dev) {
117
- (opts.logger ?? console.warn)('[payload-guard] array item filter error: ' + String(e));
117
+ (opts.logger ?? console.warn)('[payload-guard] array item filter error: ' + String(e), 'warn');
118
118
  }
119
119
  return undefined;
120
120
  }
@@ -158,7 +158,7 @@ function compile(shape, opts = {}) {
158
158
  }
159
159
  catch (e) {
160
160
  if (opts.dev)
161
- (opts.logger ?? console.warn)('[payload-guard] redact hook error: ' + String(e));
161
+ (opts.logger ?? console.warn)('[payload-guard] redact hook error: ' + String(e), 'warn');
162
162
  }
163
163
  }
164
164
  result[key] = outVal;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload-guard-filter",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Lightweight, zero-dependency shape-based payload filtering and sanitization for Node.js and browser",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",