@bcts/envelope-pattern 1.0.0-alpha.23 → 1.0.0-beta.1

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 (60) hide show
  1. package/README.md +1 -1
  2. package/dist/index.cjs +1302 -774
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +101 -59
  5. package/dist/index.d.cts.map +1 -1
  6. package/dist/index.d.mts +102 -60
  7. package/dist/index.d.mts.map +1 -1
  8. package/dist/index.iife.js +1299 -771
  9. package/dist/index.iife.js.map +1 -1
  10. package/dist/index.mjs +1299 -774
  11. package/dist/index.mjs.map +1 -1
  12. package/package.json +11 -9
  13. package/src/format.ts +19 -31
  14. package/src/parse/index.ts +16 -1009
  15. package/src/parse/leaf/array-parser.ts +36 -0
  16. package/src/parse/leaf/cbor-parser.ts +43 -0
  17. package/src/parse/leaf/date-parser.ts +81 -0
  18. package/src/parse/leaf/known-value-parser.ts +73 -0
  19. package/src/parse/leaf/null-parser.ts +16 -0
  20. package/src/parse/leaf/number-parser.ts +90 -0
  21. package/src/parse/leaf/tag-parser.ts +160 -0
  22. package/src/parse/meta/and-parser.ts +40 -0
  23. package/src/parse/meta/capture-parser.ts +50 -0
  24. package/src/parse/meta/group-parser.ts +77 -0
  25. package/src/parse/meta/not-parser.ts +30 -0
  26. package/src/parse/meta/or-parser.ts +36 -0
  27. package/src/parse/meta/primary-parser.ts +234 -0
  28. package/src/parse/meta/search-parser.ts +41 -0
  29. package/src/parse/meta/traverse-parser.ts +42 -0
  30. package/src/parse/structure/assertion-obj-parser.ts +44 -0
  31. package/src/parse/structure/assertion-parser.ts +22 -0
  32. package/src/parse/structure/assertion-pred-parser.ts +45 -0
  33. package/src/parse/structure/compressed-parser.ts +17 -0
  34. package/src/parse/structure/digest-parser.ts +132 -0
  35. package/src/parse/structure/elided-parser.ts +17 -0
  36. package/src/parse/structure/encrypted-parser.ts +17 -0
  37. package/src/parse/structure/node-parser.ts +54 -0
  38. package/src/parse/structure/object-parser.ts +32 -0
  39. package/src/parse/structure/obscured-parser.ts +17 -0
  40. package/src/parse/structure/predicate-parser.ts +32 -0
  41. package/src/parse/structure/subject-parser.ts +32 -0
  42. package/src/parse/structure/wrapped-parser.ts +36 -0
  43. package/src/pattern/dcbor-integration.ts +40 -8
  44. package/src/pattern/index.ts +29 -0
  45. package/src/pattern/leaf/array-pattern.ts +67 -169
  46. package/src/pattern/leaf/cbor-pattern.ts +37 -23
  47. package/src/pattern/leaf/index.ts +1 -1
  48. package/src/pattern/leaf/map-pattern.ts +21 -2
  49. package/src/pattern/leaf/tagged-pattern.ts +6 -1
  50. package/src/pattern/meta/search-pattern.ts +13 -38
  51. package/src/pattern/meta/traverse-pattern.ts +2 -2
  52. package/src/pattern/structure/assertions-pattern.ts +19 -53
  53. package/src/pattern/structure/digest-pattern.ts +18 -22
  54. package/src/pattern/structure/index.ts +3 -0
  55. package/src/pattern/structure/node-pattern.ts +10 -29
  56. package/src/pattern/structure/object-pattern.ts +2 -2
  57. package/src/pattern/structure/predicate-pattern.ts +2 -2
  58. package/src/pattern/structure/subject-pattern.ts +31 -4
  59. package/src/pattern/structure/wrapped-pattern.ts +28 -9
  60. package/src/pattern/vm.ts +4 -4
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { Interval, Interval as Interval$1, Quantifier, Quantifier as Quantifier$1, Reluctance, Reluctance as Reluctance$1, boolPatternAny, boolPatternDisplay, boolPatternPaths, boolPatternValue, byteStringPatternAny, byteStringPatternBinaryRegex, byteStringPatternDisplay, byteStringPatternPaths, byteStringPatternValue, datePatternAny, datePatternDisplay, datePatternEarliest, datePatternLatest, datePatternPaths, datePatternRange, datePatternRegex, datePatternStringValue, datePatternValue, knownValuePatternAny, knownValuePatternDisplay, knownValuePatternMatches, knownValuePatternNamed, knownValuePatternRegex, knownValuePatternValue, nullPatternDisplay, nullPatternPaths, numberPatternAny, numberPatternDisplay, numberPatternGreaterThan, numberPatternGreaterThanOrEqual, numberPatternInfinity, numberPatternLessThan, numberPatternLessThanOrEqual, numberPatternNaN, numberPatternNegInfinity, numberPatternPaths, numberPatternRange, numberPatternValue, parse as parse$1, patternDisplay, patternPathsWithCaptures as patternPathsWithCaptures$1, taggedPatternAny, taggedPatternDisplay, taggedPatternPathsWithCaptures, taggedPatternWithName, taggedPatternWithRegex, taggedPatternWithTag, textPatternAny, textPatternDisplay, textPatternPaths, textPatternRegex, textPatternValue } from "@bcts/dcbor-pattern";
2
- import { UNIT } from "@bcts/known-values";
3
- import { Envelope } from "@bcts/envelope";
4
- import { CborDate, asCborArray, asCborMap, bytesToHex, cbor } from "@bcts/dcbor";
1
+ import { Interval, Interval as Interval$1, Quantifier, Quantifier as Quantifier$1, Reluctance, Reluctance as Reluctance$1, arrayPatternAny, arrayPatternDisplay, arrayPatternEquals, arrayPatternMatches, arrayPatternWithElements, arrayPatternWithLength, arrayPatternWithLengthInterval, arrayPatternWithLengthRange, boolPatternAny, boolPatternDisplay, boolPatternPaths, boolPatternValue, byteStringPatternAny, byteStringPatternBinaryRegex, byteStringPatternDisplay, byteStringPatternPaths, byteStringPatternValue, datePatternAny, datePatternDisplay, datePatternEarliest, datePatternLatest, datePatternPaths, datePatternRange, datePatternRegex, datePatternStringValue, datePatternValue, knownValuePatternAny, knownValuePatternDisplay, knownValuePatternMatches, knownValuePatternNamed, knownValuePatternRegex, knownValuePatternValue, nullPatternDisplay, nullPatternPaths, numberPatternAny, numberPatternDisplay, numberPatternGreaterThan, numberPatternGreaterThanOrEqual, numberPatternInfinity, numberPatternLessThan, numberPatternLessThanOrEqual, numberPatternNaN, numberPatternNegInfinity, numberPatternPaths, numberPatternRange, numberPatternValue, parse as parse$1, patternDisplay, patternPathsWithCaptures as patternPathsWithCaptures$1, taggedPatternAny, taggedPatternDisplay, taggedPatternPathsWithCaptures, taggedPatternWithName, taggedPatternWithRegex, taggedPatternWithTag, textPatternAny, textPatternDisplay, textPatternPaths, textPatternRegex, textPatternValue } from "@bcts/dcbor-pattern";
2
+ import { KnownValue, UNIT } from "@bcts/known-values";
3
+ import { CborDate, asCborMap, bytesToHex, cbor, cborData, cborEquals } from "@bcts/dcbor";
4
+ import { Digest, Envelope } from "@bcts/envelope";
5
5
  import { parseDcborItemPartial } from "@bcts/dcbor-parse";
6
6
  //#region src/error.ts
7
7
  /**
@@ -305,6 +305,14 @@ function formatPathsOpts() {
305
305
  /**
306
306
  * Gets a summary of an envelope for display.
307
307
  *
308
+ * Mirrors Rust `envelope_summary` in `format.rs`: defers to
309
+ * `Envelope::format_flat()` for nodes / wrapped / assertions and to
310
+ * `cbor.envelope_summary(usize::MAX, ...)` for raw CBOR leaves. The
311
+ * obscured cases (`elided` / `encrypted` / `compressed`) emit just the
312
+ * keyword. KnownValue envelopes look up the canonical name via
313
+ * `KnownValue.name()`, matching the Rust call to
314
+ * `KnownValuesStore::known_value_for_raw_value(value, …)`.
315
+ *
308
316
  * @param env - The envelope to summarize
309
317
  * @returns A string summary of the envelope
310
318
  */
@@ -313,25 +321,17 @@ function envelopeSummary(env) {
313
321
  const c = env.case();
314
322
  let summary;
315
323
  switch (c.type) {
316
- case "node": {
317
- const subjectSummary = env.subject().summary(Number.MAX_SAFE_INTEGER);
318
- const assertions = env.assertions();
319
- if (assertions.length > 0) summary = `NODE ${subjectSummary} [ ${assertions.map((a) => {
320
- const ac = a.case();
321
- if (ac.type === "assertion") return `${ac.assertion.predicate().summary(Number.MAX_SAFE_INTEGER)}: ${ac.assertion.object().summary(Number.MAX_SAFE_INTEGER)}`;
322
- return a.summary(Number.MAX_SAFE_INTEGER);
323
- }).join(", ")} ]`;
324
- else summary = `NODE ${subjectSummary}`;
324
+ case "node":
325
+ summary = `NODE ${env.formatFlat()}`;
325
326
  break;
326
- }
327
327
  case "leaf":
328
328
  summary = `LEAF ${env.summary(Number.MAX_SAFE_INTEGER)}`;
329
329
  break;
330
330
  case "wrapped":
331
- summary = `WRAPPED ${env.summary(Number.MAX_SAFE_INTEGER)}`;
331
+ summary = `WRAPPED ${env.formatFlat()}`;
332
332
  break;
333
333
  case "assertion":
334
- summary = `ASSERTION ${c.assertion.predicate().summary(Number.MAX_SAFE_INTEGER)}: ${c.assertion.object().summary(Number.MAX_SAFE_INTEGER)}`;
334
+ summary = `ASSERTION ${env.formatFlat()}`;
335
335
  break;
336
336
  case "elided":
337
337
  summary = "ELIDED";
@@ -377,8 +377,8 @@ function formatPathOpt(path, opts = defaultFormatPathsOpts()) {
377
377
  if (element === void 0) return "";
378
378
  switch (opts.elementFormat.type) {
379
379
  case "Summary": return truncateWithEllipsis(envelopeSummary(element), opts.elementFormat.maxLength);
380
- case "EnvelopeUR": return element.digest().toString();
381
- case "DigestUR": return element.digest().toString();
380
+ case "EnvelopeUR": return element.urString();
381
+ case "DigestUR": return element.digest().urString();
382
382
  }
383
383
  }
384
384
  switch (opts.elementFormat.type) {
@@ -393,8 +393,8 @@ function formatPathOpt(path, opts = defaultFormatPathsOpts()) {
393
393
  }
394
394
  return lines.join("\n");
395
395
  }
396
- case "EnvelopeUR": return path.map((element) => element.digest().toString()).join(" ");
397
- case "DigestUR": return path.map((element) => element.digest().toString()).join(" ");
396
+ case "EnvelopeUR": return path.map((element) => element.urString()).join(" ");
397
+ case "DigestUR": return path.map((element) => element.digest().urString()).join(" ");
398
398
  }
399
399
  }
400
400
  /**
@@ -1236,25 +1236,16 @@ var DatePattern = class DatePattern {
1236
1236
  };
1237
1237
  //#endregion
1238
1238
  //#region src/pattern/leaf/array-pattern.ts
1239
- /**
1240
- * Copyright © 2023-2026 Blockchain Commons, LLC
1241
- * Copyright © 2025-2026 Parity Technologies
1242
- *
1243
- *
1244
- * @bcts/envelope-pattern - Array pattern matching
1245
- *
1246
- * This is a 1:1 TypeScript port of bc-envelope-pattern-rust array_pattern.rs
1247
- *
1248
- * @module envelope-pattern/pattern/leaf/array-pattern
1249
- */
1250
1239
  let createLeafArrayPattern;
1251
1240
  function registerArrayPatternFactory(factory) {
1252
1241
  createLeafArrayPattern = factory;
1253
1242
  }
1254
1243
  /**
1255
- * Pattern for matching array values in envelope leaf nodes.
1244
+ * Pattern for matching arrays.
1256
1245
  *
1257
- * Corresponds to the Rust `ArrayPattern` struct in array_pattern.rs
1246
+ * Mirrors Rust `ArrayPattern(dcbor_pattern::ArrayPattern)` from
1247
+ * `bc-envelope-pattern-rust/src/pattern/leaf/array_pattern.rs`. All
1248
+ * matching, display, and equality is delegated to dcbor-pattern.
1258
1249
  */
