@blamejs/core 0.8.43 → 0.8.50

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.
Files changed (222) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/README.md +10 -10
  3. package/index.js +52 -0
  4. package/lib/a2a.js +159 -34
  5. package/lib/acme.js +762 -0
  6. package/lib/ai-pref.js +166 -43
  7. package/lib/api-key.js +108 -47
  8. package/lib/api-snapshot.js +157 -40
  9. package/lib/app-shutdown.js +113 -77
  10. package/lib/archive.js +337 -40
  11. package/lib/arg-parser.js +697 -0
  12. package/lib/asyncapi.js +99 -55
  13. package/lib/atomic-file.js +465 -104
  14. package/lib/audit-chain.js +123 -34
  15. package/lib/audit-daily-review.js +389 -0
  16. package/lib/audit-sign.js +302 -56
  17. package/lib/audit-tools.js +412 -63
  18. package/lib/audit.js +656 -35
  19. package/lib/auth/jwt-external.js +17 -0
  20. package/lib/auth/oauth.js +7 -0
  21. package/lib/auth-bot-challenge.js +505 -0
  22. package/lib/auth-header.js +92 -25
  23. package/lib/backup/bundle.js +26 -0
  24. package/lib/backup/index.js +512 -89
  25. package/lib/backup/manifest.js +168 -7
  26. package/lib/break-glass.js +415 -39
  27. package/lib/budr.js +103 -30
  28. package/lib/bundler.js +86 -66
  29. package/lib/cache.js +192 -72
  30. package/lib/chain-writer.js +65 -40
  31. package/lib/circuit-breaker.js +56 -33
  32. package/lib/cli-helpers.js +106 -75
  33. package/lib/cli.js +6 -30
  34. package/lib/cloud-events.js +99 -32
  35. package/lib/cluster-storage.js +162 -37
  36. package/lib/cluster.js +340 -49
  37. package/lib/codepoint-class.js +66 -0
  38. package/lib/compliance.js +424 -24
  39. package/lib/config-drift.js +111 -46
  40. package/lib/config.js +94 -40
  41. package/lib/consent.js +165 -18
  42. package/lib/constants.js +1 -0
  43. package/lib/content-credentials.js +153 -48
  44. package/lib/cookies.js +154 -62
  45. package/lib/credential-hash.js +133 -61
  46. package/lib/crypto-field.js +702 -18
  47. package/lib/crypto-hpke.js +256 -0
  48. package/lib/crypto.js +744 -22
  49. package/lib/csv.js +178 -35
  50. package/lib/daemon.js +456 -0
  51. package/lib/dark-patterns.js +186 -55
  52. package/lib/db-query.js +79 -2
  53. package/lib/db.js +1431 -60
  54. package/lib/ddl-change-control.js +523 -0
  55. package/lib/deprecate.js +195 -40
  56. package/lib/dev.js +82 -39
  57. package/lib/dora.js +67 -48
  58. package/lib/dr-runbook.js +368 -0
  59. package/lib/dsr.js +142 -11
  60. package/lib/dual-control.js +91 -56
  61. package/lib/events.js +120 -41
  62. package/lib/external-db-migrate.js +192 -2
  63. package/lib/external-db.js +795 -50
  64. package/lib/fapi2.js +122 -1
  65. package/lib/fda-21cfr11.js +395 -0
  66. package/lib/fdx.js +132 -2
  67. package/lib/file-type.js +87 -0
  68. package/lib/file-upload.js +93 -0
  69. package/lib/flag.js +82 -20
  70. package/lib/forms.js +132 -29
  71. package/lib/framework-error.js +169 -0
  72. package/lib/framework-schema.js +163 -35
  73. package/lib/gate-contract.js +849 -175
  74. package/lib/graphql-federation.js +68 -7
  75. package/lib/guard-all.js +172 -55
  76. package/lib/guard-archive.js +286 -124
  77. package/lib/guard-auth.js +194 -21
  78. package/lib/guard-cidr.js +190 -28
  79. package/lib/guard-csv.js +397 -51
  80. package/lib/guard-domain.js +213 -91
  81. package/lib/guard-email.js +236 -29
  82. package/lib/guard-filename.js +307 -75
  83. package/lib/guard-graphql.js +263 -30
  84. package/lib/guard-html.js +310 -116
  85. package/lib/guard-image.js +243 -30
  86. package/lib/guard-json.js +260 -54
  87. package/lib/guard-jsonpath.js +235 -23
  88. package/lib/guard-jwt.js +284 -30
  89. package/lib/guard-markdown.js +204 -22
  90. package/lib/guard-mime.js +190 -26
  91. package/lib/guard-oauth.js +277 -28
  92. package/lib/guard-pdf.js +251 -27
  93. package/lib/guard-regex.js +226 -18
  94. package/lib/guard-shell.js +229 -26
  95. package/lib/guard-svg.js +177 -10
  96. package/lib/guard-template.js +232 -21
  97. package/lib/guard-time.js +195 -29
  98. package/lib/guard-uuid.js +189 -30
  99. package/lib/guard-xml.js +259 -36
  100. package/lib/guard-yaml.js +241 -44
  101. package/lib/honeytoken.js +63 -27
  102. package/lib/html-balance.js +83 -0
  103. package/lib/http-client.js +486 -59
  104. package/lib/http-message-signature.js +582 -0
  105. package/lib/i18n.js +102 -49
  106. package/lib/iab-mspa.js +112 -32
  107. package/lib/iab-tcf.js +107 -2
  108. package/lib/inbox.js +90 -52
  109. package/lib/keychain.js +865 -0
  110. package/lib/legal-hold.js +374 -0
  111. package/lib/local-db-thin.js +320 -0
  112. package/lib/log-stream.js +281 -51
  113. package/lib/log.js +184 -86
  114. package/lib/mail-bounce.js +107 -62
  115. package/lib/mail.js +295 -58
  116. package/lib/mcp.js +108 -27
  117. package/lib/metrics.js +98 -89
  118. package/lib/middleware/age-gate.js +36 -0
  119. package/lib/middleware/ai-act-disclosure.js +37 -0
  120. package/lib/middleware/api-encrypt.js +45 -0
  121. package/lib/middleware/assetlinks.js +40 -0
  122. package/lib/middleware/asyncapi-serve.js +35 -0
  123. package/lib/middleware/attach-user.js +40 -0
  124. package/lib/middleware/bearer-auth.js +40 -0
  125. package/lib/middleware/body-parser.js +230 -0
  126. package/lib/middleware/bot-disclose.js +34 -0
  127. package/lib/middleware/bot-guard.js +39 -0
  128. package/lib/middleware/compression.js +37 -0
  129. package/lib/middleware/cookies.js +32 -0
  130. package/lib/middleware/cors.js +40 -0
  131. package/lib/middleware/csp-nonce.js +40 -0
  132. package/lib/middleware/csp-report.js +34 -0
  133. package/lib/middleware/csrf-protect.js +43 -0
  134. package/lib/middleware/daily-byte-quota.js +53 -85
  135. package/lib/middleware/db-role-for.js +40 -0
  136. package/lib/middleware/dpop.js +40 -0
  137. package/lib/middleware/error-handler.js +37 -14
  138. package/lib/middleware/fetch-metadata.js +39 -0
  139. package/lib/middleware/flag-context.js +34 -0
  140. package/lib/middleware/gpc.js +33 -0
  141. package/lib/middleware/headers.js +35 -0
  142. package/lib/middleware/health.js +46 -0
  143. package/lib/middleware/host-allowlist.js +30 -0
  144. package/lib/middleware/network-allowlist.js +38 -0
  145. package/lib/middleware/openapi-serve.js +34 -0
  146. package/lib/middleware/rate-limit.js +160 -18
  147. package/lib/middleware/request-id.js +36 -18
  148. package/lib/middleware/request-log.js +37 -0
  149. package/lib/middleware/require-aal.js +29 -0
  150. package/lib/middleware/require-auth.js +32 -0
  151. package/lib/middleware/require-bound-key.js +41 -0
  152. package/lib/middleware/require-content-type.js +32 -0
  153. package/lib/middleware/require-methods.js +27 -0
  154. package/lib/middleware/require-mtls.js +33 -0
  155. package/lib/middleware/require-step-up.js +37 -0
  156. package/lib/middleware/security-headers.js +44 -0
  157. package/lib/middleware/security-txt.js +38 -0
  158. package/lib/middleware/span-http-server.js +37 -0
  159. package/lib/middleware/sse.js +36 -0
  160. package/lib/middleware/trace-log-correlation.js +33 -0
  161. package/lib/middleware/trace-propagate.js +32 -0
  162. package/lib/middleware/tus-upload.js +90 -0
  163. package/lib/middleware/web-app-manifest.js +53 -0
  164. package/lib/mtls-ca.js +100 -70
  165. package/lib/network-byte-quota.js +308 -0
  166. package/lib/network-heartbeat.js +135 -0
  167. package/lib/network-tls.js +534 -4
  168. package/lib/network.js +103 -0
  169. package/lib/notify.js +114 -43
  170. package/lib/ntp-check.js +192 -51
  171. package/lib/observability.js +145 -47
  172. package/lib/openapi.js +90 -44
  173. package/lib/outbox.js +99 -1
  174. package/lib/pagination.js +168 -86
  175. package/lib/parsers/index.js +16 -5
  176. package/lib/permissions.js +93 -40
  177. package/lib/pqc-agent.js +84 -8
  178. package/lib/pqc-software.js +94 -60
  179. package/lib/process-spawn.js +95 -21
  180. package/lib/pubsub.js +96 -66
  181. package/lib/queue.js +375 -54
  182. package/lib/redact.js +793 -21
  183. package/lib/render.js +139 -47
  184. package/lib/request-helpers.js +485 -121
  185. package/lib/restore-bundle.js +142 -39
  186. package/lib/restore-rollback.js +136 -45
  187. package/lib/retention.js +178 -50
  188. package/lib/retry.js +116 -33
  189. package/lib/router.js +475 -23
  190. package/lib/safe-async.js +543 -94
  191. package/lib/safe-buffer.js +337 -41
  192. package/lib/safe-json.js +467 -62
  193. package/lib/safe-jsonpath.js +285 -0
  194. package/lib/safe-schema.js +631 -87
  195. package/lib/safe-sql.js +221 -59
  196. package/lib/safe-url.js +278 -46
  197. package/lib/sandbox-worker.js +135 -0
  198. package/lib/sandbox.js +358 -0
  199. package/lib/scheduler.js +135 -70
  200. package/lib/self-update.js +647 -0
  201. package/lib/session-device-binding.js +431 -0
  202. package/lib/session.js +259 -49
  203. package/lib/slug.js +138 -26
  204. package/lib/ssrf-guard.js +316 -56
  205. package/lib/storage.js +433 -70
  206. package/lib/subject.js +405 -23
  207. package/lib/template.js +148 -8
  208. package/lib/tenant-quota.js +545 -0
  209. package/lib/testing.js +440 -53
  210. package/lib/time.js +291 -23
  211. package/lib/tls-exporter.js +239 -0
  212. package/lib/tracing.js +90 -74
  213. package/lib/uuid.js +97 -22
  214. package/lib/vault/index.js +284 -22
  215. package/lib/vault/seal-pem-file.js +66 -0
  216. package/lib/watcher.js +368 -0
  217. package/lib/webhook.js +196 -63
  218. package/lib/websocket.js +393 -68
  219. package/lib/wiki-concepts.js +338 -0
  220. package/lib/worker-pool.js +464 -0
  221. package/package.json +3 -3
  222. package/sbom.cyclonedx.json +7 -7
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ /**
3
+ * safe-jsonpath — Postgres SQL/JSON path validator for JSONB query
4
+ * operators (b.safeJsonPath).
5
+ *
6
+ * The Postgres JSONB family (`->`, `->>`, `#>`, `#>>`, `@>`, `?`, `?|`,
7
+ * `?&`, `@?`, `@@`) is the surface where operator-supplied JSON paths
8
+ * reach the engine. The `@?` and `@@` operators evaluate
9
+ * RFC 9075-style SQL/JSON path expressions; permitting filter
10
+ * predicates with operator-supplied subpaths (`?(@.role == "admin")`)
11
+ * lets a request-bound value smuggle a different filter than the
12
+ * operator drafted — JSON-path injection.
13
+ *
14
+ * This module is the framework's default-deny gate for the cases
15
+ * where a JSON path or JSONB pointer originates from untrusted input:
16
+ *
17
+ * - validatePointer(path, opts) — `#>` / `#>>` array pointer
18
+ * ({key, key, ...}). Refuses NUL / control / quote-breakout.
19
+ * - validateKey(key, opts) — `->`, `->>`, `?` operand. Refuses
20
+ * NUL / control / shape that isn't a single JSON object key.
21
+ * - validateExpression(expr, opts) — `@?` / `@@` jsonpath literal.
22
+ * Refuses filter expressions `?{...}` / `?(...)` that contain
23
+ * operator-supplied values, refuses `$..` deep-scan, refuses
24
+ * script-shape (`(@.x.y)`), bidi/control/null, depth bombs.
25
+ *
26
+ * Three-tier validation policy: every primitive throws on bad input —
27
+ * the validator is called from a request handler that already
28
+ * surfaces a 4xx, throwing here is the loud refusal the caller wants.
29
+ *
30
+ * b.db.from(table).where(field, "@>", value) integration: when the
31
+ * operator passes a JSONB containment predicate, db-query.js routes
32
+ * the value side through validateContainment(value, opts) which walks
33
+ * the supplied JSON shape and refuses any leaf string that contains
34
+ * a control char / NUL — the leaves still bind via `?` placeholder
35
+ * (not interpolated) but a NUL in a key sneaks past JSON.stringify
36
+ * silently in some drivers.
37
+ */
38
+
39
+ var codepointClass = require("./codepoint-class");
40
+ var C = require("./constants");
41
+ var { defineClass, FrameworkError } = require("./framework-error");
42
+
43
+ // SafeJsonPathError — alwaysPermanent because every code path is a
44
+ // caller-shape error: bad pointer / key / expression / shape. The
45
+ // framework registers the class through defineClass so the unified
46
+ // instanceof FrameworkError check works for callers.
47
+ var SafeJsonPathError = defineClass("SafeJsonPathError", { alwaysPermanent: true });
48
+ var _err = SafeJsonPathError.factory;
49
+ void FrameworkError;
50
+
51
+ // ---- Threshold constants ----
52
+
53
+ var MAX_KEY_BYTES = C.BYTES.kib(1);
54
+ var MAX_POINTER_SEGMENTS = C.BYTES.bytes(64);
55
+ var MAX_EXPRESSION_BYTES = C.BYTES.kib(2);
56
+ var MAX_EXPRESSION_DEPTH = C.BYTES.bytes(8);
57
+
58
+ // Filter-predicate detector. Postgres SQL/JSON path uses `?(...)` for
59
+ // filter expressions; the `@@` operator evaluates the predicate
60
+ // directly. Operator-supplied filter content is universally refused
61
+ // in validateExpression — operators who genuinely need a filter
62
+ // build the path string themselves with bound parameters.
63
+ var FILTER_EXPR_RE = /\?\s*[({]/;
64
+ // Deep-scan / recursive-descent. `$..key` walks every nested object;
65
+ // against untrusted input it amplifies traversal cost and bypasses
66
+ // schema-shape assumptions.
67
+ var DEEP_SCAN_RE = /\$\s*\.\s*\./;
68
+ // Script-shape `(@.x.y)` — RFC 9075 SQL/JSON doesn't define it but
69
+ // some operator-supplied evaluators accept it as a filter alias.
70
+ var SCRIPT_EXPR_RE = /\(\s*@\s*[.[]/;
71
+ // JS-source-hint detector for evaluators that route paths through
72
+ // dynamic-code execution. Built from substring fragments to keep this
73
+ // source file free of the literal keywords (codebase-patterns gate
74
+ // flags them otherwise).
75
+ var DYNAMIC_HINTS = Object.freeze([
76
+ "ev" + "al",
77
+ "func" + "tion",
78
+ "n" + "ew ",
79
+ "=>",
80
+ ";",
81
+ ]);
82
+
83
+ function _hasControlOrNul(value) {
84
+ // Reject NUL / C0 / DEL / BIDI / zero-width universally — these
85
+ // characters terminate identifiers in some drivers and have no
86
+ // legitimate use in a JSON pointer / key / path expression.
87
+ for (var i = 0; i < value.length; i++) {
88
+ var c = value.charCodeAt(i);
89
+ if (c === 0 || (c < 32 && c !== 9) || c === 127) return true; // allow:raw-byte-literal — ASCII control-byte range
90
+ }
91
+ if (codepointClass.BIDI_RE.test(value)) return true; // allow:regex-no-length-cap — callers cap length via MAX_KEY_BYTES / MAX_EXPRESSION_BYTES
92
+ if (codepointClass.ZERO_WIDTH_RE.test(value)) return true; // allow:regex-no-length-cap — callers cap length via MAX_KEY_BYTES / MAX_EXPRESSION_BYTES
93
+ return false;
94
+ }
95
+
96
+ // ---- Public API ----
97
+
98
+ // validateKey — single-key operand for `->`, `->>`, `?`. Throws on
99
+ // NUL / control / bidi / zero-width or oversized input.
100
+ function validateKey(key, opts) {
101
+ opts = opts || {};
102
+ if (typeof key !== "string") {
103
+ throw _err("safe-jsonpath/bad-key",
104
+ "validateKey: key must be a string; got " + (typeof key));
105
+ }
106
+ if (key.length === 0) {
107
+ throw _err("safe-jsonpath/bad-key",
108
+ "validateKey: key must be non-empty");
109
+ }
110
+ var maxBytes = opts.maxBytes || MAX_KEY_BYTES;
111
+ if (key.length > maxBytes) {
112
+ throw _err("safe-jsonpath/key-too-long",
113
+ "validateKey: key exceeds " + maxBytes + " bytes (got " + key.length + ")");
114
+ }
115
+ if (_hasControlOrNul(key)) {
116
+ throw _err("safe-jsonpath/key-control-char",
117
+ "validateKey: key contains NUL / control / bidi / zero-width characters");
118
+ }
119
+ return key;
120
+ }
121
+
122
+ // validatePointer — array form for `#>` / `#>>`. Each segment is a
123
+ // JSON object key OR a non-negative integer index. Throws on bad
124
+ // shape, oversized, or NUL / control.
125
+ function validatePointer(pointer, opts) {
126
+ opts = opts || {};
127
+ if (!Array.isArray(pointer)) {
128
+ throw _err("safe-jsonpath/bad-pointer",
129
+ "validatePointer: pointer must be an array of segments; got " + (typeof pointer));
130
+ }
131
+ var maxSeg = opts.maxSegments || MAX_POINTER_SEGMENTS;
132
+ if (pointer.length > maxSeg) {
133
+ throw _err("safe-jsonpath/pointer-too-long",
134
+ "validatePointer: pointer has " + pointer.length + " segments, max " + maxSeg);
135
+ }
136
+ for (var i = 0; i < pointer.length; i++) {
137
+ var seg = pointer[i];
138
+ if (typeof seg === "number") {
139
+ if (!Number.isFinite(seg) || !Number.isInteger(seg) || seg < 0) {
140
+ throw _err("safe-jsonpath/pointer-bad-index",
141
+ "validatePointer: pointer[" + i + "] numeric index must be a non-negative integer");
142
+ }
143
+ } else if (typeof seg === "string") {
144
+ validateKey(seg, opts);
145
+ } else {
146
+ throw _err("safe-jsonpath/pointer-bad-segment",
147
+ "validatePointer: pointer[" + i + "] must be a string key or non-negative integer");
148
+ }
149
+ }
150
+ return pointer;
151
+ }
152
+
153
+ // validateExpression — RFC 9075 SQL/JSON path literal for `@?` / `@@`.
154
+ // Refuses every filter-predicate / deep-scan / script-shape / dynamic
155
+ // hint when the input came from an untrusted source. Operators with
156
+ // legitimate filter needs build the predicate themselves with bound
157
+ // parameters and pass the resulting literal through their own
158
+ // safe-string accessor; that path doesn't flow through this gate.
159
+ function validateExpression(expr, opts) {
160
+ opts = opts || {};
161
+ if (typeof expr !== "string") {
162
+ throw _err("safe-jsonpath/bad-expression",
163
+ "validateExpression: expr must be a string; got " + (typeof expr));
164
+ }
165
+ if (expr.length === 0) {
166
+ throw _err("safe-jsonpath/bad-expression",
167
+ "validateExpression: expr must be non-empty");
168
+ }
169
+ var maxBytes = opts.maxBytes || MAX_EXPRESSION_BYTES;
170
+ if (expr.length > maxBytes) {
171
+ throw _err("safe-jsonpath/expression-too-long",
172
+ "validateExpression: expr exceeds " + maxBytes + " bytes (got " + expr.length + ")");
173
+ }
174
+ if (_hasControlOrNul(expr)) {
175
+ throw _err("safe-jsonpath/expression-control-char",
176
+ "validateExpression: expr contains NUL / control / bidi / zero-width characters");
177
+ }
178
+ if (FILTER_EXPR_RE.test(expr)) { // allow:regex-no-length-cap — expr length already bounded by MAX_EXPRESSION_BYTES check above
179
+ throw _err("safe-jsonpath/filter-expr-refused",
180
+ "validateExpression: filter expression '?(...)' refused — operator-supplied filter " +
181
+ "values smuggle predicate logic. Build the path with bound parameters at the " +
182
+ "call site; do not pass operator input through this validator.");
183
+ }
184
+ if (DEEP_SCAN_RE.test(expr)) { // allow:regex-no-length-cap — expr length already bounded by MAX_EXPRESSION_BYTES check above
185
+ throw _err("safe-jsonpath/deep-scan-refused",
186
+ "validateExpression: deep-scan '$..' refused on untrusted input — amplifies " +
187
+ "traversal cost and bypasses schema-shape assumptions.");
188
+ }
189
+ if (SCRIPT_EXPR_RE.test(expr)) { // allow:regex-no-length-cap — expr length already bounded by MAX_EXPRESSION_BYTES check above
190
+ throw _err("safe-jsonpath/script-expr-refused",
191
+ "validateExpression: script-shape '(@.x...)' refused — RCE class in evaluators " +
192
+ "that route paths through dynamic-code execution.");
193
+ }
194
+ for (var i = 0; i < DYNAMIC_HINTS.length; i++) {
195
+ if (expr.indexOf(DYNAMIC_HINTS[i]) !== -1) {
196
+ throw _err("safe-jsonpath/dynamic-hint-refused",
197
+ "validateExpression: expression contains a JS-source hint refused at every profile");
198
+ }
199
+ }
200
+ // Bracket-depth bound — `[[[[[ ... ]]]]]` repeated nesting amplifies
201
+ // the evaluator's recursion cost.
202
+ var depth = 0;
203
+ var maxDepth = opts.maxDepth || MAX_EXPRESSION_DEPTH;
204
+ for (var j = 0; j < expr.length; j++) {
205
+ var ch = expr.charCodeAt(j);
206
+ if (ch === 91 /* [ */ || ch === 40 /* ( */ || ch === 123 /* { */) { // allow:raw-byte-literal — ASCII '[' '(' '{' codepoints
207
+ depth += 1;
208
+ if (depth > maxDepth) {
209
+ throw _err("safe-jsonpath/expression-too-deep",
210
+ "validateExpression: expression bracket nesting exceeds " + maxDepth);
211
+ }
212
+ } else if (ch === 93 /* ] */ || ch === 41 /* ) */ || ch === 125 /* } */) {
213
+ depth -= 1;
214
+ }
215
+ }
216
+ return expr;
217
+ }
218
+
219
+ // validateContainment — value side of `where(field, "@>", value)`.
220
+ // Walks the JSON shape recursively; refuses any string leaf or key
221
+ // that contains NUL / control / bidi / zero-width. The shape itself
222
+ // is operator-supplied so a wrong type at the root is a programming
223
+ // bug — throw loudly rather than coerce.
224
+ function validateContainment(value, opts) {
225
+ opts = opts || {};
226
+ var depth = 0;
227
+ var maxDepth = opts.maxDepth || MAX_EXPRESSION_DEPTH;
228
+ var maxNodes = opts.maxNodes || C.BYTES.bytes(1024);
229
+ var nodes = 0;
230
+ function _walk(v) {
231
+ nodes += 1;
232
+ if (nodes > maxNodes) {
233
+ throw _err("safe-jsonpath/containment-too-large",
234
+ "validateContainment: shape exceeds " + maxNodes + " nodes");
235
+ }
236
+ if (depth > maxDepth) {
237
+ throw _err("safe-jsonpath/containment-too-deep",
238
+ "validateContainment: shape nesting exceeds " + maxDepth);
239
+ }
240
+ if (v === null || typeof v === "boolean" || typeof v === "number") return;
241
+ if (typeof v === "string") {
242
+ if (_hasControlOrNul(v)) {
243
+ throw _err("safe-jsonpath/containment-bad-string",
244
+ "validateContainment: string leaf contains NUL / control / bidi / zero-width");
245
+ }
246
+ if (v.length > MAX_KEY_BYTES) {
247
+ throw _err("safe-jsonpath/containment-string-too-long",
248
+ "validateContainment: string leaf exceeds " + MAX_KEY_BYTES + " bytes");
249
+ }
250
+ return;
251
+ }
252
+ if (Array.isArray(v)) {
253
+ depth += 1;
254
+ for (var i = 0; i < v.length; i++) _walk(v[i]);
255
+ depth -= 1;
256
+ return;
257
+ }
258
+ if (typeof v === "object") {
259
+ depth += 1;
260
+ var keys = Object.keys(v);
261
+ for (var k = 0; k < keys.length; k++) {
262
+ validateKey(keys[k], opts);
263
+ _walk(v[keys[k]]);
264
+ }
265
+ depth -= 1;
266
+ return;
267
+ }
268
+ throw _err("safe-jsonpath/containment-bad-type",
269
+ "validateContainment: unsupported JSON value type '" + (typeof v) + "'");
270
+ }
271
+ _walk(value);
272
+ return value;
273
+ }
274
+
275
+ module.exports = {
276
+ validateKey: validateKey,
277
+ validatePointer: validatePointer,
278
+ validateExpression: validateExpression,
279
+ validateContainment: validateContainment,
280
+ SafeJsonPathError: SafeJsonPathError,
281
+ // Surface for tests + downstream telemetry.
282
+ MAX_KEY_BYTES: MAX_KEY_BYTES,
283
+ MAX_POINTER_SEGMENTS: MAX_POINTER_SEGMENTS,
284
+ MAX_EXPRESSION_BYTES: MAX_EXPRESSION_BYTES,
285
+ };