1259
1250
  var ArrayPattern = class ArrayPattern {
1260
1251
  _pattern;
@@ -1265,93 +1256,54 @@ var ArrayPattern = class ArrayPattern {
1265
1256
  * Creates a new ArrayPattern that matches any array.
1266
1257
  */
1267
1258
  static any() {
1268
- return new ArrayPattern({ type: "Any" });
1259
+ return new ArrayPattern(arrayPatternAny());
1269
1260
  }
1270
1261
  /**
1271
1262
  * Creates a new ArrayPattern that matches arrays with a specific length.
1272
1263
  */
1273
1264
  static count(count) {
1274
- return new ArrayPattern({
1275
- type: "Interval",
1276
- interval: Interval$1.exactly(count)
1277
- });
1265
+ return new ArrayPattern(arrayPatternWithLength(count));
1278
1266
  }
1279
1267
  /**
1280
1268
  * Creates a new ArrayPattern that matches arrays within a length range.
1281
1269
  */
1282
1270
  static interval(min, max) {
1283
- return new ArrayPattern({
1284
- type: "Interval",
1285
- interval: max !== void 0 ? Interval$1.from(min, max) : Interval$1.atLeast(min)
1286
- });
1271
+ return new ArrayPattern(arrayPatternWithLengthRange(min, max));
1287
1272
  }
1288
1273
  /**
1289
- * Creates a new ArrayPattern from a dcbor-pattern.
1274
+ * Creates a new ArrayPattern from a length Interval.
1290
1275
  */
1291
- static fromDcborPattern(dcborPattern) {
1292
- return new ArrayPattern({
1293
- type: "DCBORPattern",
1294
- pattern: dcborPattern
1295
- });
1276
+ static fromInterval(interval) {
1277
+ return new ArrayPattern(arrayPatternWithLengthInterval(interval));
1296
1278
  }
1297
1279
  /**
1298
- * Creates a new ArrayPattern with envelope patterns for element matching.
1280
+ * Creates a new ArrayPattern from a top-level dcbor-pattern.
1281
+ *
1282
+ * Mirrors Rust `ArrayPattern::from_dcbor_pattern`, which constructs an
1283
+ * `ArrayPattern::Elements`-style dcbor array pattern.
1299
1284
  */
1300
- static withPatterns(patterns) {
1301
- return new ArrayPattern({
1302
- type: "WithPatterns",
1303
- patterns
1304
- });
1285
+ static fromDcborPattern(pattern) {
1286
+ return new ArrayPattern(arrayPatternWithElements(pattern));
1305
1287
  }
1306
1288
  /**
1307
- * Gets the pattern type.
1289
+ * Creates a new ArrayPattern from an existing dcbor-pattern ArrayPattern.
1290
+ *
1291
+ * Mirrors Rust `ArrayPattern::from_dcbor_array_pattern`.
1308
1292
  */
1309
- get pattern() {
1293
+ static fromDcborArrayPattern(arrayPattern) {
1294
+ return new ArrayPattern(arrayPattern);
1295
+ }
1296
+ /**
1297
+ * Returns the underlying dcbor-pattern ArrayPattern.
1298
+ */
1299
+ inner() {
1310
1300
  return this._pattern;
1311
1301
  }
1312
1302
  pathsWithCaptures(haystack) {
1313
1303
  const cbor = haystack.subject().asLeaf();
1314
1304
  if (cbor === void 0) return [[], /* @__PURE__ */ new Map()];
1315
- const array = asCborArray(cbor);
1316
- if (array === void 0) return [[], /* @__PURE__ */ new Map()];
1317
- switch (this._pattern.type) {
1318
- case "Any": return [[[haystack]], /* @__PURE__ */ new Map()];
1319
- case "Interval": {
1320
- const length = array.length;
1321
- if (this._pattern.interval.contains(length)) return [[[haystack]], /* @__PURE__ */ new Map()];
1322
- return [[], /* @__PURE__ */ new Map()];
1323
- }
1324
- case "DCBORPattern": {
1325
- const { paths: dcborPaths, captures: dcborCaptures } = patternPathsWithCaptures$1(this._pattern.pattern, cbor);
1326
- if (dcborPaths.length > 0) {
1327
- const envelopePaths = dcborPaths.map((dcborPath) => {
1328
- const envPath = [haystack];
1329
- for (let i = 1; i < dcborPath.length; i++) {
1330
- const elem = dcborPath[i];
1331
- if (elem !== void 0) envPath.push(Envelope.newLeaf(elem));
1332
- }
1333
- return envPath;
1334
- });
1335
- const envelopeCaptures = /* @__PURE__ */ new Map();
1336
- for (const [name, capturePaths] of dcborCaptures) {
1337
- const envCapturePaths = capturePaths.map((dcborPath) => {
1338
- const envPath = [haystack];
1339
- for (let i = 1; i < dcborPath.length; i++) {
1340
- const elem = dcborPath[i];
1341
- if (elem !== void 0) envPath.push(Envelope.newLeaf(elem));
1342
- }
1343
- return envPath;
1344
- });
1345
- envelopeCaptures.set(name, envCapturePaths);
1346
- }
1347
- return [envelopePaths, envelopeCaptures];
1348
- }
1349
- return [[], /* @__PURE__ */ new Map()];
1350
- }
1351
- case "WithPatterns":
1352
- if (array.length === this._pattern.patterns.length) return [[[haystack]], /* @__PURE__ */ new Map()];
1353
- return [[], /* @__PURE__ */ new Map()];
1354
- }
1305
+ if (arrayPatternMatches(this._pattern, cbor)) return [[[haystack]], /* @__PURE__ */ new Map()];
1306
+ return [[], /* @__PURE__ */ new Map()];
1355
1307
  }
1356
1308
  paths(haystack) {
1357
1309
  return this.pathsWithCaptures(haystack)[0];
@@ -1367,54 +1319,31 @@ var ArrayPattern = class ArrayPattern {
1367
1319
  return false;
1368
1320
  }
1369
1321
  toString() {
1370
- switch (this._pattern.type) {
1371
- case "Any": return "[*]";
1372
- case "Interval": return `[{${this._pattern.interval.toString()}}]`;
1373
- case "DCBORPattern": return patternDisplay(this._pattern.pattern);
1374
- case "WithPatterns": return `[${this._pattern.patterns.map(String).join(", ")}]`;
1375
- }
1322
+ return arrayPatternDisplay(this._pattern, patternDisplay);
1376
1323
  }
1377
1324
  /**
1378
- * Equality comparison.
1325
+ * Equality comparison. Delegates to dcbor-pattern's structural equality
1326
+ * with a display-string fallback for pattern-equality (mirrors Rust's
1327
+ * `Hash` impl that hashes the display, since dcbor `ArrayPattern`
1328
+ * itself does not derive `Hash`).
1379
1329
  */
1380
1330
  equals(other) {
1381
- if (this._pattern.type !== other._pattern.type) return false;
1382
- switch (this._pattern.type) {
1383
- case "Any": return true;
1384
- case "Interval": return this._pattern.interval.equals(other._pattern.interval);
1385
- case "DCBORPattern": return patternDisplay(this._pattern.pattern) === patternDisplay(other._pattern.pattern);
1386
- case "WithPatterns": {
1387
- const otherPatterns = other._pattern.patterns;
1388
- if (this._pattern.patterns.length !== otherPatterns.length) return false;
1389
- for (let i = 0; i < this._pattern.patterns.length; i++) if (this._pattern.patterns[i] !== otherPatterns[i]) return false;
1390
- return true;
1391
- }
1392
- }
1331
+ return arrayPatternEquals(this._pattern, other._pattern, (a, b) => patternDisplay(a) === patternDisplay(b));
1393
1332
  }
1394
1333
  /**
1395
- * Hash code for use in Maps/Sets.
1334
+ * Hash code for use in Maps/Sets. Mirrors Rust's
1335
+ * "hash the string representation" approach.
1396
1336
  */
1397
1337
  hashCode() {
1398
- switch (this._pattern.type) {
1399
- case "Any": return 0;
1400
- case "Interval": return this._pattern.interval.min() * 31 + (this._pattern.interval.max() ?? 0);
1401
- case "DCBORPattern": return simpleStringHash$3(patternDisplay(this._pattern.pattern));
1402
- case "WithPatterns": return this._pattern.patterns.length;
1338
+ let hash = 0;
1339
+ const str = this.toString();
1340
+ for (let i = 0; i < str.length; i++) {
1341
+ hash = (hash << 5) - hash + str.charCodeAt(i);
1342
+ hash = hash & hash;
1403
1343
  }
1344
+ return hash;
1404
1345
  }
1405
1346
  };
1406
- /**
1407
- * Simple string hash function for hashCode implementations.
1408
- */
1409
- function simpleStringHash$3(str) {
1410
- let hash = 0;
1411
- for (let i = 0; i < str.length; i++) {
1412
- const char = str.charCodeAt(i);
1413
- hash = (hash << 5) - hash + char;
1414
- hash = hash & hash;
1415
- }
1416
- return hash;
1417
- }
1418
1347
  //#endregion
1419
1348
  //#region src/pattern/leaf/map-pattern.ts
1420
1349
  let createLeafMapPattern;
@@ -1447,6 +1376,19 @@ var MapPattern = class MapPattern {
1447
1376
  });
1448
1377
  }
1449
1378
  /**
1379
+ * Creates a new MapPattern from a length Interval.
1380
+ *
1381
+ * Mirrors Rust `MapPattern::from_interval`. Used by the
1382
+ * dcbor-pattern → envelope-pattern bridge to preserve `{{n,m}}`
1383
+ * length info.
1384
+ */
1385
+ static fromInterval(interval) {
1386
+ return new MapPattern({
1387
+ type: "Interval",
1388
+ interval
1389
+ });
1390
+ }
1391
+ /**
1450
1392
  * Gets the pattern type.
1451
1393
  */
1452
1394
  get pattern() {
@@ -1481,8 +1423,8 @@ var MapPattern = class MapPattern {
1481
1423
  }
1482
1424
  toString() {
1483
1425
  switch (this._pattern.type) {
1484
- case "Any": return "{*}";
1485
- case "Interval": return `{{${this._pattern.interval.toString()}}}`;
1426
+ case "Any": return "map";
1427
+ case "Interval": return `{${this._pattern.interval.toString()}}`;
1486
1428
  }
1487
1429
  }
1488
1430
  /**
@@ -1735,7 +1677,7 @@ var TaggedPattern = class TaggedPattern {
1735
1677
  return false;
1736
1678
  }
1737
1679
  toString() {
1738
- return taggedPatternDisplay(this._inner, patternDisplay);
1680
+ return taggedPatternDisplay(this._inner, patternDisplay).replace(", ", ", ");
1739
1681
  }
1740
1682
  /**
1741
1683
  * Equality comparison.
@@ -1861,10 +1803,18 @@ var CBORPattern = class CBORPattern {
1861
1803
  }
1862
1804
  /**
1863
1805
  * Convert a single dcbor path to an envelope path.
1806
+ *
1807
+ * Uses canonical CBOR-byte equality (`cborEquals`) for the "skip the
1808
+ * dcbor root if it duplicates our base envelope" check, mirroring
1809
+ * Rust's `dcbor_path.first().map(|first| first == &base_cbor)`. The
1810
+ * earlier port compared diagnostic strings, which collapses values
1811
+ * that share a textual representation but differ structurally
1812
+ * (e.g. NaN payloads).
1864
1813
  */
1865
1814
  _convertDcborPathToEnvelopePath(dcborPath, baseEnvelope, baseCbor) {
1866
1815
  const envelopePath = [baseEnvelope];
1867
- const elementsToAdd = dcborPath.length > 0 && dcborPath[0]?.toDiagnostic() === baseCbor.toDiagnostic() ? dcborPath.slice(1) : dcborPath;
1816
+ const first = dcborPath[0];
1817
+ const elementsToAdd = first !== void 0 && cborEquals(first, baseCbor) ? dcborPath.slice(1) : dcborPath;
1868
1818
  for (const cborElement of elementsToAdd) envelopePath.push(Envelope.newLeaf(cborElement));
1869
1819
  return envelopePath;
1870
1820
  }
@@ -1891,7 +1841,7 @@ var CBORPattern = class CBORPattern {
1891
1841
  switch (this._pattern.type) {
1892
1842
  case "Any": return [[[haystack]], /* @__PURE__ */ new Map()];
1893
1843
  case "Value":
1894
- if (knownValueCbor.toDiagnostic() === this._pattern.cbor.toDiagnostic()) return [[[haystack]], /* @__PURE__ */ new Map()];
1844
+ if (cborEquals(knownValueCbor, this._pattern.cbor)) return [[[haystack]], /* @__PURE__ */ new Map()];
1895
1845
  return [[], /* @__PURE__ */ new Map()];
1896
1846
  case "Pattern": {
1897
1847
  const { paths: dcborPaths, captures: dcborCaptures } = patternPathsWithCaptures$1(this._pattern.pattern, knownValueCbor);
@@ -1915,7 +1865,7 @@ var CBORPattern = class CBORPattern {
1915
1865
  switch (this._pattern.type) {
1916
1866
  case "Any": return [[[haystack]], /* @__PURE__ */ new Map()];
1917
1867
  case "Value":
1918
- if (leafCbor.toDiagnostic() === this._pattern.cbor.toDiagnostic()) return [[[haystack]], /* @__PURE__ */ new Map()];
1868
+ if (cborEquals(leafCbor, this._pattern.cbor)) return [[[haystack]], /* @__PURE__ */ new Map()];
1919
1869
  return [[], /* @__PURE__ */ new Map()];
1920
1870
  case "Pattern": {
1921
1871
  const { paths: dcborPaths, captures: dcborCaptures } = patternPathsWithCaptures$1(this._pattern.pattern, leafCbor);
@@ -1923,7 +1873,8 @@ var CBORPattern = class CBORPattern {
1923
1873
  const basePath = [haystack];
1924
1874
  return [dcborPaths.map((dcborPath) => {
1925
1875
  const extendedPath = [...basePath];
1926
- const elementsToAdd = dcborPath.length > 0 && dcborPath[0]?.toDiagnostic() === leafCbor.toDiagnostic() ? dcborPath.slice(1) : dcborPath;
1876
+ const first = dcborPath[0];
1877
+ const elementsToAdd = first !== void 0 && cborEquals(first, leafCbor) ? dcborPath.slice(1) : dcborPath;
1927
1878
  for (const cborElement of elementsToAdd) extendedPath.push(Envelope.newLeaf(cborElement));
1928
1879
  return extendedPath;
1929
1880
  }), this._convertDcborCapturesToEnvelopeCaptures(dcborCaptures, haystack, leafCbor)];
@@ -1958,13 +1909,16 @@ var CBORPattern = class CBORPattern {
1958
1909
  }
1959
1910
  }
1960
1911
  /**
1961
- * Equality comparison.
1912
+ * Equality comparison. `Value` variants compare by canonical CBOR
1913
+ * byte sequence (mirrors Rust `==` on `CBOR`); `Pattern` variants fall
1914
+ * back to display-string compare since `DCBORPattern` doesn't expose
1915
+ * structural equality outside the crate.
1962
1916
  */
1963
1917
  equals(other) {
1964
1918
  if (this._pattern.type !== other._pattern.type) return false;
1965
1919
  switch (this._pattern.type) {
1966
1920
  case "Any": return true;
1967
- case "Value": return this._pattern.cbor.toDiagnostic() === other._pattern.cbor.toDiagnostic();
1921
+ case "Value": return cborEquals(this._pattern.cbor, other._pattern.cbor);
1968
1922
  case "Pattern": return patternDisplay(this._pattern.pattern) === patternDisplay(other._pattern.pattern);
1969
1923
  }
1970
1924
  }
@@ -1974,7 +1928,12 @@ var CBORPattern = class CBORPattern {
1974
1928
  hashCode() {
1975
1929
  switch (this._pattern.type) {
1976
1930
  case "Any": return 0;
1977
- case "Value": return simpleStringHash(this._pattern.cbor.toDiagnostic());
1931
+ case "Value": {
1932
+ const bytes = cborData(this._pattern.cbor);
1933
+ let hash = 0;
1934
+ for (const byte of bytes) hash = hash * 31 + byte | 0;
1935
+ return hash;
1936
+ }
1978
1937
  case "Pattern": return simpleStringHash(patternDisplay(this._pattern.pattern));
1979
1938
  }
1980
1939
  }
@@ -2243,7 +2202,13 @@ var LeafStructurePattern = class LeafStructurePattern {
2243
2202
  return 0;
2244
2203
  }
2245
2204
  };
2205
+ let dispatchPatternCompile$1;
2206
+ let dispatchPatternToString$3;
2246
2207
  function registerSubjectPatternFactory(factory) {}
2208
+ function registerSubjectPatternDispatch(dispatch) {
2209
+ dispatchPatternCompile$1 = dispatch.compile;
2210
+ dispatchPatternToString$3 = dispatch.toString;
2211
+ }
2247
2212
  /**
2248
2213
  * Pattern for matching subjects in envelopes.
2249
2214
  *
@@ -2307,9 +2272,10 @@ var SubjectPattern = class SubjectPattern {
2307
2272
  code.push({ type: "NavigateSubject" });
2308
2273
  break;
2309
2274
  case "Pattern":
2275
+ if (dispatchPatternCompile$1 === void 0) throw new Error("SubjectPattern.compile requires the top-level Pattern compile dispatch; not registered");
2310
2276
  code.push({ type: "NavigateSubject" });
2311
2277
  code.push({ type: "ExtendTraversal" });
2312
- this._pattern.pattern.compile(code, literals, captures);
2278
+ dispatchPatternCompile$1(this._pattern.pattern, code, literals, captures);
2313
2279
  code.push({ type: "CombineTraversal" });
2314
2280
  break;
2315
2281
  }
@@ -2320,7 +2286,10 @@ var SubjectPattern = class SubjectPattern {
2320
2286
  toString() {
2321
2287
  switch (this._pattern.type) {
2322
2288
  case "Any": return "subj";
2323
- case "Pattern": return `subj(${this._pattern.pattern.toString()})`;
2289
+ case "Pattern": {
2290
+ const fmt = dispatchPatternToString$3;
2291
+ return `subj(${fmt !== void 0 ? fmt(this._pattern.pattern) : "?"})`;
2292
+ }
2324
2293
  }
2325
2294
  }
2326
2295
  /**
@@ -2417,7 +2386,7 @@ var PredicatePattern = class PredicatePattern {
2417
2386
  toString() {
2418
2387
  switch (this._pattern.type) {
2419
2388
  case "Any": return "pred";
2420
- case "Pattern": return `pred(${this._pattern.pattern.toString()})`;
2389
+ case "Pattern": return `pred(${dispatchPatternToString(this._pattern.pattern)})`;
2421
2390
  }
2422
2391
  }
2423
2392
  /**
@@ -2514,7 +2483,7 @@ var ObjectPattern = class ObjectPattern {
2514
2483
  toString() {
2515
2484
  switch (this._pattern.type) {
2516
2485
  case "Any": return "obj";
2517
- case "Pattern": return `obj(${this._pattern.pattern.toString()})`;
2486
+ case "Pattern": return `obj(${dispatchPatternToString(this._pattern.pattern)})`;
2518
2487
  }
2519
2488
  }
2520
2489
  /**
@@ -2535,9 +2504,13 @@ var ObjectPattern = class ObjectPattern {
2535
2504
  //#endregion
2536
2505
  //#region src/pattern/structure/assertions-pattern.ts
2537
2506
  let createStructureAssertionsPattern;
2507
+ let dispatchPatternToString$2;
2538
2508
  function registerAssertionsPatternFactory(factory) {
2539
2509
  createStructureAssertionsPattern = factory;
2540
2510
  }
2511
+ function registerAssertionsPatternToStringDispatch(fn) {
2512
+ dispatchPatternToString$2 = fn;
2513
+ }
2541
2514
  /**
2542
2515
  * Pattern for matching assertions in envelopes.
2543
2516
  *
@@ -2575,17 +2548,6 @@ var AssertionsPattern = class AssertionsPattern {
2575
2548
  });
2576
2549
  }
2577
2550
  /**
2578
- * Creates a new AssertionsPattern that matches assertions with both
2579
- * predicate and object patterns.
2580
- */
2581
- static withBoth(predicatePattern, objectPattern) {
2582
- return new AssertionsPattern({
2583
- type: "WithBoth",
2584
- predicatePattern,
2585
- objectPattern
2586
- });
2587
- }
2588
- /**
2589
2551
  * Gets the pattern type.
2590
2552
  */
2591
2553
  get patternType() {
@@ -2596,14 +2558,12 @@ var AssertionsPattern = class AssertionsPattern {
2596
2558
  */
2597
2559
  predicatePattern() {
2598
2560
  if (this._pattern.type === "WithPredicate") return this._pattern.pattern;
2599
- if (this._pattern.type === "WithBoth") return this._pattern.predicatePattern;
2600
2561
  }
2601
2562
  /**
2602
2563
  * Gets the object pattern if this has one, undefined otherwise.
2603
2564
  */
2604
2565
  objectPattern() {
2605
2566
  if (this._pattern.type === "WithObject") return this._pattern.pattern;
2606
- if (this._pattern.type === "WithBoth") return this._pattern.objectPattern;
2607
2567
  }
2608
2568
  pathsWithCaptures(haystack) {
2609
2569
  const paths = [];
@@ -2625,14 +2585,6 @@ var AssertionsPattern = class AssertionsPattern {
2625
2585
  }
2626
2586
  break;
2627
2587
  }
2628
- case "WithBoth": {
2629
- const predicate = assertion.asPredicate?.();
2630
- const object = assertion.asObject?.();
2631
- if (predicate !== void 0 && object !== void 0) {
2632
- if (matchPattern(this._pattern.predicatePattern, predicate) && matchPattern(this._pattern.objectPattern, object)) paths.push([assertion]);
2633
- }
2634
- break;
2635
- }
2636
2588
  }
2637
2589
  return [paths, /* @__PURE__ */ new Map()];
2638
2590
  }
@@ -2655,11 +2607,11 @@ var AssertionsPattern = class AssertionsPattern {
2655
2607
  return false;
2656
2608
  }
2657
2609
  toString() {
2610
+ const fmt = dispatchPatternToString$2;
2658
2611
  switch (this._pattern.type) {
2659
2612
  case "Any": return "assert";
2660
- case "WithPredicate": return `assertpred(${this._pattern.pattern.toString()})`;
2661
- case "WithObject": return `assertobj(${this._pattern.pattern.toString()})`;
2662
- case "WithBoth": return `assert(${this._pattern.predicatePattern.toString()}, ${this._pattern.objectPattern.toString()})`;
2613
+ case "WithPredicate": return `assertpred(${fmt !== void 0 ? fmt(this._pattern.pattern) : "?"})`;
2614
+ case "WithObject": return `assertobj(${fmt !== void 0 ? fmt(this._pattern.pattern) : "?"})`;
2663
2615
  }
2664
2616
  }
2665
2617
  /**
@@ -2671,10 +2623,6 @@ var AssertionsPattern = class AssertionsPattern {
2671
2623
  case "Any": return true;
2672
2624
  case "WithPredicate":
2673
2625
  case "WithObject": return this._pattern.pattern === other._pattern.pattern;
2674
- case "WithBoth": {
2675
- const otherBoth = other._pattern;
2676
- return this._pattern.predicatePattern === otherBoth.predicatePattern && this._pattern.objectPattern === otherBoth.objectPattern;
2677
- }
2678
2626
  }
2679
2627
  }
2680
2628
  /**
@@ -2685,7 +2633,6 @@ var AssertionsPattern = class AssertionsPattern {
2685
2633
  case "Any": return 0;
2686
2634
  case "WithPredicate": return 1;
2687
2635
  case "WithObject": return 2;
2688
- case "WithBoth": return 3;
2689
2636
  }
2690
2637
  }
2691
2638
  };
@@ -2714,12 +2661,6 @@ var DigestPattern = class DigestPattern {
2714
2661
  this._pattern = pattern;
2715
2662
  }
2716
2663
  /**
2717
- * Creates a new DigestPattern that matches any digest.
2718
- */
2719
- static any() {
2720
- return new DigestPattern({ type: "Any" });
2721
- }
2722
- /**
2723
2664
  * Creates a new DigestPattern that matches the exact digest.
2724
2665
  */
2725
2666
  static digest(digest) {
@@ -2757,9 +2698,6 @@ var DigestPattern = class DigestPattern {
2757
2698
  const digestData = digest.data();
2758
2699
  let isHit = false;
2759
2700
  switch (this._pattern.type) {
2760
- case "Any":
2761
- isHit = true;
2762
- break;
2763
2701
  case "Digest":
2764
2702
  isHit = digest.equals(this._pattern.digest);
2765
2703
  break;
@@ -2797,7 +2735,6 @@ var DigestPattern = class DigestPattern {
2797
2735
  }
2798
2736
  toString() {
2799
2737
  switch (this._pattern.type) {
2800
- case "Any": return "digest";
2801
2738
  case "Digest": return `digest(${this._pattern.digest.hex()})`;
2802
2739
  case "Prefix": return `digest(${bytesToHex(this._pattern.prefix)})`;
2803
2740
  case "BinaryRegex": return `digest(/${this._pattern.regex.source}/)`;
@@ -2805,17 +2742,26 @@ var DigestPattern = class DigestPattern {
2805
2742
  }
2806
2743
  /**
2807
2744
  * Equality comparison.
2745
+ *
2746
+ * `Prefix` comparison is case-insensitive on the *hex representation* to
2747
+ * mirror Rust's `eq_ignore_ascii_case` (which compares the underlying
2748
+ * `Vec<u8>` of hex bytes byte-for-byte modulo ASCII case). For raw byte
2749
+ * prefixes that happen to be ASCII, this is an ordinary byte compare.
2808
2750
  */
2809
2751
  equals(other) {
2810
2752
  if (this._pattern.type !== other._pattern.type) return false;
2811
2753
  switch (this._pattern.type) {
2812
- case "Any": return true;
2813
2754
  case "Digest": return this._pattern.digest.equals(other._pattern.digest);
2814
2755
  case "Prefix": {
2815
2756
  const thisPrefix = this._pattern.prefix;
2816
2757
  const otherPrefix = other._pattern.prefix;
2817
2758
  if (thisPrefix.length !== otherPrefix.length) return false;
2818
- for (let i = 0; i < thisPrefix.length; i++) if (thisPrefix[i] !== otherPrefix[i]) return false;
2759
+ for (let i = 0; i < thisPrefix.length; i++) {
2760
+ const a = thisPrefix[i];
2761
+ const b = otherPrefix[i];
2762
+ if (a === b) continue;
2763
+ if ((a >= 65 && a <= 90 ? a + 32 : a) !== (b >= 65 && b <= 90 ? b + 32 : b)) return false;
2764
+ }
2819
2765
  return true;
2820
2766
  }
2821
2767
  case "BinaryRegex": return this._pattern.regex.source === other._pattern.regex.source;
@@ -2826,7 +2772,6 @@ var DigestPattern = class DigestPattern {
2826
2772
  */
2827
2773
  hashCode() {
2828
2774
  switch (this._pattern.type) {
2829
- case "Any": return 0;
2830
2775
  case "Digest": {
2831
2776
  const data = this._pattern.digest.data().slice(0, 8);
2832
2777
  let hash = 0;
@@ -2835,7 +2780,10 @@ var DigestPattern = class DigestPattern {
2835
2780
  }
2836
2781
  case "Prefix": {
2837
2782
  let hash = 0;
2838
- for (const byte of this._pattern.prefix) hash = hash * 31 + byte | 0;
2783
+ for (const byte of this._pattern.prefix) {
2784
+ const folded = byte >= 65 && byte <= 90 ? byte + 32 : byte;
2785
+ hash = hash * 31 + folded | 0;
2786
+ }
2839
2787
  return hash;
2840
2788
  }
2841
2789
  case "BinaryRegex": {
@@ -2887,28 +2835,19 @@ var NodePattern = class NodePattern {
2887
2835
  });
2888
2836
  }
2889
2837
  /**
2890
- * Creates a new NodePattern with a subject pattern constraint.
2891
- */
2892
- static withSubject(subjectPattern) {
2893
- return new NodePattern({
2894
- type: "WithSubject",
2895
- subjectPattern
2896
- });
2897
- }
2898
- /**
2899
2838
  * Gets the pattern type.
2900
2839
  */
2901
2840
  get patternType() {
2902
2841
  return this._pattern;
2903
2842
  }
2904
2843
  /**
2905
- * Gets the subject pattern if this is a WithSubject type, undefined otherwise.
2844
+ * Returns the subject pattern, if any. Rust's `NodePattern` does not carry
2845
+ * subject patterns, so this always returns `undefined`.
2906
2846
  */
2907
- subjectPattern() {
2908
- return this._pattern.type === "WithSubject" ? this._pattern.subjectPattern : void 0;
2909
- }
2847
+ subjectPattern() {}
2910
2848
  /**
2911
- * Gets the assertion patterns (empty array if none).
2849
+ * Returns the assertion patterns. Rust's `NodePattern` does not carry
2850
+ * assertion sub-patterns, so this always returns an empty array.
2912
2851
  */
2913
2852
  assertionPatterns() {
2914
2853
  return [];
@@ -2923,9 +2862,6 @@ var NodePattern = class NodePattern {
2923
2862
  case "AssertionsInterval":
2924
2863
  isHit = this._pattern.interval.contains(haystack.assertions().length);
2925
2864
  break;
2926
- case "WithSubject":
2927
- isHit = true;
2928
- break;
2929
2865
  }
2930
2866
  return [isHit ? [[haystack]] : [], /* @__PURE__ */ new Map()];
2931
2867
  }
@@ -2946,7 +2882,6 @@ var NodePattern = class NodePattern {
2946
2882
  switch (this._pattern.type) {
2947
2883
  case "Any": return "node";
2948
2884
  case "AssertionsInterval": return `node(${this._pattern.interval.toString()})`;
2949
- case "WithSubject": return `node(${this._pattern.subjectPattern.toString()})`;
2950
2885
  }
2951
2886
  }
2952
2887
  /**
@@ -2957,7 +2892,6 @@ var NodePattern = class NodePattern {
2957
2892
  switch (this._pattern.type) {
2958
2893
  case "Any": return true;
2959
2894
  case "AssertionsInterval": return this._pattern.interval.equals(other._pattern.interval);
2960
- case "WithSubject": return this._pattern.subjectPattern === other._pattern.subjectPattern;
2961
2895
  }
2962
2896
  }
2963
2897
  /**
@@ -2967,7 +2901,6 @@ var NodePattern = class NodePattern {
2967
2901
  switch (this._pattern.type) {
2968
2902
  case "Any": return 0;
2969
2903
  case "AssertionsInterval": return this._pattern.interval.min() * 31 + (this._pattern.interval.max() ?? 0);
2970
- case "WithSubject": return 1;
2971
2904
  }
2972
2905
  }
2973
2906
  };
@@ -3077,12 +3010,16 @@ var ObscuredPattern = class ObscuredPattern {
3077
3010
  //#endregion
3078
3011
  //#region src/pattern/structure/wrapped-pattern.ts
3079
3012
  let createStructureWrappedPattern;
3013
+ let createAnyPattern;
3080
3014
  let dispatchPatternPathsWithCaptures;
3081
3015
  let dispatchPatternCompile;
3082
3016
  let dispatchPatternToString$1;
3083
3017
  function registerWrappedPatternFactory(factory) {
3084
3018
  createStructureWrappedPattern = factory;
3085
3019
  }
3020
+ function registerWrappedPatternAny(factory) {
3021
+ createAnyPattern = factory;
3022
+ }
3086
3023
  function registerWrappedPatternDispatch(dispatch) {
3087
3024
  dispatchPatternPathsWithCaptures = dispatch.pathsWithCaptures;
3088
3025
  dispatchPatternCompile = dispatch.compile;
@@ -3116,10 +3053,15 @@ var WrappedPattern = class WrappedPattern {
3116
3053
  }
3117
3054
  /**
3118
3055
  * Creates a new WrappedPattern that matches any wrapped envelope and descends into it.
3119
- * Note: This requires Pattern.any() to be available, so it's set up during registration.
3056
+ *
3057
+ * Mirrors Rust `WrappedPattern::unwrap()` which delegates to
3058
+ * `Self::unwrap_matching(Pattern::any())`. The `any` factory is wired in
3059
+ * during module-load registration to break the circular import on the
3060
+ * top-level `Pattern` type.
3120
3061
  */
3121
3062
  static unwrap() {
3122
- return new WrappedPattern({ type: "Any" });
3063
+ if (createAnyPattern === void 0) throw new Error("WrappedPattern.unwrap() requires Pattern.any factory; not registered");
3064
+ return WrappedPattern.unwrapMatching(createAnyPattern());
3123
3065
  }
3124
3066
  /**
3125
3067
  * Gets the pattern type.
@@ -3195,9 +3137,9 @@ var WrappedPattern = class WrappedPattern {
3195
3137
  switch (this._pattern.type) {
3196
3138
  case "Any": return "wrapped";
3197
3139
  case "Unwrap": {
3198
- const patternStr = dispatchPatternToString$1 !== void 0 ? dispatchPatternToString$1(this._pattern.pattern) : "*";
3199
- if (patternStr === "*") return "unwrap";
3200
- return `unwrap(${patternStr})`;
3140
+ const inner = this._pattern.pattern;
3141
+ if (inner.type === "Meta" && inner.pattern.type === "Any") return "unwrap";
3142
+ return `unwrap(${dispatchPatternToString$1 !== void 0 ? dispatchPatternToString$1(inner) : "?"})`;
3201
3143
  }
3202
3144
  }
3203
3145
  }
@@ -3421,10 +3363,7 @@ function axisChildren(axis, env) {
3421
3363
  case "Wrapped":
3422
3364
  if (envCase.type === "node") {
3423
3365
  const subject = envCase.subject;
3424
- if (subject.isWrapped()) {
3425
- const unwrapped = subject.unwrap();
3426
- if (unwrapped !== void 0) return [[unwrapped, "Content"]];
3427
- }
3366
+ if (subject.isWrapped()) return [[subject.tryUnwrap(), "Content"]];
3428
3367
  } else if (envCase.type === "wrapped") return [[envCase.envelope, "Content"]];
3429
3368
  return [];
3430
3369
  }
@@ -4422,30 +4361,20 @@ var SearchPattern = class SearchPattern {
4422
4361
  return [uniquePaths, /* @__PURE__ */ new Map()];
4423
4362
  }
4424
4363
  /**
4425
- * Walk the envelope tree recursively.
4364
+ * Walk the envelope tree using the canonical `Envelope.walk` traversal.
4365
+ *
4366
+ * Mirrors Rust `bc_envelope::Envelope::walk(false, vec![], visitor)`
4367
+ * which is what `SearchPattern::paths_with_captures` uses. The earlier
4368
+ * port hand-rolled a recursion that double-recursed assertions and
4369
+ * stepped through wrapped subjects manually, producing a different
4370
+ * path order (and extra duplicates that the digest-set deduplication
4371
+ * would partially mask).
4426
4372
  */
4427
4373
  _walkEnvelope(envelope, pathToCurrent, visitor) {
4428
- visitor(envelope, pathToCurrent);
4429
- const subject = envelope.subject();
4430
- const newPath = [...pathToCurrent, envelope];
4431
- if (!subject.digest().equals(envelope.digest())) this._walkEnvelope(subject, newPath, visitor);
4432
- for (const assertion of envelope.assertions()) {
4433
- this._walkEnvelope(assertion, newPath, visitor);
4434
- const predicate = assertion.asPredicate?.();
4435
- if (predicate !== void 0) {
4436
- const assertionPath = [...newPath, assertion];
4437
- this._walkEnvelope(predicate, assertionPath, visitor);
4438
- }
4439
- const object = assertion.asObject?.();
4440
- if (object !== void 0) {
4441
- const assertionPath = [...newPath, assertion];
4442
- this._walkEnvelope(object, assertionPath, visitor);
4443
- }
4444
- }
4445
- if (subject.isWrapped()) {
4446
- const unwrapped = subject.tryUnwrap?.();
4447
- if (unwrapped !== void 0) this._walkEnvelope(unwrapped, newPath, visitor);
4448
- }
4374
+ envelope.walk(false, pathToCurrent, (current, _level, _edge, state) => {
4375
+ visitor(current, state);
4376
+ return [[...state, current], false];
4377
+ });
4449
4378
  }
4450
4379
  paths(haystack) {
4451
4380
  return this.pathsWithCaptures(haystack)[0];
@@ -4574,7 +4503,7 @@ var TraversePattern = class TraversePattern {
4574
4503
  return _patternIsComplex(this._first) || this._rest !== void 0;
4575
4504
  }
4576
4505
  toString() {
4577
- return this.patterns().map((p) => p.toString()).join(" -> ");
4506
+ return this.patterns().map((p) => dispatchPatternToString(p)).join(" -> ");
4578
4507
  }
4579
4508
  /**
4580
4509
  * Equality comparison.
@@ -4923,17 +4852,44 @@ function convertValuePatternToEnvelopePattern(valuePattern) {
4923
4852
  */
4924
4853
  function convertStructurePatternToEnvelopePattern(structurePattern) {
4925
4854
  switch (structurePattern.type) {
4926
- case "Array": return ok({
4927
- type: "Leaf",
4928
- pattern: leafArray(ArrayPattern.fromDcborPattern({
4929
- kind: "Structure",
4930
- pattern: structurePattern
4931
- }))
4932
- });
4933
- case "Map": return ok({
4934
- type: "Leaf",
4935
- pattern: leafMap(MapPattern.any())
4936
- });
4855
+ case "Array": {
4856
+ const inner = structurePattern.pattern;
4857
+ let arrayPattern;
4858
+ switch (inner.variant) {
4859
+ case "Any":
4860
+ arrayPattern = ArrayPattern.any();
4861
+ break;
4862
+ case "Length":
4863
+ arrayPattern = ArrayPattern.fromInterval(inner.length);
4864
+ break;
4865
+ case "Elements":
4866
+ arrayPattern = ArrayPattern.fromDcborArrayPattern(inner);
4867
+ break;
4868
+ }
4869
+ return ok({
4870
+ type: "Leaf",
4871
+ pattern: leafArray(arrayPattern)
4872
+ });
4873
+ }
4874
+ case "Map": {
4875
+ const inner = structurePattern.pattern;
4876
+ let mapPattern;
4877
+ switch (inner.variant) {
4878
+ case "Any":
4879
+ mapPattern = MapPattern.any();
4880
+ break;
4881
+ case "Length":
4882
+ mapPattern = MapPattern.fromInterval(inner.length);
4883
+ break;
4884
+ case "Constraints":
4885
+ mapPattern = MapPattern.any();
4886
+ break;
4887
+ }
4888
+ return ok({
4889
+ type: "Leaf",
4890
+ pattern: leafMap(mapPattern)
4891
+ });
4892
+ }
4937
4893
  case "Tagged": return ok({
4938
4894
  type: "Leaf",
4939
4895
  pattern: leafTag(TaggedPattern.fromDcborPattern(structurePattern.pattern))
@@ -4991,6 +4947,169 @@ function convertMetaPatternToEnvelopePattern(metaPattern, originalPattern) {
4991
4947
  }
4992
4948
  }
4993
4949
  //#endregion
4950
+ //#region src/parse/utils.ts
4951
+ let createCborPattern;
4952
+ let createCborPatternFromDcbor;
4953
+ let createAnyArray;
4954
+ let createArrayWithCount;
4955
+ let createArrayWithRange;
4956
+ let createArrayFromDcborPattern;
4957
+ /**
4958
+ * Register pattern factory functions.
4959
+ * This is called by the pattern module to avoid circular dependencies.
4960
+ */
4961
+ function registerPatternFactories(factories) {
4962
+ createCborPattern = factories.cborPattern;
4963
+ createCborPatternFromDcbor = factories.cborPatternFromDcbor;
4964
+ createAnyArray = factories.anyArray;
4965
+ createArrayWithCount = factories.arrayWithCount;
4966
+ createArrayWithRange = factories.arrayWithRange;
4967
+ createArrayFromDcborPattern = factories.arrayFromDcborPattern;
4968
+ }
4969
+ /**
4970
+ * Skips whitespace in the source string.
4971
+ *
4972
+ * @param src - The source string
4973
+ * @param pos - The current position (modified in place)
4974
+ */
4975
+ function skipWs$1(src, pos) {
4976
+ while (pos.value < src.length) {
4977
+ const ch = src[pos.value];
4978
+ if (ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f") pos.value++;
4979
+ else break;
4980
+ }
4981
+ }
4982
+ /**
4983
+ * Parses a CBOR value or dcbor-pattern expression.
4984
+ *
4985
+ * @param src - The source string
4986
+ * @returns The parsed pattern and consumed character count, or an error
4987
+ */
4988
+ function parseCborInner(src) {
4989
+ if (createCborPattern === void 0 || createCborPatternFromDcbor === void 0) return err(unknown());
4990
+ const pos = { value: 0 };
4991
+ skipWs$1(src, pos);
4992
+ if (src[pos.value] === "/") {
4993
+ pos.value++;
4994
+ const start = pos.value;
4995
+ let escape = false;
4996
+ while (pos.value < src.length) {
4997
+ const b = src[pos.value];
4998
+ pos.value++;
4999
+ if (escape) {
5000
+ escape = false;
5001
+ continue;
5002
+ }
5003
+ if (b === "\\") {
5004
+ escape = true;
5005
+ continue;
5006
+ }
5007
+ if (b === "/") {
5008
+ const parseResult = parse$1(src.slice(start, pos.value - 1));
5009
+ if (!parseResult.ok) return err(invalidPattern({
5010
+ start,
5011
+ end: pos.value - 1
5012
+ }));
5013
+ skipWs$1(src, pos);
5014
+ return ok([createCborPatternFromDcbor(parseResult.value), pos.value]);
5015
+ }
5016
+ }
5017
+ return err(unterminatedRegex({
5018
+ start: start - 1,
5019
+ end: pos.value
5020
+ }));
5021
+ }
5022
+ if (src.slice(pos.value, pos.value + 3) === "ur:") {
5023
+ const parseResult = parseDcborItemPartial(src.slice(pos.value));
5024
+ if (!parseResult.ok) return err(unknown());
5025
+ const [cborValue, consumed] = parseResult.value;
5026
+ return ok([createCborPattern(cborValue), pos.value + consumed]);
5027
+ }
5028
+ const parseResult = parseDcborItemPartial(src.slice(pos.value));
5029
+ if (!parseResult.ok) return err(unknown());
5030
+ const [cborValue, consumed] = parseResult.value;
5031
+ return ok([createCborPattern(cborValue), pos.value + consumed]);
5032
+ }
5033
+ /**
5034
+ * Parses an array pattern inner content.
5035
+ *
5036
+ * @param src - The source string (content between [ and ])
5037
+ * @returns The parsed pattern and consumed character count, or an error
5038
+ */
5039
+ function parseArrayInner(src) {
5040
+ if (createAnyArray === void 0 || createArrayWithCount === void 0 || createArrayWithRange === void 0 || createArrayFromDcborPattern === void 0) return err(unknown());
5041
+ const pos = { value: 0 };
5042
+ skipWs$1(src, pos);
5043
+ if (src[pos.value] === "*") {
5044
+ pos.value++;
5045
+ skipWs$1(src, pos);
5046
+ return ok([createAnyArray(), pos.value]);
5047
+ }
5048
+ if (src[pos.value] === "{") {
5049
+ pos.value++;
5050
+ skipWs$1(src, pos);
5051
+ const startPos = pos.value;
5052
+ while (pos.value < src.length && src[pos.value] !== void 0 && /\d/.test(src[pos.value])) pos.value++;
5053
+ if (startPos === pos.value) return err(invalidRange({
5054
+ start: pos.value,
5055
+ end: pos.value
5056
+ }));
5057
+ const firstNum = parseInt(src.slice(startPos, pos.value), 10);
5058
+ if (Number.isNaN(firstNum)) return err(invalidNumberFormat({
5059
+ start: startPos,
5060
+ end: pos.value
5061
+ }));
5062
+ skipWs$1(src, pos);
5063
+ if (pos.value >= src.length) return err(unexpectedEndOfInput());
5064
+ const ch = src[pos.value];
5065
+ if (ch === "}") {
5066
+ pos.value++;
5067
+ skipWs$1(src, pos);
5068
+ return ok([createArrayWithCount(firstNum), pos.value]);
5069
+ }
5070
+ if (ch === ",") {
5071
+ pos.value++;
5072
+ skipWs$1(src, pos);
5073
+ if (pos.value >= src.length) return err(unexpectedEndOfInput());
5074
+ const nextCh = src[pos.value];
5075
+ if (nextCh === "}") {
5076
+ pos.value++;
5077
+ skipWs$1(src, pos);
5078
+ return ok([createArrayWithRange(firstNum, void 0), pos.value]);
5079
+ }
5080
+ if (nextCh !== void 0 && /\d/.test(nextCh)) {
5081
+ const secondStart = pos.value;
5082
+ while (pos.value < src.length && src[pos.value] !== void 0 && /\d/.test(src[pos.value])) pos.value++;
5083
+ const secondNum = parseInt(src.slice(secondStart, pos.value), 10);
5084
+ if (Number.isNaN(secondNum)) return err(invalidNumberFormat({
5085
+ start: secondStart,
5086
+ end: pos.value
5087
+ }));
5088
+ skipWs$1(src, pos);
5089
+ if (pos.value >= src.length || src[pos.value] !== "}") return err(unexpectedEndOfInput());
5090
+ pos.value++;
5091
+ skipWs$1(src, pos);
5092
+ return ok([createArrayWithRange(firstNum, secondNum), pos.value]);
5093
+ }
5094
+ return err(invalidRange({
5095
+ start: pos.value,
5096
+ end: pos.value
5097
+ }));
5098
+ }
5099
+ return err(invalidRange({
5100
+ start: pos.value,
5101
+ end: pos.value
5102
+ }));
5103
+ }
5104
+ const parseResult = parse$1(`[${src.slice(pos.value)}]`);
5105
+ if (!parseResult.ok) return err(invalidPattern({
5106
+ start: pos.value,
5107
+ end: src.length
5108
+ }));
5109
+ const consumed = src.length - pos.value;
5110
+ return ok([createArrayFromDcborPattern(parseResult.value), consumed]);
5111
+ }
5112
+ //#endregion
4994
5113
  //#region src/pattern/index.ts
4995
5114
  /**
4996
5115
  * Creates a Leaf pattern.
@@ -5492,7 +5611,6 @@ function registerAllFactories() {
5492
5611
  registerTaggedPatternFactory((p) => patternLeaf(leafTag(p)));
5493
5612
  registerCBORPatternFactory((p) => patternLeaf(leafCbor(p)));
5494
5613
  registerLeafStructurePatternFactory((p) => patternStructure(structureLeaf(p)));
5495
- registerSubjectPatternFactory((p) => patternStructure(structureSubject(p)));
5496
5614
  registerPredicatePatternFactory((p) => patternStructure(structurePredicate(p)));
5497
5615
  registerObjectPatternFactory((p) => patternStructure(structureObject(p)));
5498
5616
  registerAssertionsPatternFactory((p) => patternStructure(structureAssertions(p)));
@@ -5505,17 +5623,24 @@ function registerAllFactories() {
5505
5623
  compile: patternCompile,
5506
5624
  toString: patternToString
5507
5625
  });
5626
+ registerWrappedPatternAny(any);
5627
+ registerAssertionsPatternToStringDispatch(patternToString);
5628
+ registerSubjectPatternDispatch({
5629
+ compile: patternCompile,
5630
+ toString: patternToString
5631
+ });
5508
5632
  registerAnyPatternFactory((p) => patternMeta(metaAny(p)));
5509
- registerAndPatternFactory((p) => patternMeta(metaAnd(p)));
5510
- registerOrPatternFactory((p) => patternMeta(metaOr(p)));
5511
- registerNotPatternFactory((p) => patternMeta(metaNot(p)));
5512
- registerCapturePatternFactory((p) => patternMeta(metaCapture(p)));
5513
- registerSearchPatternFactory((p) => patternMeta(metaSearch(p)));
5514
- registerTraversePatternFactory((p) => patternMeta(metaTraverse(p)));
5515
- registerGroupPatternFactory((p) => patternMeta(metaGroup(p)));
5516
5633
  }
5517
5634
  registerAllFactories();
5518
5635
  registerVMPatternFunctions(patternPathsWithCaptures, patternMatches, patternPaths);
5636
+ registerPatternFactories({
5637
+ cborPattern: (value) => cborValue(value),
5638
+ cborPatternFromDcbor: (pattern) => cborPattern(pattern),
5639
+ anyArray,
5640
+ arrayWithCount: (count) => patternLeaf(leafArray(ArrayPattern.count(count))),
5641
+ arrayWithRange: (min, max) => patternLeaf(leafArray(ArrayPattern.interval(min, max))),
5642
+ arrayFromDcborPattern: (pattern) => patternLeaf(leafArray(ArrayPattern.fromDcborPattern(pattern)))
5643
+ });
5519
5644
  registerPatternMatchFn(patternMatches);
5520
5645
  registerPatternDispatchFns({
5521
5646
  pathsWithCaptures: patternPathsWithCaptures,
@@ -6269,305 +6394,198 @@ var Lexer = class {
6269
6394
  }
6270
6395
  };
6271
6396
  //#endregion
6272
- //#region src/parse/index.ts
6397
+ //#region src/parse/leaf/array-parser.ts
6273
6398
  /**
6274
6399
  * Copyright © 2023-2026 Blockchain Commons, LLC
6275
6400
  * Copyright © 2025-2026 Parity Technologies
6276
6401
  *
6402
+ * Array parser — port of `bc-envelope-pattern-rust`
6403
+ * `parse/leaf/array_parser.rs`.
6277
6404
  *
6278
- * @bcts/envelope-pattern - Parser entry point
6279
- *
6280
- * This is a 1:1 TypeScript port of bc-envelope-pattern-rust parse/mod.rs
6281
- * Recursive descent parser for Gordian Envelope pattern syntax.
6405
+ * Mirrors Rust's flow exactly: after the `[` token has been consumed,
6406
+ * delegate to `utils::parseArrayInner` (which handles `*`, `{n}`, `{n,m}`,
6407
+ * `{n,}` directly and otherwise wraps the body in `[...]` and re-parses
6408
+ * via dcbor-pattern), then expect a closing `]`.
6282
6409
  *
6283
- * @module envelope-pattern/parse
6284
- */
6285
- /**
6286
- * Parse a pattern expression string into a Pattern.
6410
+ * @module envelope-pattern/parse/leaf/array-parser
6287
6411
  */
6288
- function parse(input) {
6289
- const lexer = new Lexer(input);
6290
- const result = parseOr(lexer);
6291
- if (!result.ok) {
6292
- const dcborResult = parse$1(input);
6293
- if (dcborResult.ok) return convertDcborPatternToEnvelopePattern$1(dcborResult.value);
6294
- return result;
6295
- }
6296
- const next = lexer.next();
6297
- if (next !== void 0) return err(extraData(next.span));
6298
- return result;
6412
+ function parseArray(lexer) {
6413
+ const inner = parseArrayInner(lexer.remainder());
6414
+ if (!inner.ok) return inner;
6415
+ const [pattern, consumed] = inner.value;
6416
+ lexer.bump(consumed);
6417
+ const close = lexer.next();
6418
+ if (close === void 0) return err(expectedCloseBracket(lexer.span()));
6419
+ if (close.token.type !== "BracketClose") return err(unexpectedToken(close.token, close.span));
6420
+ return ok(pattern);
6299
6421
  }
6422
+ //#endregion
6423
+ //#region src/parse/leaf/cbor-parser.ts
6300
6424
  /**
6301
- * Parse a pattern, allowing extra data after the pattern.
6425
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6426
+ * Copyright © 2025-2026 Parity Technologies
6427
+ *
6428
+ * CBOR pattern parser — port of `bc-envelope-pattern-rust`
6429
+ * `parse/leaf/cbor_parser.rs`.
6430
+ *
6431
+ * Mirrors Rust's flow: lookahead for `(`. If absent, return `any_cbor()`.
6432
+ * Otherwise consume the `(`, delegate to `parseCborInner` (handles
6433
+ * `/regex/`, `ur:…`, and CBOR diagnostic notation), and expect a closing
6434
+ * `)`.
6435
+ *
6436
+ * @module envelope-pattern/parse/leaf/cbor-parser
6302
6437
  */
6303
- function parsePartial(input) {
6304
- const lexer = new Lexer(input);
6305
- const result = parseOr(lexer);
6306
- if (!result.ok) return result;
6307
- return ok([result.value, lexer.position]);
6438
+ function parseCbor(lexer) {
6439
+ if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyCbor());
6440
+ lexer.next();
6441
+ const innerResult = parseCborInner(lexer.remainder());
6442
+ if (!innerResult.ok) return innerResult;
6443
+ const [pattern, consumed] = innerResult.value;
6444
+ lexer.bump(consumed);
6445
+ const close = lexer.next();
6446
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
6447
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
6448
+ return ok(pattern);
6308
6449
  }
6450
+ //#endregion
6451
+ //#region src/parse/leaf/date-parser.ts
6309
6452
  /**
6310
- * Convert a dcbor-pattern Pattern to an envelope-pattern Pattern.
6453
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6454
+ * Copyright © 2025-2026 Parity Technologies
6455
+ *
6456
+ * Date content parser — port of `bc-envelope-pattern-rust`
6457
+ * `parse/leaf/date_parser.rs`.
6458
+ *
6459
+ * Mirrors Rust's `Date::from_string`, which accepts a strict ISO-8601
6460
+ * subset, by deferring to dcbor's `CborDate.fromString`. Falls back to JS
6461
+ * `Date.parse` only as a defensive shim — that branch is unreachable for
6462
+ * conformant inputs.
6463
+ *
6464
+ * @module envelope-pattern/parse/leaf/date-parser
6311
6465
  */
6312
- function convertDcborPatternToEnvelopePattern$1(_dcborPattern) {
6313
- return ok(any());
6314
- }
6315
6466
  /**
6316
- * Parse an Or expression: expr (| expr)*
6467
+ * Parse a date pattern of one of the forms accepted by Rust:
6468
+ *
6469
+ * - `/regex/` (regex match against ISO-8601 string)
6470
+ * - `start...end` (inclusive range)
6471
+ * - `start...` (earliest)
6472
+ * - `...end` (latest)
6473
+ * - `iso-8601` (exact)
6474
+ *
6475
+ * Mirrors `parse_date_content` in Rust; uses `CborDate.fromString` so the
6476
+ * accepted formats match Rust's `bc_envelope::prelude::Date::from_string`
6477
+ * exactly rather than the looser JS `Date.parse`.
6317
6478
  */
6318
- function parseOr(lexer) {
6319
- const patterns = [];
6320
- const first = parseTraverse(lexer);
6321
- if (!first.ok) return first;
6322
- patterns.push(first.value);
6323
- while (true) {
6324
- if (lexer.peekToken()?.token.type !== "Or") break;
6325
- lexer.next();
6326
- const nextExpr = parseTraverse(lexer);
6327
- if (!nextExpr.ok) return nextExpr;
6328
- patterns.push(nextExpr.value);
6479
+ function parseDateContent(content, span) {
6480
+ if (content.startsWith("/") && content.endsWith("/") && content.length >= 2) {
6481
+ const regexStr = content.slice(1, -1);
6482
+ try {
6483
+ return ok(dateRegex(new RegExp(regexStr)));
6484
+ } catch {
6485
+ return err(invalidRegex(span));
6486
+ }
6329
6487
  }
6330
- if (patterns.length === 1) return ok(patterns[0]);
6331
- return ok(or(patterns));
6488
+ const ellipsisIdx = content.indexOf("...");
6489
+ if (ellipsisIdx !== -1) {
6490
+ const left = content.slice(0, ellipsisIdx);
6491
+ const right = content.slice(ellipsisIdx + 3);
6492
+ if (left.length === 0 && right.length > 0) {
6493
+ const parsed = parseIsoDateStrict(right);
6494
+ if (parsed === void 0) return err(invalidDateFormat(span));
6495
+ return ok(dateLatest(parsed));
6496
+ }
6497
+ if (left.length > 0 && right.length === 0) {
6498
+ const parsed = parseIsoDateStrict(left);
6499
+ if (parsed === void 0) return err(invalidDateFormat(span));
6500
+ return ok(dateEarliest(parsed));
6501
+ }
6502
+ if (left.length > 0 && right.length > 0) {
6503
+ const start = parseIsoDateStrict(left);
6504
+ const end = parseIsoDateStrict(right);
6505
+ if (start === void 0 || end === void 0) return err(invalidDateFormat(span));
6506
+ return ok(dateRange(start, end));
6507
+ }
6508
+ return err(invalidDateFormat(span));
6509
+ }
6510
+ const parsed = parseIsoDateStrict(content);
6511
+ if (parsed === void 0) return err(invalidDateFormat(span));
6512
+ return ok(date(parsed));
6332
6513
  }
6514
+ function parseIsoDateStrict(value) {
6515
+ try {
6516
+ return CborDate.fromString(value);
6517
+ } catch {
6518
+ return;
6519
+ }
6520
+ }
6521
+ //#endregion
6522
+ //#region src/parse/leaf/known-value-parser.ts
6333
6523
  /**
6334
- * Parse a Traverse expression: expr (-> expr)*
6335
- */
6336
- function parseTraverse(lexer) {
6337
- const patterns = [];
6338
- const first = parseAnd(lexer);
6339
- if (!first.ok) return first;
6340
- patterns.push(first.value);
6341
- while (true) {
6342
- if (lexer.peekToken()?.token.type !== "Traverse") break;
6343
- lexer.next();
6344
- const nextExpr = parseAnd(lexer);
6345
- if (!nextExpr.ok) return nextExpr;
6346
- patterns.push(nextExpr.value);
6347
- }
6348
- if (patterns.length === 1) return ok(patterns[0]);
6349
- return ok(traverse(patterns));
6350
- }
6351
- /**
6352
- * Parse an And expression: expr (& expr)*
6524
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6525
+ * Copyright © 2025-2026 Parity Technologies
6526
+ *
6527
+ * Helpers for parsing the body of a `'…'` (single-quoted) known-value
6528
+ * literal. Mirrors the inline body of Rust's `Token::SingleQuotedPattern`
6529
+ * branch in `parse_primary`:
6530
+ *
6531
+ * - If the contents are a valid `u64`, build `Pattern::known_value(...)`.
6532
+ * - Otherwise, build `Pattern::known_value_named(...)`.
6533
+ *
6534
+ * The earlier port duck-typed a fake `KnownValue`; this version uses the
6535
+ * real `KnownValue` constructor so all subsequent KnownValue methods work
6536
+ * (e.g., `taggedCbor()`, `name()`, etc.).
6537
+ *
6538
+ * @module envelope-pattern/parse/leaf/known-value-parser
6353
6539
  */
6354
- function parseAnd(lexer) {
6355
- const patterns = [];
6356
- const first = parseNot(lexer);
6357
- if (!first.ok) return first;
6358
- patterns.push(first.value);
6359
- while (true) {
6360
- if (lexer.peekToken()?.token.type !== "And") break;
6361
- lexer.next();
6362
- const nextExpr = parseNot(lexer);
6363
- if (!nextExpr.ok) return nextExpr;
6364
- patterns.push(nextExpr.value);
6365
- }
6366
- if (patterns.length === 1) return ok(patterns[0]);
6367
- return ok(and(patterns));
6368
- }
6369
6540
  /**
6370
- * Parse a Not expression: !? group
6541
+ * Maximum value of a Rust `u64`. Used to reject literals that would
6542
+ * silently wrap or lose precision when constructing a `KnownValue`.
6371
6543
  */
6372
- function parseNot(lexer) {
6373
- if (lexer.peekToken()?.token.type === "Not") {
6374
- lexer.next();
6375
- const inner = parseGroup(lexer);
6376
- if (!inner.ok) return inner;
6377
- return ok(notMatching(inner.value));
6378
- }
6379
- return parseGroup(lexer);
6380
- }
6544
+ const U64_MAX = 18446744073709551615n;
6381
6545
  /**
6382
- * Parse a Group expression: primary quantifier?
6546
+ * Parse the inner contents of a `'…'` known-value pattern token.
6547
+ *
6548
+ * Mirrors the Rust dispatch
6549
+ * ```ignore
6550
+ * if let Ok(value) = content.parse::<u64>() {
6551
+ * Pattern::known_value(KnownValue::new(value))
6552
+ * } else {
6553
+ * Pattern::known_value_named(content)
6554
+ * }
6555
+ * ```
6556
+ * but uses BigInt parsing to preserve full `u64` range — the previous
6557
+ * `parseInt(...)` path silently truncated above `2^53-1`.
6383
6558
  */
6384
- function parseGroup(lexer) {
6385
- const primary = parsePrimary(lexer);
6386
- if (!primary.ok) return primary;
6387
- const next = lexer.peekToken();
6388
- if (next === void 0) return primary;
6389
- const tokenType = next.token.type;
6390
- let quantifier;
6391
- if (tokenType === "RepeatZeroOrMore") {
6392
- lexer.next();
6393
- quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Greedy);
6394
- } else if (tokenType === "RepeatZeroOrMoreLazy") {
6395
- lexer.next();
6396
- quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Lazy);
6397
- } else if (tokenType === "RepeatZeroOrMorePossessive") {
6398
- lexer.next();
6399
- quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Possessive);
6400
- } else if (tokenType === "RepeatOneOrMore") {
6401
- lexer.next();
6402
- quantifier = Quantifier$1.oneOrMore(Reluctance$1.Greedy);
6403
- } else if (tokenType === "RepeatOneOrMoreLazy") {
6404
- lexer.next();
6405
- quantifier = Quantifier$1.oneOrMore(Reluctance$1.Lazy);
6406
- } else if (tokenType === "RepeatOneOrMorePossessive") {
6407
- lexer.next();
6408
- quantifier = Quantifier$1.oneOrMore(Reluctance$1.Possessive);
6409
- } else if (tokenType === "RepeatZeroOrOne") {
6410
- lexer.next();
6411
- quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Greedy);
6412
- } else if (tokenType === "RepeatZeroOrOneLazy") {
6413
- lexer.next();
6414
- quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Lazy);
6415
- } else if (tokenType === "RepeatZeroOrOnePossessive") {
6416
- lexer.next();
6417
- quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Possessive);
6418
- } else if (tokenType === "Range") {
6419
- lexer.next();
6420
- if (!next.token.value.ok) return err(next.token.value.error);
6421
- quantifier = next.token.value.value;
6422
- } else return primary;
6423
- return ok(repeat(primary.value, quantifier.min(), quantifier.max(), quantifier.reluctance()));
6559
+ function parseKnownValueContent(content) {
6560
+ if (isU64Literal(content)) return ok(knownValue(new KnownValue(BigInt(content))));
6561
+ return ok(patternLeaf(leafKnownValue(KnownValuePattern.named(content))));
6424
6562
  }
6425
- /**
6426
- * Parse a primary expression (atoms and structure keywords).
6427
- */
6428
- function parsePrimary(lexer) {
6429
- const tokenResult = lexer.next();
6430
- if (tokenResult === void 0) return err(unexpectedEndOfInput());
6431
- const { token, span } = tokenResult;
6432
- switch (token.type) {
6433
- case "Search": return parseSearch(lexer);
6434
- case "Node": return parseNode(lexer);
6435
- case "Assertion": return parseAssertion(lexer);
6436
- case "AssertionPred": return parseAssertionPred(lexer);
6437
- case "AssertionObj": return parseAssertionObj(lexer);
6438
- case "Digest": return parseDigest(lexer);
6439
- case "Obj": return parseObject(lexer);
6440
- case "Obscured": return ok(obscured());
6441
- case "Elided": return ok(elided());
6442
- case "Encrypted": return ok(encrypted());
6443
- case "Compressed": return ok(compressed());
6444
- case "Pred": return parsePredicate(lexer);
6445
- case "Subject": return parseSubject(lexer);
6446
- case "Wrapped": return ok(wrapped());
6447
- case "Unwrap": return parseUnwrap(lexer);
6448
- case "Leaf": return ok(leaf());
6449
- case "GroupName": return parseCapture(lexer, token.name);
6450
- case "ParenOpen": return parseParenGroup(lexer);
6451
- case "Cbor": return parseCbor(lexer);
6452
- case "RepeatZeroOrMore": return ok(any());
6453
- case "BoolKeyword": return ok(anyBool());
6454
- case "BoolTrue": return ok(bool(true));
6455
- case "BoolFalse": return ok(bool(false));
6456
- case "NumberKeyword": return ok(anyNumber());
6457
- case "TextKeyword": return ok(anyText());
6458
- case "StringLiteral":
6459
- if (!token.value.ok) return err(token.value.error);
6460
- return ok(text(token.value.value));
6461
- case "UnsignedInteger":
6462
- if (!token.value.ok) return err(token.value.error);
6463
- return parseNumberRangeOrComparison(lexer, token.value.value);
6464
- case "Integer":
6465
- if (!token.value.ok) return err(token.value.error);
6466
- return parseNumberRangeOrComparison(lexer, token.value.value);
6467
- case "Float":
6468
- if (!token.value.ok) return err(token.value.error);
6469
- return parseNumberRangeOrComparison(lexer, token.value.value);
6470
- case "GreaterThanOrEqual": return parseComparisonNumber(lexer, ">=");
6471
- case "LessThanOrEqual": return parseComparisonNumber(lexer, "<=");
6472
- case "GreaterThan": return parseComparisonNumber(lexer, ">");
6473
- case "LessThan": return parseComparisonNumber(lexer, "<");
6474
- case "NaN": return ok(patternLeaf(leafNumber(NumberPattern.nan())));
6475
- case "Infinity": return ok(number(Infinity));
6476
- case "NegativeInfinity": return ok(number(-Infinity));
6477
- case "Regex":
6478
- if (!token.value.ok) return err(token.value.error);
6479
- try {
6480
- return ok(textRegex(new RegExp(token.value.value)));
6481
- } catch {
6482
- return err(invalidRegex(span));
6483
- }
6484
- case "BracketOpen": return parseArray(lexer);
6485
- case "ByteString": return ok(anyByteString());
6486
- case "HexPattern":
6487
- if (!token.value.ok) return err(token.value.error);
6488
- return ok(byteString(token.value.value));
6489
- case "HexBinaryRegex":
6490
- if (!token.value.ok) return err(token.value.error);
6491
- try {
6492
- return ok(patternLeaf(leafByteString(ByteStringPattern.regex(new RegExp(token.value.value)))));
6493
- } catch {
6494
- return err(invalidRegex(span));
6495
- }
6496
- case "DateKeyword": return ok(anyDate());
6497
- case "DatePattern":
6498
- if (!token.value.ok) return err(token.value.error);
6499
- return parseDateContent(token.value.value, span);
6500
- case "Tagged": return parseTag(lexer);
6501
- case "Known": return ok(anyKnownValue());
6502
- case "SingleQuotedPattern":
6503
- if (!token.value.ok) return err(token.value.error);
6504
- return parseKnownValueContent(token.value.value);
6505
- case "SingleQuotedRegex":
6506
- if (!token.value.ok) return err(token.value.error);
6507
- try {
6508
- return ok(patternLeaf(leafKnownValue(KnownValuePattern.regex(new RegExp(token.value.value)))));
6509
- } catch {
6510
- return err(invalidRegex(span));
6511
- }
6512
- case "Null": return ok(nullPattern());
6513
- case "And":
6514
- case "Or":
6515
- case "Not":
6516
- case "Traverse":
6517
- case "RepeatZeroOrMoreLazy":
6518
- case "RepeatZeroOrMorePossessive":
6519
- case "RepeatOneOrMore":
6520
- case "RepeatOneOrMoreLazy":
6521
- case "RepeatOneOrMorePossessive":
6522
- case "RepeatZeroOrOne":
6523
- case "RepeatZeroOrOneLazy":
6524
- case "RepeatZeroOrOnePossessive":
6525
- case "ParenClose":
6526
- case "BracketClose":
6527
- case "Comma":
6528
- case "Ellipsis":
6529
- case "Range":
6530
- case "Identifier": return err(unexpectedToken(token, span));
6563
+ function isU64Literal(content) {
6564
+ if (content.length === 0) return false;
6565
+ for (let i = 0; i < content.length; i++) {
6566
+ const c = content.charCodeAt(i);
6567
+ if (c < 48 || c > 57) return false;
6568
+ }
6569
+ try {
6570
+ const value = BigInt(content);
6571
+ return value >= 0n && value <= U64_MAX;
6572
+ } catch {
6573
+ return false;
6531
6574
  }
6532
6575
  }
6576
+ //#endregion
6577
+ //#region src/parse/leaf/number-parser.ts
6533
6578
  /**
6534
- * Parse a parenthesized group expression.
6535
- */
6536
- function parseParenGroup(lexer) {
6537
- const inner = parseOr(lexer);
6538
- if (!inner.ok) return inner;
6539
- if (lexer.next()?.token.type !== "ParenClose") return err({
6540
- type: "ExpectedCloseParen",
6541
- span: lexer.span()
6542
- });
6543
- return ok(group(inner.value));
6544
- }
6545
- /**
6546
- * Parse a capture group: @name pattern
6547
- */
6548
- function parseCapture(lexer, name) {
6549
- const inner = parseGroup(lexer);
6550
- if (!inner.ok) return inner;
6551
- return ok(capture(name, inner.value));
6552
- }
6553
- /**
6554
- * Parse a search pattern: search(pattern)
6579
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6580
+ * Copyright © 2025-2026 Parity Technologies
6581
+ *
6582
+ * Number parsers — port of `bc-envelope-pattern-rust` `parse/leaf/number_parser.rs`.
6583
+ *
6584
+ * @module envelope-pattern/parse/leaf/number-parser
6555
6585
  */
6556
- function parseSearch(lexer) {
6557
- if (lexer.next()?.token.type !== "ParenOpen") return err({
6558
- type: "ExpectedOpenParen",
6559
- span: lexer.span()
6560
- });
6561
- const inner = parseOr(lexer);
6562
- if (!inner.ok) return inner;
6563
- if (lexer.next()?.token.type !== "ParenClose") return err({
6564
- type: "ExpectedCloseParen",
6565
- span: lexer.span()
6566
- });
6567
- return ok(search(inner.value));
6568
- }
6569
6586
  /**
6570
- * Parse number with possible range or comparison.
6587
+ * Parses an optional `...end` suffix following an already-consumed number,
6588
+ * mirroring Rust `parse_number_range_or_comparison`.
6571
6589
  */
6572
6590
  function parseNumberRangeOrComparison(lexer, firstValue) {
6573
6591
  const next = lexer.peekToken();
@@ -6577,10 +6595,7 @@ function parseNumberRangeOrComparison(lexer, firstValue) {
6577
6595
  const endToken = lexer.next();
6578
6596
  if (endToken === void 0) return err(unexpectedEndOfInput());
6579
6597
  let endValue;
6580
- if (endToken.token.type === "UnsignedInteger" || endToken.token.type === "Integer") {
6581
- if (!endToken.token.value.ok) return err(endToken.token.value.error);
6582
- endValue = endToken.token.value.value;
6583
- } else if (endToken.token.type === "Float") {
6598
+ if (endToken.token.type === "UnsignedInteger" || endToken.token.type === "Integer" || endToken.token.type === "Float") {
6584
6599
  if (!endToken.token.value.ok) return err(endToken.token.value.error);
6585
6600
  endValue = endToken.token.value.value;
6586
6601
  } else return err(unexpectedToken(endToken.token, endToken.span));
@@ -6589,16 +6604,14 @@ function parseNumberRangeOrComparison(lexer, firstValue) {
6589
6604
  return ok(number(firstValue));
6590
6605
  }
6591
6606
  /**
6592
- * Parse comparison number: >=n, <=n, >n, <n
6607
+ * Parses a number following a comparison operator, mirroring Rust
6608
+ * `parse_comparison_number`.
6593
6609
  */
6594
6610
  function parseComparisonNumber(lexer, op) {
6595
6611
  const numToken = lexer.next();
6596
6612
  if (numToken === void 0) return err(unexpectedEndOfInput());
6597
6613
  let value;
6598
- if (numToken.token.type === "UnsignedInteger" || numToken.token.type === "Integer") {
6599
- if (!numToken.token.value.ok) return err(numToken.token.value.error);
6600
- value = numToken.token.value.value;
6601
- } else if (numToken.token.type === "Float") {
6614
+ if (numToken.token.type === "UnsignedInteger" || numToken.token.type === "Integer" || numToken.token.type === "Float") {
6602
6615
  if (!numToken.token.value.ok) return err(numToken.token.value.error);
6603
6616
  value = numToken.token.value.value;
6604
6617
  } else return err(unexpectedToken(numToken.token, numToken.span));
@@ -6607,306 +6620,818 @@ function parseComparisonNumber(lexer, op) {
6607
6620
  case "<=": return ok(patternLeaf(leafNumber(NumberPattern.lessThanOrEqual(value))));
6608
6621
  case ">": return ok(numberGreaterThan(value));
6609
6622
  case "<": return ok(numberLessThan(value));
6610
- default: return ok(number(value));
6611
6623
  }
6612
6624
  }
6625
+ //#endregion
6626
+ //#region src/parse/leaf/tag-parser.ts
6613
6627
  /**
6614
- * Parse an array pattern.
6628
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6629
+ * Copyright © 2025-2026 Parity Technologies
6630
+ *
6631
+ * Tag parser — port of `bc-envelope-pattern-rust`
6632
+ * `parse/leaf/tag_parser.rs`.
6633
+ *
6634
+ * Mirrors the Rust dispatch exactly: lookahead for `(`; if absent, return
6635
+ * the bare `any_tag()`. Otherwise build a synthetic dcbor-pattern
6636
+ * expression `tagged(<inner>)`, parse it via `@bcts/dcbor-pattern`, and
6637
+ * extract the resulting `TaggedPattern` to wrap as an envelope-pattern
6638
+ * leaf. This keeps the **full** tag selector (number, name, regex)
6639
+ * intact — the previous port discarded the tag value entirely.
6640
+ *
6641
+ * @module envelope-pattern/parse/leaf/tag-parser
6615
6642
  */
6616
- function parseArray(lexer) {
6617
- const first = lexer.peekToken();
6618
- if (first === void 0) return err(unexpectedEndOfInput());
6619
- if (first.token.type === "BracketClose") {
6620
- lexer.next();
6621
- return ok(patternLeaf(leafArray(ArrayPattern.count(0))));
6622
- }
6623
- if (first.token.type === "RepeatZeroOrMore") {
6624
- lexer.next();
6625
- if (lexer.next()?.token.type !== "BracketClose") return err({
6626
- type: "ExpectedCloseBracket",
6627
- span: lexer.span()
6628
- });
6629
- return ok(anyArray());
6630
- }
6631
- const patterns = [];
6632
- while (true) {
6633
- const next = lexer.peekToken();
6634
- if (next === void 0) return err(unexpectedEndOfInput());
6635
- if (next.token.type === "BracketClose") {
6636
- lexer.next();
6637
- break;
6638
- }
6639
- const pattern = parseOr(lexer);
6640
- if (!pattern.ok) return pattern;
6641
- patterns.push(pattern.value);
6642
- const afterPattern = lexer.peekToken();
6643
- if (afterPattern === void 0) return err(unexpectedEndOfInput());
6644
- if (afterPattern.token.type === "Comma") lexer.next();
6645
- else if (afterPattern.token.type !== "BracketClose") return err(unexpectedToken(afterPattern.token, afterPattern.span));
6646
- }
6647
- if (patterns.length === 0) return ok(patternLeaf(leafArray(ArrayPattern.count(0))));
6648
- return ok(patternLeaf(leafArray(ArrayPattern.withPatterns(patterns))));
6649
- }
6650
6643
  /**
6651
- * Parse a tag pattern.
6644
+ * Parse `tagged` and `tagged(...)` patterns.
6652
6645
  */
6653
6646
  function parseTag(lexer) {
6654
- if (lexer.next()?.token.type !== "ParenOpen") return ok(anyTag());
6655
- const tagToken = lexer.next();
6656
- if (tagToken === void 0) return err(unexpectedEndOfInput());
6657
- if (tagToken.token.type !== "UnsignedInteger") return err(unexpectedToken(tagToken.token, tagToken.span));
6658
- if (!tagToken.token.value.ok) return err(tagToken.token.value.error);
6659
- if (lexer.next()?.token.type !== "ParenClose") return err({
6660
- type: "ExpectedCloseParen",
6661
- span: lexer.span()
6662
- });
6663
- return ok(anyTag());
6664
- }
6665
- /**
6666
- * Parse date content from date'...' pattern.
6667
- */
6668
- function parseDateContent(content, span) {
6669
- if (content.startsWith("/") && content.endsWith("/")) {
6670
- const regexStr = content.slice(1, -1);
6671
- try {
6672
- return ok(dateRegex(new RegExp(regexStr)));
6673
- } catch {
6674
- return err(invalidRegex(span));
6647
+ if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyTag());
6648
+ lexer.next();
6649
+ const remainder = lexer.remainder();
6650
+ const closeIdx = findMatchingCloseParen(remainder);
6651
+ if (closeIdx === void 0) return err(expectedCloseParen(lexer.span()));
6652
+ const innerContent = remainder.slice(0, closeIdx);
6653
+ const dcborResult = parse$1(`tagged(${innerContent})`);
6654
+ if (dcborResult.ok) {
6655
+ const dcborPattern = dcborResult.value;
6656
+ if (dcborPattern.kind === "Structure" && dcborPattern.pattern.type === "Tagged") {
6657
+ lexer.bump(closeIdx);
6658
+ const close = lexer.next();
6659
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
6660
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
6661
+ return ok(patternLeaf(leafTag(TaggedPattern.fromDcborPattern(dcborPattern.pattern.pattern))));
6675
6662
  }
6676
6663
  }
6677
- const rangeIdx = content.indexOf("...");
6678
- if (rangeIdx !== -1) {
6679
- const left = content.slice(0, rangeIdx).trim();
6680
- const right = content.slice(rangeIdx + 3).trim();
6681
- if (left.length === 0 && right.length > 0) {
6682
- const parsed = Date.parse(right);
6683
- if (isNaN(parsed)) return err({
6684
- type: "InvalidDateFormat",
6685
- span
6686
- });
6687
- return ok(dateLatest(CborDate.fromDatetime(new Date(parsed))));
6688
- }
6689
- if (left.length > 0 && right.length === 0) {
6690
- const parsed = Date.parse(left);
6691
- if (isNaN(parsed)) return err({
6692
- type: "InvalidDateFormat",
6693
- span
6694
- });
6695
- return ok(dateEarliest(CborDate.fromDatetime(new Date(parsed))));
6696
- }
6697
- if (left.length > 0 && right.length > 0) {
6698
- const parsedStart = Date.parse(left);
6699
- const parsedEnd = Date.parse(right);
6700
- if (isNaN(parsedStart) || isNaN(parsedEnd)) return err({
6701
- type: "InvalidDateFormat",
6702
- span
6703
- });
6704
- return ok(dateRange(CborDate.fromDatetime(new Date(parsedStart)), CborDate.fromDatetime(new Date(parsedEnd))));
6664
+ const fallback = parseTagInner(innerContent);
6665
+ if (!fallback.ok) return fallback;
6666
+ lexer.bump(closeIdx);
6667
+ const close = lexer.next();
6668
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
6669
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
6670
+ return ok(fallback.value);
6671
+ }
6672
+ /**
6673
+ * Locate the index of the closing `)` matching the `(` that has already
6674
+ * been consumed by `parseTag`. Mirrors Rust `find_matching_paren`.
6675
+ */
6676
+ function findMatchingCloseParen(src) {
6677
+ let depth = 0;
6678
+ for (let i = 0; i < src.length; i++) {
6679
+ const ch = src.charCodeAt(i);
6680
+ if (ch === 40) depth += 1;
6681
+ else if (ch === 41) {
6682
+ if (depth === 0) return i;
6683
+ depth -= 1;
6705
6684
  }
6706
- return err({
6707
- type: "InvalidDateFormat",
6708
- span
6709
- });
6710
6685
  }
6711
- const parsed = Date.parse(content);
6712
- if (isNaN(parsed)) return err({
6713
- type: "InvalidDateFormat",
6714
- span
6715
- });
6716
- return ok(date(CborDate.fromDatetime(new Date(parsed))));
6717
6686
  }
6718
6687
  /**
6719
- * Parse known value content from '...' pattern.
6688
+ * Fallback for `tagged(N)` and `tagged(name)` when the full delegation
6689
+ * to dcbor-pattern fails. Mirrors Rust `parse_tag_inner`.
6720
6690
  */
6721
- function parseKnownValueContent(content) {
6722
- const numValue = parseInt(content, 10);
6723
- if (!isNaN(numValue)) return ok(knownValue({ value: () => BigInt(numValue) }));
6724
- return ok(patternLeaf(leafKnownValue(KnownValuePattern.named(content))));
6691
+ function parseTagInner(src) {
6692
+ const trimmed = src.trim();
6693
+ if (trimmed.length === 0) return err(unexpectedEndOfInput());
6694
+ if (trimmed.startsWith("/")) return err(unexpectedEndOfInput());
6695
+ if (/^\d+$/.test(trimmed)) try {
6696
+ const dcborResult = parse$1(`tagged(${trimmed})`);
6697
+ if (dcborResult.ok && dcborResult.value.kind === "Structure" && dcborResult.value.pattern.type === "Tagged") return ok(patternLeaf(leafTag(TaggedPattern.fromDcborPattern(dcborResult.value.pattern.pattern))));
6698
+ } catch {}
6699
+ const dcborResult = parse$1(`tagged(${trimmed})`);
6700
+ if (dcborResult.ok && dcborResult.value.kind === "Structure" && dcborResult.value.pattern.type === "Tagged") return ok(patternLeaf(leafTag(TaggedPattern.fromDcborPattern(dcborResult.value.pattern.pattern))));
6701
+ return err(unexpectedEndOfInput());
6725
6702
  }
6703
+ //#endregion
6704
+ //#region src/parse/structure/assertion-parser.ts
6726
6705
  /**
6727
- * Parse CBOR pattern.
6706
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6707
+ * Copyright © 2025-2026 Parity Technologies
6708
+ *
6709
+ * Assertion parser — port of `bc-envelope-pattern-rust`
6710
+ * `parse/structure/assertion_parser.rs`.
6711
+ *
6712
+ * Note: Rust's `parse_assertion` ignores its lexer entirely and always
6713
+ * returns `Pattern::any_assertion()`. There is intentionally **no**
6714
+ * `assert(pred, obj)` syntax — predicate/object filters are written via
6715
+ * the dedicated `assertpred(...)` / `assertobj(...)` keywords.
6728
6716
  *
6729
- * Matches Rust parse_cbor: tries dcbor-pattern regex first (/keyword/),
6730
- * then CBOR diagnostic notation via parseDcborItemPartial, then falls
6731
- * back to parseOr for envelope pattern expressions.
6717
+ * @module envelope-pattern/parse/structure/assertion-parser
6732
6718
  */
6733
- function parseCbor(lexer) {
6734
- if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyCbor());
6735
- lexer.next();
6736
- if (lexer.peek() === "/") {
6737
- const regexTokenResult = lexer.next();
6738
- if (regexTokenResult?.token.type === "Regex") {
6739
- const regexToken = regexTokenResult.token;
6740
- if (!regexToken.value.ok) return err(regexToken.value.error);
6741
- const keyword = regexToken.value.value;
6742
- const dcborResult = parse$1(keyword);
6743
- if (!dcborResult.ok) return err(unexpectedToken(regexToken, regexTokenResult.span));
6744
- if (lexer.next()?.token.type !== "ParenClose") return err({
6745
- type: "ExpectedCloseParen",
6746
- span: lexer.span()
6747
- });
6748
- return ok(cborPattern(dcborResult.value));
6749
- }
6750
- }
6751
- const cborResult = parseDcborItemPartial(lexer.remainder());
6752
- if (cborResult.ok) {
6753
- const [cborData, consumed] = cborResult.value;
6754
- lexer.bump(consumed);
6755
- while (lexer.peek() === " " || lexer.peek() === " " || lexer.peek() === "\n") lexer.bump(1);
6756
- if (lexer.next()?.token.type !== "ParenClose") return err({
6757
- type: "ExpectedCloseParen",
6758
- span: lexer.span()
6759
- });
6760
- return ok(cborValue(cborData));
6761
- }
6762
- const inner = parseOr(lexer);
6763
- if (!inner.ok) return inner;
6764
- if (lexer.next()?.token.type !== "ParenClose") return err({
6765
- type: "ExpectedCloseParen",
6766
- span: lexer.span()
6767
- });
6768
- return inner;
6719
+ function parseAssertion(_lexer) {
6720
+ return ok(anyAssertion());
6769
6721
  }
6770
- function parseNode(lexer) {
6771
- if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyNode());
6772
- lexer.next();
6773
- const afterParen = lexer.peekToken();
6774
- if (afterParen?.token.type === "Range") {
6775
- lexer.next();
6776
- const rangeToken = afterParen.token;
6777
- if (!rangeToken.value.ok) return err(rangeToken.value.error);
6778
- const interval = rangeToken.value.value.interval();
6779
- if (lexer.next()?.token.type !== "ParenClose") return err({
6780
- type: "ExpectedCloseParen",
6781
- span: lexer.span()
6782
- });
6783
- return ok(patternStructure(structureNode(NodePattern.fromInterval(interval))));
6784
- }
6722
+ //#endregion
6723
+ //#region src/parse/structure/assertion-obj-parser.ts
6724
+ /**
6725
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6726
+ * Copyright © 2025-2026 Parity Technologies
6727
+ *
6728
+ * Assertion-object parser — port of
6729
+ * `bc-envelope-pattern-rust/src/parse/structure/assertion_obj_parser.rs`.
6730
+ *
6731
+ * Requires `assertobj(<pattern>)`. The bare `assertobj` keyword is a
6732
+ * syntax error in Rust; we now mirror that behaviour.
6733
+ *
6734
+ * @module envelope-pattern/parse/structure/assertion-obj-parser
6735
+ */
6736
+ function parseAssertionObj(lexer) {
6737
+ const open = lexer.next();
6738
+ if (open === void 0) return err(unexpectedEndOfInput());
6739
+ if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
6785
6740
  const inner = parseOr(lexer);
6786
6741
  if (!inner.ok) return inner;
6787
- if (lexer.next()?.token.type !== "ParenClose") return err({
6788
- type: "ExpectedCloseParen",
6789
- span: lexer.span()
6790
- });
6791
- return ok(patternStructure(structureNode(NodePattern.withSubject(inner.value))));
6792
- }
6793
- function parseAssertion(lexer) {
6794
- if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyAssertion());
6795
- lexer.next();
6796
- const pred = parseOr(lexer);
6797
- if (!pred.ok) return pred;
6798
- const comma = lexer.next();
6799
- if (comma?.token.type !== "Comma") return err(unexpectedToken(comma?.token ?? { type: "Null" }, comma?.span ?? lexer.span()));
6800
- const obj = parseOr(lexer);
6801
- if (!obj.ok) return obj;
6802
- if (lexer.next()?.token.type !== "ParenClose") return err({
6803
- type: "ExpectedCloseParen",
6804
- span: lexer.span()
6805
- });
6806
- return ok(patternStructure(structureAssertions(AssertionsPattern.withBoth(pred.value, obj.value))));
6742
+ const close = lexer.next();
6743
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
6744
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
6745
+ return ok(assertionWithObject(inner.value));
6807
6746
  }
6747
+ //#endregion
6748
+ //#region src/parse/structure/assertion-pred-parser.ts
6749
+ /**
6750
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6751
+ * Copyright © 2025-2026 Parity Technologies
6752
+ *
6753
+ * Assertion-predicate parser — port of
6754
+ * `bc-envelope-pattern-rust/src/parse/structure/assertion_pred_parser.rs`.
6755
+ *
6756
+ * Requires `assertpred(<pattern>)`. The bare `assertpred` keyword is a
6757
+ * syntax error in Rust (it errors on `UnexpectedEndOfInput` /
6758
+ * `UnexpectedToken`); we now mirror that behaviour.
6759
+ *
6760
+ * @module envelope-pattern/parse/structure/assertion-pred-parser
6761
+ */
6808
6762
  function parseAssertionPred(lexer) {
6809
- if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyAssertion());
6810
- lexer.next();
6763
+ const open = lexer.next();
6764
+ if (open === void 0) return err(unexpectedEndOfInput());
6765
+ if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
6811
6766
  const inner = parseOr(lexer);
6812
6767
  if (!inner.ok) return inner;
6813
- if (lexer.next()?.token.type !== "ParenClose") return err({
6814
- type: "ExpectedCloseParen",
6815
- span: lexer.span()
6816
- });
6768
+ const close = lexer.next();
6769
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
6770
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
6817
6771
  return ok(assertionWithPredicate(inner.value));
6818
6772
  }
6819
- function parseAssertionObj(lexer) {
6820
- if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyAssertion());
6821
- lexer.next();
6822
- const inner = parseOr(lexer);
6823
- if (!inner.ok) return inner;
6824
- if (lexer.next()?.token.type !== "ParenClose") return err({
6825
- type: "ExpectedCloseParen",
6826
- span: lexer.span()
6827
- });
6828
- return ok(assertionWithObject(inner.value));
6773
+ //#endregion
6774
+ //#region src/parse/structure/compressed-parser.ts
6775
+ /**
6776
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6777
+ * Copyright © 2025-2026 Parity Technologies
6778
+ *
6779
+ * Compressed parser — port of `bc-envelope-pattern-rust`
6780
+ * `parse/structure/compressed_parser.rs`.
6781
+ *
6782
+ * @module envelope-pattern/parse/structure/compressed-parser
6783
+ */
6784
+ function parseCompressed(_lexer) {
6785
+ return ok(compressed());
6829
6786
  }
6787
+ //#endregion
6788
+ //#region src/parse/structure/digest-parser.ts
6789
+ /**
6790
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6791
+ * Copyright © 2025-2026 Parity Technologies
6792
+ *
6793
+ * Digest parser — port of `bc-envelope-pattern-rust`
6794
+ * `parse/structure/digest_parser.rs`.
6795
+ *
6796
+ * Mirrors Rust exactly:
6797
+ *
6798
+ * - Requires `digest(...)` — bare `digest` is an `UnexpectedEndOfInput`
6799
+ * error (the previous TS port silently returned `digest(any)`).
6800
+ * - Inside the parens, accepts either a UR string (`ur:digest/...`,
6801
+ * parsed via `Digest.fromURString`) or a hex byte prefix.
6802
+ * - Hex prefixes must have even length and not exceed `Digest.DIGEST_SIZE`
6803
+ * bytes; otherwise the parser surfaces `InvalidHexString`.
6804
+ *
6805
+ * @module envelope-pattern/parse/structure/digest-parser
6806
+ */
6807
+ const DIGEST_SIZE = Digest.DIGEST_SIZE;
6830
6808
  function parseDigest(lexer) {
6831
- if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(patternStructure(structureDigest(DigestPattern.any())));
6832
- lexer.next();
6833
- const digestToken = lexer.next();
6834
- if (digestToken === void 0) return err(unexpectedEndOfInput());
6835
- if (digestToken.token.type === "HexPattern") {
6836
- if (!digestToken.token.value.ok) return err(digestToken.token.value.error);
6837
- if (lexer.next()?.token.type !== "ParenClose") return err({
6838
- type: "ExpectedCloseParen",
6839
- span: lexer.span()
6840
- });
6841
- return ok(digestPrefix(digestToken.token.value.value));
6809
+ const open = lexer.next();
6810
+ if (open === void 0) return err(unexpectedEndOfInput());
6811
+ if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
6812
+ const innerResult = parseDigestInner(lexer.remainder(), lexer.position);
6813
+ if (!innerResult.ok) return innerResult;
6814
+ const [pattern, consumed] = innerResult.value;
6815
+ lexer.bump(consumed);
6816
+ const close = lexer.next();
6817
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
6818
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
6819
+ return ok(pattern);
6820
+ }
6821
+ function parseDigestInner(src, basePos) {
6822
+ let pos = 0;
6823
+ pos = skipWs(src, pos);
6824
+ if (src.startsWith("ur:", pos)) {
6825
+ const start = pos;
6826
+ while (pos < src.length && src[pos] !== ")") pos += 1;
6827
+ const ur = src.slice(start, pos).trimEnd();
6828
+ let parsed;
6829
+ try {
6830
+ parsed = Digest.fromURString(ur);
6831
+ } catch {
6832
+ return err(invalidUr(ur, {
6833
+ start: basePos + start,
6834
+ end: basePos + pos
6835
+ }));
6836
+ }
6837
+ pos = skipWs(src, pos);
6838
+ return ok([digest(parsed), pos]);
6839
+ }
6840
+ const start = pos;
6841
+ while (pos < src.length && isAsciiHexDigit(src.charCodeAt(pos))) pos += 1;
6842
+ if (pos === start) return err(invalidHexString({
6843
+ start: basePos + pos,
6844
+ end: basePos + pos
6845
+ }));
6846
+ const hexStr = src.slice(start, pos);
6847
+ if (hexStr.length % 2 !== 0) return err(invalidHexString({
6848
+ start: basePos + pos,
6849
+ end: basePos + pos
6850
+ }));
6851
+ const bytes = decodeHex(hexStr);
6852
+ if (bytes === void 0) return err(invalidHexString({
6853
+ start: basePos + pos,
6854
+ end: basePos + pos
6855
+ }));
6856
+ if (bytes.length > DIGEST_SIZE) return err(invalidHexString({
6857
+ start: basePos + pos,
6858
+ end: basePos + pos
6859
+ }));
6860
+ pos = skipWs(src, pos);
6861
+ return ok([digestPrefix(bytes), pos]);
6862
+ }
6863
+ function skipWs(src, pos) {
6864
+ while (pos < src.length) {
6865
+ const ch = src[pos];
6866
+ if (ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f") pos += 1;
6867
+ else break;
6842
6868
  }
6843
- if (digestToken.token.type === "Identifier") {
6844
- const hexStr = digestToken.token.value;
6845
- if (hexStr.length === 0 || hexStr.length % 2 !== 0 || !/^[0-9a-fA-F]+$/.test(hexStr)) return err({
6846
- type: "InvalidHexString",
6847
- span: digestToken.span
6848
- });
6849
- const bytes = new Uint8Array(hexStr.length / 2);
6850
- for (let i = 0; i < hexStr.length; i += 2) bytes[i / 2] = Number.parseInt(hexStr.slice(i, i + 2), 16);
6851
- if (lexer.next()?.token.type !== "ParenClose") return err({
6852
- type: "ExpectedCloseParen",
6853
- span: lexer.span()
6854
- });
6855
- return ok(digestPrefix(bytes));
6869
+ return pos;
6870
+ }
6871
+ function isAsciiHexDigit(c) {
6872
+ return c >= 48 && c <= 57 || c >= 65 && c <= 70 || c >= 97 && c <= 102;
6873
+ }
6874
+ function decodeHex(hex) {
6875
+ if (hex.length % 2 !== 0) return void 0;
6876
+ const out = new Uint8Array(hex.length / 2);
6877
+ for (let i = 0; i < hex.length; i += 2) {
6878
+ const value = Number.parseInt(hex.slice(i, i + 2), 16);
6879
+ if (Number.isNaN(value)) return void 0;
6880
+ out[i / 2] = value;
6856
6881
  }
6857
- return err(unexpectedToken(digestToken.token, digestToken.span));
6882
+ return out;
6883
+ }
6884
+ //#endregion
6885
+ //#region src/parse/structure/elided-parser.ts
6886
+ /**
6887
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6888
+ * Copyright © 2025-2026 Parity Technologies
6889
+ *
6890
+ * Elided parser — port of `bc-envelope-pattern-rust`
6891
+ * `parse/structure/elided_parser.rs`.
6892
+ *
6893
+ * @module envelope-pattern/parse/structure/elided-parser
6894
+ */
6895
+ function parseElided(_lexer) {
6896
+ return ok(elided());
6858
6897
  }
6898
+ //#endregion
6899
+ //#region src/parse/structure/encrypted-parser.ts
6900
+ /**
6901
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6902
+ * Copyright © 2025-2026 Parity Technologies
6903
+ *
6904
+ * Encrypted parser — port of `bc-envelope-pattern-rust`
6905
+ * `parse/structure/encrypted_parser.rs`.
6906
+ *
6907
+ * @module envelope-pattern/parse/structure/encrypted-parser
6908
+ */
6909
+ function parseEncrypted(_lexer) {
6910
+ return ok(encrypted());
6911
+ }
6912
+ //#endregion
6913
+ //#region src/parse/structure/node-parser.ts
6914
+ /**
6915
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6916
+ * Copyright © 2025-2026 Parity Technologies
6917
+ *
6918
+ * Node parser — port of `bc-envelope-pattern-rust`
6919
+ * `parse/structure/node_parser.rs`.
6920
+ *
6921
+ * Mirrors Rust:
6922
+ * - Bare `node` → `any_node()`.
6923
+ * - `node({n})` / `node({n,m})` / `node({n,})` → `node_with_assertions_range`.
6924
+ * - Anything else inside the parens (e.g. `node(text)`) is a syntax error
6925
+ * in Rust; the previous TS port silently produced an always-matching
6926
+ * `WithSubject` node, which we have removed.
6927
+ *
6928
+ * @module envelope-pattern/parse/structure/node-parser
6929
+ */
6930
+ function parseNode(lexer) {
6931
+ if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyNode());
6932
+ lexer.next();
6933
+ const inner = lexer.next();
6934
+ if (inner === void 0) return err(unexpectedEndOfInput());
6935
+ if (inner.token.type !== "Range") return err(unexpectedToken(inner.token, inner.span));
6936
+ if (!inner.token.value.ok) return err(inner.token.value.error);
6937
+ const interval = inner.token.value.value.interval();
6938
+ const close = lexer.next();
6939
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
6940
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
6941
+ return ok(patternStructure(structureNode(NodePattern.fromInterval(interval))));
6942
+ }
6943
+ //#endregion
6944
+ //#region src/parse/structure/object-parser.ts
6945
+ /**
6946
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6947
+ * Copyright © 2025-2026 Parity Technologies
6948
+ *
6949
+ * Object parser — port of `bc-envelope-pattern-rust`
6950
+ * `parse/structure/object_parser.rs`.
6951
+ *
6952
+ * @module envelope-pattern/parse/structure/object-parser
6953
+ */
6859
6954
  function parseObject(lexer) {
6860
6955
  if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyObject());
6861
6956
  lexer.next();
6862
6957
  const inner = parseOr(lexer);
6863
6958
  if (!inner.ok) return inner;
6864
- if (lexer.next()?.token.type !== "ParenClose") return err({
6865
- type: "ExpectedCloseParen",
6866
- span: lexer.span()
6867
- });
6959
+ const close = lexer.next();
6960
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
6961
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
6868
6962
  return ok(object(inner.value));
6869
6963
  }
6964
+ //#endregion
6965
+ //#region src/parse/structure/obscured-parser.ts
6966
+ /**
6967
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6968
+ * Copyright © 2025-2026 Parity Technologies
6969
+ *
6970
+ * Obscured parser — port of `bc-envelope-pattern-rust`
6971
+ * `parse/structure/obscured_parser.rs`.
6972
+ *
6973
+ * @module envelope-pattern/parse/structure/obscured-parser
6974
+ */
6975
+ function parseObscured(_lexer) {
6976
+ return ok(obscured());
6977
+ }
6978
+ //#endregion
6979
+ //#region src/parse/structure/predicate-parser.ts
6980
+ /**
6981
+ * Copyright © 2023-2026 Blockchain Commons, LLC
6982
+ * Copyright © 2025-2026 Parity Technologies
6983
+ *
6984
+ * Predicate parser — port of `bc-envelope-pattern-rust`
6985
+ * `parse/structure/predicate_parser.rs`.
6986
+ *
6987
+ * @module envelope-pattern/parse/structure/predicate-parser
6988
+ */
6870
6989
  function parsePredicate(lexer) {
6871
6990
  if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anyPredicate());
6872
6991
  lexer.next();
6873
6992
  const inner = parseOr(lexer);
6874
6993
  if (!inner.ok) return inner;
6875
- if (lexer.next()?.token.type !== "ParenClose") return err({
6876
- type: "ExpectedCloseParen",
6877
- span: lexer.span()
6878
- });
6994
+ const close = lexer.next();
6995
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
6996
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
6879
6997
  return ok(predicate(inner.value));
6880
6998
  }
6999
+ //#endregion
7000
+ //#region src/parse/structure/subject-parser.ts
7001
+ /**
7002
+ * Copyright © 2023-2026 Blockchain Commons, LLC
7003
+ * Copyright © 2025-2026 Parity Technologies
7004
+ *
7005
+ * Subject parser — port of `bc-envelope-pattern-rust`
7006
+ * `parse/structure/subject_parser.rs`.
7007
+ *
7008
+ * @module envelope-pattern/parse/structure/subject-parser
7009
+ */
6881
7010
  function parseSubject(lexer) {
6882
7011
  if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(anySubject());
6883
7012
  lexer.next();
6884
7013
  const inner = parseOr(lexer);
6885
7014
  if (!inner.ok) return inner;
6886
- if (lexer.next()?.token.type !== "ParenClose") return err({
6887
- type: "ExpectedCloseParen",
6888
- span: lexer.span()
6889
- });
7015
+ const close = lexer.next();
7016
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
7017
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
6890
7018
  return ok(subject(inner.value));
6891
7019
  }
7020
+ //#endregion
7021
+ //#region src/parse/structure/wrapped-parser.ts
7022
+ /**
7023
+ * Copyright © 2023-2026 Blockchain Commons, LLC
7024
+ * Copyright © 2025-2026 Parity Technologies
7025
+ *
7026
+ * Wrapped/unwrap parser — port of `bc-envelope-pattern-rust`
7027
+ * `parse/structure/wrapped_parser.rs`.
7028
+ *
7029
+ * @module envelope-pattern/parse/structure/wrapped-parser
7030
+ */
7031
+ function parseWrapped(_lexer) {
7032
+ return ok(wrapped());
7033
+ }
6892
7034
  function parseUnwrap(lexer) {
6893
7035
  if (lexer.peekToken()?.token.type !== "ParenOpen") return ok(unwrapEnvelope());
6894
7036
  lexer.next();
6895
7037
  const inner = parseOr(lexer);
6896
7038
  if (!inner.ok) return inner;
6897
- if (lexer.next()?.token.type !== "ParenClose") return err({
6898
- type: "ExpectedCloseParen",
6899
- span: lexer.span()
6900
- });
7039
+ const close = lexer.next();
7040
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
7041
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
6901
7042
  return ok(unwrapMatching(inner.value));
6902
7043
  }
6903
7044
  //#endregion
7045
+ //#region src/parse/meta/capture-parser.ts
7046
+ /**
7047
+ * Copyright © 2023-2026 Blockchain Commons, LLC
7048
+ * Copyright © 2025-2026 Parity Technologies
7049
+ *
7050
+ * Capture parser — port of `bc-envelope-pattern-rust`
7051
+ * `parse/meta/capture_parser.rs`.
7052
+ *
7053
+ * The `@name(...)` form requires explicit parentheses. Mirrors Rust
7054
+ * exactly:
7055
+ * ```ignore
7056
+ * @name ( expr )
7057
+ * ```
7058
+ * The previous TS port called `parse_group` (primary + quantifier), which
7059
+ * wrapped the inner expression in a redundant `GroupPattern` and accepted
7060
+ * the bare `@name p` form that Rust rejects.
7061
+ *
7062
+ * @module envelope-pattern/parse/meta/capture-parser
7063
+ */
7064
+ function parseCapture(lexer, name) {
7065
+ const open = lexer.next();
7066
+ if (open === void 0) return err(unexpectedEndOfInput());
7067
+ if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
7068
+ const inner = parseOr(lexer);
7069
+ if (!inner.ok) return inner;
7070
+ const close = lexer.next();
7071
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
7072
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
7073
+ return ok(capture(name, inner.value));
7074
+ }
7075
+ //#endregion
7076
+ //#region src/parse/meta/group-parser.ts
7077
+ /**
7078
+ * Copyright © 2023-2026 Blockchain Commons, LLC
7079
+ * Copyright © 2025-2026 Parity Technologies
7080
+ *
7081
+ * Group parser — port of `bc-envelope-pattern-rust`
7082
+ * `parse/meta/group_parser.rs`.
7083
+ *
7084
+ * Called from `parse_primary` after the opening `(` has been consumed.
7085
+ *
7086
+ * Mirrors Rust exactly:
7087
+ *
7088
+ * - Parse the inner expression with `parse_or`.
7089
+ * - Expect `)`. If missing, surface `ExpectedCloseParen`.
7090
+ * - Lookahead **once** for a quantifier suffix. If present, consume it
7091
+ * and wrap as `Pattern::repeat(inner, …)`. Otherwise return the inner
7092
+ * expression unchanged.
7093
+ *
7094
+ * The previous TS port wrapped every parenthesised expression in a
7095
+ * dedicated `GroupPattern` and applied quantifiers to bare primaries —
7096
+ * both broke `format(parse(s)) === s` round-tripping.
7097
+ *
7098
+ * @module envelope-pattern/parse/meta/group-parser
7099
+ */
7100
+ function parseGroup(lexer) {
7101
+ const inner = parseOr(lexer);
7102
+ if (!inner.ok) return inner;
7103
+ const close = lexer.next();
7104
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
7105
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
7106
+ const next = lexer.peekToken();
7107
+ if (next === void 0) return inner;
7108
+ let quantifier;
7109
+ const tokenType = next.token.type;
7110
+ if (tokenType === "RepeatZeroOrMore") quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Greedy);
7111
+ else if (tokenType === "RepeatZeroOrMoreLazy") quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Lazy);
7112
+ else if (tokenType === "RepeatZeroOrMorePossessive") quantifier = Quantifier$1.zeroOrMore(Reluctance$1.Possessive);
7113
+ else if (tokenType === "RepeatOneOrMore") quantifier = Quantifier$1.oneOrMore(Reluctance$1.Greedy);
7114
+ else if (tokenType === "RepeatOneOrMoreLazy") quantifier = Quantifier$1.oneOrMore(Reluctance$1.Lazy);
7115
+ else if (tokenType === "RepeatOneOrMorePossessive") quantifier = Quantifier$1.oneOrMore(Reluctance$1.Possessive);
7116
+ else if (tokenType === "RepeatZeroOrOne") quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Greedy);
7117
+ else if (tokenType === "RepeatZeroOrOneLazy") quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Lazy);
7118
+ else if (tokenType === "RepeatZeroOrOnePossessive") quantifier = Quantifier$1.zeroOrOne(Reluctance$1.Possessive);
7119
+ else if (tokenType === "Range") {
7120
+ if (!next.token.value.ok) return err(next.token.value.error);
7121
+ quantifier = next.token.value.value;
7122
+ } else return inner;
7123
+ lexer.next();
7124
+ return ok(repeat(inner.value, quantifier.min(), quantifier.max(), quantifier.reluctance()));
7125
+ }
7126
+ //#endregion
7127
+ //#region src/parse/meta/search-parser.ts
7128
+ /**
7129
+ * Copyright © 2023-2026 Blockchain Commons, LLC
7130
+ * Copyright © 2025-2026 Parity Technologies
7131
+ *
7132
+ * Search parser — port of `bc-envelope-pattern-rust`
7133
+ * `parse/meta/search_parser.rs`.
7134
+ *
7135
+ * @module envelope-pattern/parse/meta/search-parser
7136
+ */
7137
+ function parseSearch(lexer) {
7138
+ const open = lexer.next();
7139
+ if (open === void 0) return err(unexpectedEndOfInput());
7140
+ if (open.token.type !== "ParenOpen") return err(unexpectedToken(open.token, open.span));
7141
+ const inner = parseOr(lexer);
7142
+ if (!inner.ok) return inner;
7143
+ const close = lexer.next();
7144
+ if (close === void 0) return err(expectedCloseParen(lexer.span()));
7145
+ if (close.token.type !== "ParenClose") return err(unexpectedToken(close.token, close.span));
7146
+ return ok(search(inner.value));
7147
+ }
7148
+ //#endregion
7149
+ //#region src/parse/meta/primary-parser.ts
7150
+ /**
7151
+ * Copyright © 2023-2026 Blockchain Commons, LLC
7152
+ * Copyright © 2025-2026 Parity Technologies
7153
+ *
7154
+ * Primary parser — port of `bc-envelope-pattern-rust`
7155
+ * `parse/meta/primary_parser.rs`.
7156
+ *
7157
+ * Dispatches on the next token to the appropriate leaf/structure/meta
7158
+ * parser. When a `(` is encountered the open paren is consumed here and
7159
+ * `parse_group` handles the rest (paren'd expression + optional
7160
+ * quantifier suffix).
7161
+ *
7162
+ * @module envelope-pattern/parse/meta/primary-parser
7163
+ */
7164
+ function parsePrimary(lexer) {
7165
+ const tokenResult = lexer.next();
7166
+ if (tokenResult === void 0) return err(unexpectedEndOfInput());
7167
+ const { token, span } = tokenResult;
7168
+ switch (token.type) {
7169
+ case "Search": return parseSearch(lexer);
7170
+ case "Node": return parseNode(lexer);
7171
+ case "Assertion": return parseAssertion(lexer);
7172
+ case "AssertionPred": return parseAssertionPred(lexer);
7173
+ case "AssertionObj": return parseAssertionObj(lexer);
7174
+ case "Digest": return parseDigest(lexer);
7175
+ case "Obj": return parseObject(lexer);
7176
+ case "Obscured": return parseObscured(lexer);
7177
+ case "Elided": return parseElided(lexer);
7178
+ case "Encrypted": return parseEncrypted(lexer);
7179
+ case "Compressed": return parseCompressed(lexer);
7180
+ case "Pred": return parsePredicate(lexer);
7181
+ case "Subject": return parseSubject(lexer);
7182
+ case "Wrapped": return parseWrapped(lexer);
7183
+ case "Unwrap": return parseUnwrap(lexer);
7184
+ case "Leaf": return ok(leaf());
7185
+ case "GroupName": return parseCapture(lexer, token.name);
7186
+ case "ParenOpen": return parseGroup(lexer);
7187
+ case "Cbor": return parseCbor(lexer);
7188
+ case "RepeatZeroOrMore": return ok(any());
7189
+ case "BoolKeyword": return ok(anyBool());
7190
+ case "BoolTrue": return ok(bool(true));
7191
+ case "BoolFalse": return ok(bool(false));
7192
+ case "NumberKeyword": return ok(anyNumber());
7193
+ case "TextKeyword": return ok(anyText());
7194
+ case "StringLiteral":
7195
+ if (!token.value.ok) return err(token.value.error);
7196
+ return ok(text(token.value.value));
7197
+ case "UnsignedInteger":
7198
+ if (!token.value.ok) return err(token.value.error);
7199
+ return parseNumberRangeOrComparison(lexer, token.value.value);
7200
+ case "Integer":
7201
+ if (!token.value.ok) return err(token.value.error);
7202
+ return parseNumberRangeOrComparison(lexer, token.value.value);
7203
+ case "Float":
7204
+ if (!token.value.ok) return err(token.value.error);
7205
+ return parseNumberRangeOrComparison(lexer, token.value.value);
7206
+ case "GreaterThanOrEqual": return parseComparisonNumber(lexer, ">=");
7207
+ case "LessThanOrEqual": return parseComparisonNumber(lexer, "<=");
7208
+ case "GreaterThan": return parseComparisonNumber(lexer, ">");
7209
+ case "LessThan": return parseComparisonNumber(lexer, "<");
7210
+ case "NaN": return ok(patternLeaf(leafNumber(NumberPattern.nan())));
7211
+ case "Infinity": return ok(number(Infinity));
7212
+ case "NegativeInfinity": return ok(number(-Infinity));
7213
+ case "Regex":
7214
+ if (!token.value.ok) return err(token.value.error);
7215
+ try {
7216
+ return ok(textRegex(new RegExp(token.value.value)));
7217
+ } catch {
7218
+ return err(invalidRegex(span));
7219
+ }
7220
+ case "BracketOpen": return parseArray(lexer);
7221
+ case "ByteString": return ok(anyByteString());
7222
+ case "HexPattern":
7223
+ if (!token.value.ok) return err(token.value.error);
7224
+ return ok(byteString(token.value.value));
7225
+ case "HexBinaryRegex":
7226
+ if (!token.value.ok) return err(token.value.error);
7227
+ try {
7228
+ return ok(patternLeaf(leafByteString(ByteStringPattern.regex(new RegExp(token.value.value)))));
7229
+ } catch {
7230
+ return err(invalidRegex(span));
7231
+ }
7232
+ case "DateKeyword": return ok(anyDate());
7233
+ case "DatePattern":
7234
+ if (!token.value.ok) return err(token.value.error);
7235
+ return parseDateContent(token.value.value, span);
7236
+ case "Tagged": return parseTag(lexer);
7237
+ case "Known": return ok(anyKnownValue());
7238
+ case "SingleQuotedPattern":
7239
+ if (!token.value.ok) return err(token.value.error);
7240
+ return parseKnownValueContent(token.value.value);
7241
+ case "SingleQuotedRegex":
7242
+ if (!token.value.ok) return err(token.value.error);
7243
+ try {
7244
+ return ok(patternLeaf(leafKnownValue(KnownValuePattern.regex(new RegExp(token.value.value)))));
7245
+ } catch {
7246
+ return err(invalidRegex(span));
7247
+ }
7248
+ case "Null": return ok(nullPattern());
7249
+ case "Identifier": return err(unrecognizedToken(span));
7250
+ case "And":
7251
+ case "Or":
7252
+ case "Not":
7253
+ case "Traverse":
7254
+ case "RepeatZeroOrMoreLazy":
7255
+ case "RepeatZeroOrMorePossessive":
7256
+ case "RepeatOneOrMore":
7257
+ case "RepeatOneOrMoreLazy":
7258
+ case "RepeatOneOrMorePossessive":
7259
+ case "RepeatZeroOrOne":
7260
+ case "RepeatZeroOrOneLazy":
7261
+ case "RepeatZeroOrOnePossessive":
7262
+ case "ParenClose":
7263
+ case "BracketClose":
7264
+ case "Comma":
7265
+ case "Ellipsis":
7266
+ case "Range": return err(unexpectedToken(token, span));
7267
+ }
7268
+ }
7269
+ //#endregion
7270
+ //#region src/parse/meta/and-parser.ts
7271
+ /**
7272
+ * Copyright © 2023-2026 Blockchain Commons, LLC
7273
+ * Copyright © 2025-2026 Parity Technologies
7274
+ *
7275
+ * And parser — port of `bc-envelope-pattern-rust`
7276
+ * `parse/meta/and_parser.rs`.
7277
+ *
7278
+ * Mirrors Rust: `parse_and` calls `parse_primary` (NOT `parse_not`); `!`
7279
+ * is handled at a higher precedence level by `parse_not`.
7280
+ *
7281
+ * @module envelope-pattern/parse/meta/and-parser
7282
+ */
7283
+ function parseAnd(lexer) {
7284
+ const patterns = [];
7285
+ const first = parsePrimary(lexer);
7286
+ if (!first.ok) return first;
7287
+ patterns.push(first.value);
7288
+ while (true) {
7289
+ if (lexer.peekToken()?.token.type !== "And") break;
7290
+ lexer.next();
7291
+ const nextExpr = parsePrimary(lexer);
7292
+ if (!nextExpr.ok) return nextExpr;
7293
+ patterns.push(nextExpr.value);
7294
+ }
7295
+ if (patterns.length === 1) return ok(patterns[0]);
7296
+ return ok(and(patterns));
7297
+ }
7298
+ //#endregion
7299
+ //#region src/parse/meta/not-parser.ts
7300
+ /**
7301
+ * Copyright © 2023-2026 Blockchain Commons, LLC
7302
+ * Copyright © 2025-2026 Parity Technologies
7303
+ *
7304
+ * Not parser — port of `bc-envelope-pattern-rust`
7305
+ * `parse/meta/not_parser.rs`.
7306
+ *
7307
+ * Mirrors Rust:
7308
+ * - On `!`, recurse into `parse_not` so chained negation parses as
7309
+ * `not(not(x))` rather than `not(group(x))`.
7310
+ * - Otherwise descend into `parse_and`.
7311
+ *
7312
+ * @module envelope-pattern/parse/meta/not-parser
7313
+ */
7314
+ function parseNot(lexer) {
7315
+ if (lexer.peekToken()?.token.type === "Not") {
7316
+ lexer.next();
7317
+ const inner = parseNot(lexer);
7318
+ if (!inner.ok) return inner;
7319
+ return ok(notMatching(inner.value));
7320
+ }
7321
+ return parseAnd(lexer);
7322
+ }
7323
+ //#endregion
7324
+ //#region src/parse/meta/traverse-parser.ts
7325
+ /**
7326
+ * Copyright © 2023-2026 Blockchain Commons, LLC
7327
+ * Copyright © 2025-2026 Parity Technologies
7328
+ *
7329
+ * Traverse parser — port of `bc-envelope-pattern-rust`
7330
+ * `parse/meta/traverse_parser.rs`.
7331
+ *
7332
+ * Note the precedence chain: `parse_or → parse_traverse → parse_not →
7333
+ * parse_and → parse_primary`. The earlier TS port had `parse_traverse`
7334
+ * call `parse_and` directly, which pushed `!` below `&` and
7335
+ * miscompiled `!a & b`.
7336
+ *
7337
+ * @module envelope-pattern/parse/meta/traverse-parser
7338
+ */
7339
+ function parseTraverse(lexer) {
7340
+ const patterns = [];
7341
+ const first = parseNot(lexer);
7342
+ if (!first.ok) return first;
7343
+ patterns.push(first.value);
7344
+ while (true) {
7345
+ if (lexer.peekToken()?.token.type !== "Traverse") break;
7346
+ lexer.next();
7347
+ const nextExpr = parseNot(lexer);
7348
+ if (!nextExpr.ok) return nextExpr;
7349
+ patterns.push(nextExpr.value);
7350
+ }
7351
+ if (patterns.length === 1) return ok(patterns[0]);
7352
+ return ok(traverse(patterns));
7353
+ }
7354
+ //#endregion
7355
+ //#region src/parse/meta/or-parser.ts
7356
+ /**
7357
+ * Copyright © 2023-2026 Blockchain Commons, LLC
7358
+ * Copyright © 2025-2026 Parity Technologies
7359
+ *
7360
+ * Or parser — port of `bc-envelope-pattern-rust` `parse/meta/or_parser.rs`.
7361
+ *
7362
+ * @module envelope-pattern/parse/meta/or-parser
7363
+ */
7364
+ function parseOr(lexer) {
7365
+ const patterns = [];
7366
+ const first = parseTraverse(lexer);
7367
+ if (!first.ok) return first;
7368
+ patterns.push(first.value);
7369
+ while (true) {
7370
+ if (lexer.peekToken()?.token.type !== "Or") break;
7371
+ lexer.next();
7372
+ const nextExpr = parseTraverse(lexer);
7373
+ if (!nextExpr.ok) return nextExpr;
7374
+ patterns.push(nextExpr.value);
7375
+ }
7376
+ if (patterns.length === 1) return ok(patterns[0]);
7377
+ return ok(or(patterns));
7378
+ }
7379
+ //#endregion
7380
+ //#region src/parse/index.ts
7381
+ /**
7382
+ * Copyright © 2023-2026 Blockchain Commons, LLC
7383
+ * Copyright © 2025-2026 Parity Technologies
7384
+ *
7385
+ *
7386
+ * @bcts/envelope-pattern - Parser entry point
7387
+ *
7388
+ * This is a 1:1 TypeScript port of bc-envelope-pattern-rust parse/mod.rs.
7389
+ *
7390
+ * Recursive-descent parser for the Gordian Envelope pattern syntax. The
7391
+ * parsing rules live under `parse/leaf/`, `parse/meta/`, and
7392
+ * `parse/structure/`, mirroring the Rust crate's module layout.
7393
+ *
7394
+ * @module envelope-pattern/parse
7395
+ */
7396
+ /**
7397
+ * Parse a pattern expression string into a Pattern.
7398
+ *
7399
+ * Mirrors Rust `Pattern::parse`: tries envelope-pattern parsing first;
7400
+ * on failure falls back to dcbor-pattern parsing and converts the
7401
+ * result into an envelope pattern via the
7402
+ * `dcbor_integration::convert_dcbor_pattern_to_envelope_pattern` bridge.
7403
+ */
7404
+ function parse(input) {
7405
+ const lexer = new Lexer(input);
7406
+ const result = parseOr(lexer);
7407
+ if (!result.ok) {
7408
+ const dcborResult = parse$1(input);
7409
+ if (dcborResult.ok) return convertDcborPatternToEnvelopePattern(dcborResult.value);
7410
+ return result;
7411
+ }
7412
+ const next = lexer.next();
7413
+ if (next !== void 0) return err(extraData(next.span));
7414
+ return result;
7415
+ }
7416
+ /**
7417
+ * Parse a pattern, allowing extra data after the pattern.
7418
+ *
7419
+ * Returns the parsed pattern and the byte offset at which parsing
7420
+ * stopped, mirroring `Pattern::parse_partial` in spirit.
7421
+ */
7422
+ function parsePartial(input) {
7423
+ const lexer = new Lexer(input);
7424
+ const result = parseOr(lexer);
7425
+ if (!result.ok) return result;
7426
+ return ok([result.value, lexer.position]);
7427
+ }
7428
+ //#endregion
6904
7429
  //#region src/index.ts
6905
7430
  /**
6906
7431
  * Package version.
6907
7432
  */
6908
7433
  const VERSION = "1.0.0-alpha.11";
6909
7434
  //#endregion
6910
- export { AndPattern, AnyPattern, ArrayPattern, AssertionsPattern, BoolPattern, ByteStringPattern, CBORPattern, CapturePattern, DatePattern, DigestPattern, FormatPathsOptsBuilder, GroupPattern, Interval, KnownValuePattern, LeafStructurePattern, Lexer, MapPattern, MatcherDefaults, NodePattern, NotPattern, NullPattern, NumberPattern, ObjectPattern, ObscuredPattern, OrPattern, PredicatePattern, Quantifier, Reluctance, SearchPattern, SubjectPattern, TaggedPattern, TextPattern, TraversePattern, VERSION, WrappedPattern, and, any, anyArray, anyAssertion, anyBool, anyByteString, anyCbor, anyDate, anyKnownValue, anyMap, anyNode, anyNumber, anyObject, anyPredicate, anySubject, anyTag, anyText, assertionWithObject, assertionWithPredicate, axisChildren, bool, byteString, capture, cborPattern, cborValue, compile, compileAsAtomic, compressed, convertDcborPatternToEnvelopePattern, date, dateEarliest, dateLatest, dateRange, dateRegex, dcborPatternError, defaultFormatPathsOpts, defaultPathElementFormat, digest, digestPrefix, digestURFormat, dispatchCompile, dispatchIsComplex, dispatchPaths, dispatchPathsWithCaptures, dispatchPatternToString, elided, emptyInput, encrypted, envelopeSummary, envelopeURFormat, err, expectedCloseBracket, expectedCloseParen, expectedOpenBracket, expectedOpenParen, expectedPattern, extraData, formatError, formatPath, formatPathOpt, formatPaths, formatPathsOpt, formatPathsOpts, formatPathsWithCaptures, formatPathsWithCapturesOpt, group, invalidCaptureGroupName, invalidDateFormat, invalidHexString, invalidNumberFormat, invalidPattern, invalidRange, invalidRegex, invalidUr, isErr, isOk, knownValue, leaf, leafArray, leafBool, leafByteString, leafCbor, leafDate, leafKnownValue, leafMap, leafNull, leafNumber, leafPatternCompile, leafPatternIsComplex, leafPatternPaths, leafPatternPathsWithCaptures, leafPatternToString, leafTag, leafText, map, matchPattern, metaAnd, metaAny, metaCapture, metaGroup, metaNot, metaOr, metaPatternCollectCaptureNames, metaPatternCompile, metaPatternIsComplex, metaPatternPathsWithCaptures, metaPatternToString, metaSearch, metaTraverse, notMatching, nullPattern, number, numberGreaterThan, numberLessThan, numberRange, object, obscured, ok, or, parse, parsePartial, patternCollectCaptureNames, patternCompile, patternIsComplex, patternLeaf, patternMatches, patternMeta, patternPaths, patternPathsWithCaptures, patternStructure, patternToString, predicate, registerAndPatternFactory, registerAnyPatternFactory, registerArrayPatternFactory, registerAssertionsPatternFactory, registerBoolPatternFactory, registerByteStringPatternFactory, registerCBORPatternFactory, registerCapturePatternFactory, registerDatePatternFactory, registerDigestPatternFactory, registerGroupPatternFactory, registerKnownValuePatternFactory, registerLeafStructurePatternFactory, registerMapPatternFactory, registerNodePatternFactory, registerNotPatternFactory, registerNullPatternFactory, registerNumberPatternFactory, registerObjectPatternFactory, registerObscuredPatternFactory, registerOrPatternFactory, registerPatternDispatchFns, registerPatternMatchFn, registerPredicatePatternFactory, registerSearchPatternFactory, registerSubjectPatternFactory, registerTaggedPatternFactory, registerTextPatternFactory, registerTraversePatternFactory, registerVMPatternFunctions, registerWrappedPatternDispatch, registerWrappedPatternFactory, repeat, run, search, structureAssertions, structureDigest, structureLeaf, structureNode, structureObject, structureObscured, structurePatternCompile, structurePatternIsComplex, structurePatternPaths, structurePatternPathsWithCaptures, structurePatternToString, structurePredicate, structureSubject, structureWrapped, subject, summaryFormat, tagged, text, textRegex, traverse, unexpectedEndOfInput, unexpectedToken, unit, unknown, unmatchedBraces, unmatchedParentheses, unrecognizedToken, unterminatedRegex, unwrap, unwrapEnvelope, unwrapMatching, unwrapOr, wrapped };
7435
+ export { AndPattern, AnyPattern, ArrayPattern, AssertionsPattern, BoolPattern, ByteStringPattern, CBORPattern, CapturePattern, DatePattern, DigestPattern, FormatPathsOptsBuilder, GroupPattern, Interval, KnownValuePattern, LeafStructurePattern, Lexer, MapPattern, MatcherDefaults, NodePattern, NotPattern, NullPattern, NumberPattern, ObjectPattern, ObscuredPattern, OrPattern, PredicatePattern, Quantifier, Reluctance, SearchPattern, SubjectPattern, TaggedPattern, TextPattern, TraversePattern, VERSION, WrappedPattern, and, any, anyArray, anyAssertion, anyBool, anyByteString, anyCbor, anyDate, anyKnownValue, anyMap, anyNode, anyNumber, anyObject, anyPredicate, anySubject, anyTag, anyText, assertionWithObject, assertionWithPredicate, axisChildren, bool, byteString, capture, cborPattern, cborValue, compile, compileAsAtomic, compressed, convertDcborPatternToEnvelopePattern, date, dateEarliest, dateLatest, dateRange, dateRegex, dcborPatternError, defaultFormatPathsOpts, defaultPathElementFormat, digest, digestPrefix, digestURFormat, dispatchCompile, dispatchIsComplex, dispatchPaths, dispatchPathsWithCaptures, dispatchPatternToString, elided, emptyInput, encrypted, envelopeSummary, envelopeURFormat, err, expectedCloseBracket, expectedCloseParen, expectedOpenBracket, expectedOpenParen, expectedPattern, extraData, formatError, formatPath, formatPathOpt, formatPaths, formatPathsOpt, formatPathsOpts, formatPathsWithCaptures, formatPathsWithCapturesOpt, group, invalidCaptureGroupName, invalidDateFormat, invalidHexString, invalidNumberFormat, invalidPattern, invalidRange, invalidRegex, invalidUr, isErr, isOk, knownValue, leaf, leafArray, leafBool, leafByteString, leafCbor, leafDate, leafKnownValue, leafMap, leafNull, leafNumber, leafPatternCompile, leafPatternIsComplex, leafPatternPaths, leafPatternPathsWithCaptures, leafPatternToString, leafTag, leafText, map, matchPattern, metaAnd, metaAny, metaCapture, metaGroup, metaNot, metaOr, metaPatternCollectCaptureNames, metaPatternCompile, metaPatternIsComplex, metaPatternPathsWithCaptures, metaPatternToString, metaSearch, metaTraverse, notMatching, nullPattern, number, numberGreaterThan, numberLessThan, numberRange, object, obscured, ok, or, parse, parsePartial, patternCollectCaptureNames, patternCompile, patternIsComplex, patternLeaf, patternMatches, patternMeta, patternPaths, patternPathsWithCaptures, patternStructure, patternToString, predicate, registerAndPatternFactory, registerAnyPatternFactory, registerArrayPatternFactory, registerAssertionsPatternFactory, registerAssertionsPatternToStringDispatch, registerBoolPatternFactory, registerByteStringPatternFactory, registerCBORPatternFactory, registerCapturePatternFactory, registerDatePatternFactory, registerDigestPatternFactory, registerGroupPatternFactory, registerKnownValuePatternFactory, registerLeafStructurePatternFactory, registerMapPatternFactory, registerNodePatternFactory, registerNotPatternFactory, registerNullPatternFactory, registerNumberPatternFactory, registerObjectPatternFactory, registerObscuredPatternFactory, registerOrPatternFactory, registerPatternDispatchFns, registerPatternMatchFn, registerPredicatePatternFactory, registerSearchPatternFactory, registerSubjectPatternDispatch, registerSubjectPatternFactory, registerTaggedPatternFactory, registerTextPatternFactory, registerTraversePatternFactory, registerVMPatternFunctions, registerWrappedPatternAny, registerWrappedPatternDispatch, registerWrappedPatternFactory, repeat, run, search, structureAssertions, structureDigest, structureLeaf, structureNode, structureObject, structureObscured, structurePatternCompile, structurePatternIsComplex, structurePatternPaths, structurePatternPathsWithCaptures, structurePatternToString, structurePredicate, structureSubject, structureWrapped, subject, summaryFormat, tagged, text, textRegex, traverse, unexpectedEndOfInput, unexpectedToken, unit, unknown, unmatchedBraces, unmatchedParentheses, unrecognizedToken, unterminatedRegex, unwrap, unwrapEnvelope, unwrapMatching, unwrapOr, wrapped };
6911
7436
 
6912
7437
  //# sourceMappingURL=index.mjs.map