@suss/ir-core 0.22.1 → 0.22.3

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.
@@ -470,6 +470,203 @@ function statesAnOrigin(text) {
470
470
  return SCHEME_ORIGIN.test(text) || PROTOCOL_RELATIVE_ORIGIN.test(text);
471
471
  }
472
472
 
473
+ // src/semantics/pathPattern.ts
474
+ var HOLE_RANGE_SUFFIX = {
475
+ one: "",
476
+ optional: "?",
477
+ many: "+",
478
+ any: "*"
479
+ };
480
+ function rangedHole(name, range) {
481
+ return patternHole(`${name}${HOLE_RANGE_SUFFIX[range]}`);
482
+ }
483
+ var UNSPELLABLE_OPTION = /[()|?#{}]/;
484
+ function setPiece(options) {
485
+ if (options.some((option) => UNSPELLABLE_OPTION.test(option))) {
486
+ return null;
487
+ }
488
+ return `(${options.join("|")})`;
489
+ }
490
+ var ONE = { kind: "one" };
491
+ var OPTIONAL = { kind: "optional" };
492
+ var STAR = { kind: "star" };
493
+ var HOLE_SEGMENT = /^\{[^{}]*?([?+*]?)\}$/;
494
+ var SET_PIECE = /\(([^()]*)\)/;
495
+ var ALTERNATIVE_CAP = 64;
496
+ function alternativesOf(path) {
497
+ let alternatives = [path];
498
+ for (; ; ) {
499
+ const next = [];
500
+ let expanded = false;
501
+ for (const alternative of alternatives) {
502
+ const set = SET_PIECE.exec(alternative);
503
+ if (set === null || set.index === void 0) {
504
+ next.push(alternative);
505
+ continue;
506
+ }
507
+ expanded = true;
508
+ const head = alternative.slice(0, set.index);
509
+ const tail = alternative.slice(set.index + set[0].length);
510
+ for (const option of (set[1] ?? "").split("|")) {
511
+ next.push(head + option + tail);
512
+ }
513
+ }
514
+ if (!expanded) {
515
+ return alternatives;
516
+ }
517
+ if (next.length > ALTERNATIVE_CAP) {
518
+ return [path.replace(new RegExp(SET_PIECE, "g"), "{value}")];
519
+ }
520
+ alternatives = next;
521
+ }
522
+ }
523
+ var HOLE_RANGE_ITEMS = {
524
+ "": [ONE],
525
+ "?": [OPTIONAL],
526
+ "+": [ONE, STAR],
527
+ "*": [STAR]
528
+ };
529
+ function escapedForRegex(text) {
530
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
531
+ }
532
+ function shapedItem(segment) {
533
+ const source = segment.split(/(\{[^}]*\}|\*)/g).map((part) => {
534
+ if (part === "*") {
535
+ return ".*";
536
+ }
537
+ if (part.startsWith("{")) {
538
+ return "[^/]+";
539
+ }
540
+ return escapedForRegex(part);
541
+ }).join("");
542
+ return {
543
+ kind: "shaped",
544
+ shape: segment.replace(/\{[^}]*\}/g, "{}"),
545
+ test: new RegExp(`^${source}$`)
546
+ };
547
+ }
548
+ function itemsOf(segment) {
549
+ if (segment === "*") {
550
+ return [STAR];
551
+ }
552
+ const hole = HOLE_SEGMENT.exec(segment);
553
+ if (hole !== null) {
554
+ return HOLE_RANGE_ITEMS[hole[1] ?? ""] ?? [ONE];
555
+ }
556
+ if (segment.includes("{") || segment.includes("*")) {
557
+ return [shapedItem(segment)];
558
+ }
559
+ return [{ kind: "text", text: segment }];
560
+ }
561
+ function segmentsOf(alternative) {
562
+ const trimmed = alternative.startsWith("/") ? alternative.slice(1) : alternative;
563
+ return trimmed === "" ? [] : trimmed.split("/");
564
+ }
565
+ function patternOf(path) {
566
+ return alternativesOf(path).map(
567
+ (alternative) => segmentsOf(alternative).flatMap(itemsOf)
568
+ );
569
+ }
570
+ function literalItemsOf(path) {
571
+ return segmentsOf(path).map((text) => ({ kind: "text", text }));
572
+ }
573
+ function absorbsAnything(item) {
574
+ return item.kind === "one" || item.kind === "optional" || item.kind === "star";
575
+ }
576
+ function meetOnOneSegment(a, b) {
577
+ if (absorbsAnything(a) || absorbsAnything(b)) {
578
+ return true;
579
+ }
580
+ if (a.kind === "text" && b.kind === "text") {
581
+ return a.text === b.text;
582
+ }
583
+ if (a.kind === "text" && b.kind === "shaped") {
584
+ return b.test.test(a.text);
585
+ }
586
+ if (a.kind === "shaped" && b.kind === "text") {
587
+ return a.test.test(b.text);
588
+ }
589
+ return a.kind === "shaped" && b.kind === "shaped" && a.shape === b.shape;
590
+ }
591
+ function skippable(item) {
592
+ return item.kind === "optional" || item.kind === "star";
593
+ }
594
+ function itemsMeet(a, b) {
595
+ const width = b.length + 1;
596
+ const seen = new Uint8Array((a.length + 1) * width);
597
+ const queue = [0];
598
+ seen[0] = 1;
599
+ const visit = (i, j) => {
600
+ const at = i * width + j;
601
+ if (seen[at] === 0) {
602
+ seen[at] = 1;
603
+ queue.push(at);
604
+ }
605
+ };
606
+ while (queue.length > 0) {
607
+ const at = queue.pop();
608
+ const i = Math.floor(at / width);
609
+ const j = at % width;
610
+ if (i === a.length && j === b.length) {
611
+ return true;
612
+ }
613
+ const left = a[i];
614
+ const right = b[j];
615
+ if (left !== void 0 && skippable(left)) {
616
+ visit(i + 1, j);
617
+ }
618
+ if (right !== void 0 && skippable(right)) {
619
+ visit(i, j + 1);
620
+ }
621
+ if (left !== void 0 && right !== void 0) {
622
+ if (meetOnOneSegment(left, right)) {
623
+ visit(
624
+ left.kind === "star" ? i : i + 1,
625
+ right.kind === "star" ? j : j + 1
626
+ );
627
+ }
628
+ }
629
+ }
630
+ return false;
631
+ }
632
+ function pathsMeet(a, b) {
633
+ const left = patternOf(a);
634
+ const right = patternOf(b);
635
+ return left.some((one) => right.some((other) => itemsMeet(one, other)));
636
+ }
637
+ function patternAdmits(declared, request) {
638
+ const literal = literalItemsOf(request);
639
+ return patternOf(declared).some((items) => itemsMeet(items, literal));
640
+ }
641
+ function pathSpansShapes(path) {
642
+ return /\{[^{}]*[?+*]\}|\(|(?:^|\/)\*(?:\/|$)/.test(path);
643
+ }
644
+ function countOf(items, kinds) {
645
+ return items.filter((item) => kinds.includes(item.kind)).length;
646
+ }
647
+ function pathSpecificity(path) {
648
+ const alternatives = patternOf(path);
649
+ const ranks = alternatives.map((items) => [
650
+ countOf(items, ["text"]),
651
+ countOf(items, ["shaped"]),
652
+ -countOf(items, ["optional", "star"])
653
+ ]);
654
+ const loosest = ranks.reduce(
655
+ (low, rank) => compareRanks(rank, low) < 0 ? rank : low
656
+ );
657
+ return [...loosest, 1 - alternatives.length];
658
+ }
659
+ function compareRanks(a, b) {
660
+ const length = Math.max(a.length, b.length);
661
+ for (let index = 0; index < length; index += 1) {
662
+ const difference = (a[index] ?? 0) - (b[index] ?? 0);
663
+ if (difference !== 0) {
664
+ return difference;
665
+ }
666
+ }
667
+ return 0;
668
+ }
669
+
473
670
  // src/semantics/rest.ts
474
671
  var RestSemanticsSchema = z6.object({
475
672
  name: z6.literal("rest"),
@@ -495,7 +692,7 @@ function baseUrlReference(semantics) {
495
692
  return label === void 0 ? null : referenceFromName(patternHole(label));
496
693
  }
497
694
  function normalizePath(path) {
498
- let normalized = path.replace(/:([a-zA-Z_]\w*)/g, "{$1}");
695
+ let normalized = path.replace(/:([a-zA-Z_]\w*)([?+*]?)/g, "{$1$2}");
499
696
  if (normalized.length > 1 && normalized.endsWith("/")) {
500
697
  normalized = normalized.slice(0, -1);
501
698
  }
@@ -506,7 +703,7 @@ function normalizePath(path) {
506
703
  return normalized;
507
704
  }
508
705
  function pathShape(path) {
509
- return normalizePath(path).replace(/\{[^}]*\}/g, "{}");
706
+ return normalizePath(path).replace(/\{[^{}]*?([?+*]?)\}/g, "{$1}");
510
707
  }
511
708
  function methodsAgree(a, b) {
512
709
  if (a === null || b === null) {
@@ -514,22 +711,11 @@ function methodsAgree(a, b) {
514
711
  }
515
712
  return a === b || a === "*" || b === "*";
516
713
  }
517
- function routePathRegex(pattern) {
518
- const source = pattern.split(/(\{[^}]+\}|\*)/g).map((part) => {
519
- if (part === "*") {
520
- return ".*";
521
- }
522
- if (part.startsWith("{") && part.endsWith("}")) {
523
- return "[^/]+";
524
- }
525
- return part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
526
- }).join("");
527
- return new RegExp(`^${source}$`);
528
- }
529
714
  function routePathAdmits(declaredPath, requestPath) {
530
- return routePathRegex(normalizePath(declaredPath)).test(
531
- normalizePath(requestPath)
532
- );
715
+ return patternAdmits(normalizePath(declaredPath), normalizePath(requestPath));
716
+ }
717
+ function routePathsMeet(a, b) {
718
+ return pathsMeet(normalizePath(a), normalizePath(b));
533
719
  }
534
720
  var restSemantics = defineBoundarySemantics({
535
721
  name: "rest",
@@ -574,6 +760,15 @@ var restSemantics = defineBoundarySemantics({
574
760
  sidesAgree(a, b) {
575
761
  return methodsAgree(a.method, b.method);
576
762
  },
763
+ spansBuckets(semantics) {
764
+ return semantics.path !== null && pathSpansShapes(normalizePath(semantics.path));
765
+ },
766
+ bucketsMeet(a, b) {
767
+ return a.path !== null && b.path !== null && routePathsMeet(a.path, b.path);
768
+ },
769
+ bucketRank(semantics) {
770
+ return semantics.path === null ? [] : pathSpecificity(normalizePath(semantics.path));
771
+ },
577
772
  /**
578
773
  * What the identity key says, with a missing half still readable:
579
774
  * ANY when no method was stated, and ? when no path was. Null when
@@ -1049,11 +1244,15 @@ export {
1049
1244
  referenceFromName,
1050
1245
  pathAfterOrigin,
1051
1246
  statesAnOrigin,
1247
+ rangedHole,
1248
+ setPiece,
1249
+ compareRanks,
1052
1250
  RestSemanticsSchema,
1053
1251
  normalizePath,
1054
1252
  pathShape,
1055
1253
  methodsAgree,
1056
1254
  routePathAdmits,
1255
+ routePathsMeet,
1057
1256
  DeployableUnitSchema,
1058
1257
  ecsContainerInstanceName,
1059
1258
  RuntimeConfigSemanticsSchema,
package/dist/index.cjs CHANGED
@@ -51,11 +51,14 @@ __export(index_exports, {
51
51
  boundaryKey: () => boundaryKey,
52
52
  boundaryLabel: () => boundaryLabel,
53
53
  boundaryNameString: () => boundaryNameString,
54
+ bucketRank: () => bucketRank,
55
+ bucketsMeet: () => bucketsMeet,
54
56
  busIdentityKey: () => busIdentityKey,
55
57
  busesAgree: () => busesAgree,
56
58
  canPair: () => canPair,
57
59
  channelsPair: () => channelsPair,
58
60
  codeScopePath: () => codeScopePath,
61
+ compareRanks: () => compareRanks,
59
62
  countsForThreshold: () => countsForThreshold,
60
63
  dispatchByType: () => dispatchByType,
61
64
  displayLabel: () => displayLabel,
@@ -93,6 +96,7 @@ __export(index_exports, {
93
96
  pathAfterOrigin: () => pathAfterOrigin,
94
97
  pathShape: () => pathShape,
95
98
  patternHole: () => patternHole,
99
+ rangedHole: () => rangedHole,
96
100
  referenceFromName: () => referenceFromName,
97
101
  referenceName: () => referenceName,
98
102
  referenceOf: () => referenceOf,
@@ -100,11 +104,14 @@ __export(index_exports, {
100
104
  resourceNameIn: () => resourceNameIn,
101
105
  restBinding: () => restBinding,
102
106
  routePathAdmits: () => routePathAdmits,
107
+ routePathsMeet: () => routePathsMeet,
103
108
  ruleBoundaryMatchesKey: () => ruleBoundaryMatchesKey,
104
109
  runtimeConfigBinding: () => runtimeConfigBinding,
105
110
  semanticsAgree: () => semanticsAgree,
106
111
  semconvAttributes: () => semconvAttributes,
107
112
  servesRequest: () => servesRequest,
113
+ setPiece: () => setPiece,
114
+ spansBuckets: () => spansBuckets,
108
115
  spellingTokens: () => spellingTokens,
109
116
  statesAnOrigin: () => statesAnOrigin,
110
117
  storageBinding: () => storageBinding,
@@ -592,6 +599,203 @@ function statesAnOrigin(text) {
592
599
  return SCHEME_ORIGIN.test(text) || PROTOCOL_RELATIVE_ORIGIN.test(text);
593
600
  }
594
601
 
602
+ // src/semantics/pathPattern.ts
603
+ var HOLE_RANGE_SUFFIX = {
604
+ one: "",
605
+ optional: "?",
606
+ many: "+",
607
+ any: "*"
608
+ };
609
+ function rangedHole(name, range) {
610
+ return patternHole(`${name}${HOLE_RANGE_SUFFIX[range]}`);
611
+ }
612
+ var UNSPELLABLE_OPTION = /[()|?#{}]/;
613
+ function setPiece(options) {
614
+ if (options.some((option) => UNSPELLABLE_OPTION.test(option))) {
615
+ return null;
616
+ }
617
+ return `(${options.join("|")})`;
618
+ }
619
+ var ONE = { kind: "one" };
620
+ var OPTIONAL = { kind: "optional" };
621
+ var STAR = { kind: "star" };
622
+ var HOLE_SEGMENT = /^\{[^{}]*?([?+*]?)\}$/;
623
+ var SET_PIECE = /\(([^()]*)\)/;
624
+ var ALTERNATIVE_CAP = 64;
625
+ function alternativesOf(path) {
626
+ let alternatives = [path];
627
+ for (; ; ) {
628
+ const next = [];
629
+ let expanded = false;
630
+ for (const alternative of alternatives) {
631
+ const set = SET_PIECE.exec(alternative);
632
+ if (set === null || set.index === void 0) {
633
+ next.push(alternative);
634
+ continue;
635
+ }
636
+ expanded = true;
637
+ const head = alternative.slice(0, set.index);
638
+ const tail = alternative.slice(set.index + set[0].length);
639
+ for (const option of (set[1] ?? "").split("|")) {
640
+ next.push(head + option + tail);
641
+ }
642
+ }
643
+ if (!expanded) {
644
+ return alternatives;
645
+ }
646
+ if (next.length > ALTERNATIVE_CAP) {
647
+ return [path.replace(new RegExp(SET_PIECE, "g"), "{value}")];
648
+ }
649
+ alternatives = next;
650
+ }
651
+ }
652
+ var HOLE_RANGE_ITEMS = {
653
+ "": [ONE],
654
+ "?": [OPTIONAL],
655
+ "+": [ONE, STAR],
656
+ "*": [STAR]
657
+ };
658
+ function escapedForRegex(text) {
659
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
660
+ }
661
+ function shapedItem(segment) {
662
+ const source = segment.split(/(\{[^}]*\}|\*)/g).map((part) => {
663
+ if (part === "*") {
664
+ return ".*";
665
+ }
666
+ if (part.startsWith("{")) {
667
+ return "[^/]+";
668
+ }
669
+ return escapedForRegex(part);
670
+ }).join("");
671
+ return {
672
+ kind: "shaped",
673
+ shape: segment.replace(/\{[^}]*\}/g, "{}"),
674
+ test: new RegExp(`^${source}$`)
675
+ };
676
+ }
677
+ function itemsOf(segment) {
678
+ if (segment === "*") {
679
+ return [STAR];
680
+ }
681
+ const hole = HOLE_SEGMENT.exec(segment);
682
+ if (hole !== null) {
683
+ return HOLE_RANGE_ITEMS[hole[1] ?? ""] ?? [ONE];
684
+ }
685
+ if (segment.includes("{") || segment.includes("*")) {
686
+ return [shapedItem(segment)];
687
+ }
688
+ return [{ kind: "text", text: segment }];
689
+ }
690
+ function segmentsOf(alternative) {
691
+ const trimmed = alternative.startsWith("/") ? alternative.slice(1) : alternative;
692
+ return trimmed === "" ? [] : trimmed.split("/");
693
+ }
694
+ function patternOf(path) {
695
+ return alternativesOf(path).map(
696
+ (alternative) => segmentsOf(alternative).flatMap(itemsOf)
697
+ );
698
+ }
699
+ function literalItemsOf(path) {
700
+ return segmentsOf(path).map((text) => ({ kind: "text", text }));
701
+ }
702
+ function absorbsAnything(item) {
703
+ return item.kind === "one" || item.kind === "optional" || item.kind === "star";
704
+ }
705
+ function meetOnOneSegment(a, b) {
706
+ if (absorbsAnything(a) || absorbsAnything(b)) {
707
+ return true;
708
+ }
709
+ if (a.kind === "text" && b.kind === "text") {
710
+ return a.text === b.text;
711
+ }
712
+ if (a.kind === "text" && b.kind === "shaped") {
713
+ return b.test.test(a.text);
714
+ }
715
+ if (a.kind === "shaped" && b.kind === "text") {
716
+ return a.test.test(b.text);
717
+ }
718
+ return a.kind === "shaped" && b.kind === "shaped" && a.shape === b.shape;
719
+ }
720
+ function skippable(item) {
721
+ return item.kind === "optional" || item.kind === "star";
722
+ }
723
+ function itemsMeet(a, b) {
724
+ const width = b.length + 1;
725
+ const seen = new Uint8Array((a.length + 1) * width);
726
+ const queue = [0];
727
+ seen[0] = 1;
728
+ const visit = (i, j) => {
729
+ const at = i * width + j;
730
+ if (seen[at] === 0) {
731
+ seen[at] = 1;
732
+ queue.push(at);
733
+ }
734
+ };
735
+ while (queue.length > 0) {
736
+ const at = queue.pop();
737
+ const i = Math.floor(at / width);
738
+ const j = at % width;
739
+ if (i === a.length && j === b.length) {
740
+ return true;
741
+ }
742
+ const left = a[i];
743
+ const right = b[j];
744
+ if (left !== void 0 && skippable(left)) {
745
+ visit(i + 1, j);
746
+ }
747
+ if (right !== void 0 && skippable(right)) {
748
+ visit(i, j + 1);
749
+ }
750
+ if (left !== void 0 && right !== void 0) {
751
+ if (meetOnOneSegment(left, right)) {
752
+ visit(
753
+ left.kind === "star" ? i : i + 1,
754
+ right.kind === "star" ? j : j + 1
755
+ );
756
+ }
757
+ }
758
+ }
759
+ return false;
760
+ }
761
+ function pathsMeet(a, b) {
762
+ const left = patternOf(a);
763
+ const right = patternOf(b);
764
+ return left.some((one) => right.some((other) => itemsMeet(one, other)));
765
+ }
766
+ function patternAdmits(declared, request) {
767
+ const literal = literalItemsOf(request);
768
+ return patternOf(declared).some((items) => itemsMeet(items, literal));
769
+ }
770
+ function pathSpansShapes(path) {
771
+ return /\{[^{}]*[?+*]\}|\(|(?:^|\/)\*(?:\/|$)/.test(path);
772
+ }
773
+ function countOf(items, kinds) {
774
+ return items.filter((item) => kinds.includes(item.kind)).length;
775
+ }
776
+ function pathSpecificity(path) {
777
+ const alternatives = patternOf(path);
778
+ const ranks = alternatives.map((items) => [
779
+ countOf(items, ["text"]),
780
+ countOf(items, ["shaped"]),
781
+ -countOf(items, ["optional", "star"])
782
+ ]);
783
+ const loosest = ranks.reduce(
784
+ (low, rank) => compareRanks(rank, low) < 0 ? rank : low
785
+ );
786
+ return [...loosest, 1 - alternatives.length];
787
+ }
788
+ function compareRanks(a, b) {
789
+ const length = Math.max(a.length, b.length);
790
+ for (let index = 0; index < length; index += 1) {
791
+ const difference = (a[index] ?? 0) - (b[index] ?? 0);
792
+ if (difference !== 0) {
793
+ return difference;
794
+ }
795
+ }
796
+ return 0;
797
+ }
798
+
595
799
  // src/semantics/rest.ts
596
800
  var RestSemanticsSchema = import_zod6.z.object({
597
801
  name: import_zod6.z.literal("rest"),
@@ -617,7 +821,7 @@ function baseUrlReference(semantics) {
617
821
  return label === void 0 ? null : referenceFromName(patternHole(label));
618
822
  }
619
823
  function normalizePath(path) {
620
- let normalized = path.replace(/:([a-zA-Z_]\w*)/g, "{$1}");
824
+ let normalized = path.replace(/:([a-zA-Z_]\w*)([?+*]?)/g, "{$1$2}");
621
825
  if (normalized.length > 1 && normalized.endsWith("/")) {
622
826
  normalized = normalized.slice(0, -1);
623
827
  }
@@ -628,7 +832,7 @@ function normalizePath(path) {
628
832
  return normalized;
629
833
  }
630
834
  function pathShape(path) {
631
- return normalizePath(path).replace(/\{[^}]*\}/g, "{}");
835
+ return normalizePath(path).replace(/\{[^{}]*?([?+*]?)\}/g, "{$1}");
632
836
  }
633
837
  function methodsAgree(a, b) {
634
838
  if (a === null || b === null) {
@@ -636,22 +840,11 @@ function methodsAgree(a, b) {
636
840
  }
637
841
  return a === b || a === "*" || b === "*";
638
842
  }
639
- function routePathRegex(pattern) {
640
- const source = pattern.split(/(\{[^}]+\}|\*)/g).map((part) => {
641
- if (part === "*") {
642
- return ".*";
643
- }
644
- if (part.startsWith("{") && part.endsWith("}")) {
645
- return "[^/]+";
646
- }
647
- return part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
648
- }).join("");
649
- return new RegExp(`^${source}$`);
650
- }
651
843
  function routePathAdmits(declaredPath, requestPath) {
652
- return routePathRegex(normalizePath(declaredPath)).test(
653
- normalizePath(requestPath)
654
- );
844
+ return patternAdmits(normalizePath(declaredPath), normalizePath(requestPath));
845
+ }
846
+ function routePathsMeet(a, b) {
847
+ return pathsMeet(normalizePath(a), normalizePath(b));
655
848
  }
656
849
  var restSemantics = defineBoundarySemantics({
657
850
  name: "rest",
@@ -696,6 +889,15 @@ var restSemantics = defineBoundarySemantics({
696
889
  sidesAgree(a, b) {
697
890
  return methodsAgree(a.method, b.method);
698
891
  },
892
+ spansBuckets(semantics) {
893
+ return semantics.path !== null && pathSpansShapes(normalizePath(semantics.path));
894
+ },
895
+ bucketsMeet(a, b) {
896
+ return a.path !== null && b.path !== null && routePathsMeet(a.path, b.path);
897
+ },
898
+ bucketRank(semantics) {
899
+ return semantics.path === null ? [] : pathSpecificity(normalizePath(semantics.path));
900
+ },
699
901
  /**
700
902
  * What the identity key says, with a missing half still readable:
701
903
  * ANY when no method was stated, and ? when no path was. Null when
@@ -1199,6 +1401,19 @@ function semanticsAgree(a, b) {
1199
1401
  const agree = behaviorOf(a).sidesAgree;
1200
1402
  return agree === void 0 ? true : agree(a, b);
1201
1403
  }
1404
+ function spansBuckets(binding) {
1405
+ return behaviorOf(binding.semantics).spansBuckets?.(binding.semantics) ?? false;
1406
+ }
1407
+ function bucketsMeet(a, b) {
1408
+ if (a.semantics.name !== b.semantics.name) {
1409
+ return false;
1410
+ }
1411
+ const meet = behaviorOf(a.semantics).bucketsMeet;
1412
+ return meet !== void 0 && meet(a.semantics, b.semantics);
1413
+ }
1414
+ function bucketRank(binding) {
1415
+ return behaviorOf(binding.semantics).bucketRank?.(binding.semantics) ?? [];
1416
+ }
1202
1417
  function boundaryLabel(binding) {
1203
1418
  const behavior = behaviorOf(binding.semantics);
1204
1419
  return (behavior.displayLabel ?? behavior.identityKey)(binding.semantics);
@@ -1740,11 +1955,14 @@ function metricBinding(opts) {
1740
1955
  boundaryKey,
1741
1956
  boundaryLabel,
1742
1957
  boundaryNameString,
1958
+ bucketRank,
1959
+ bucketsMeet,
1743
1960
  busIdentityKey,
1744
1961
  busesAgree,
1745
1962
  canPair,
1746
1963
  channelsPair,
1747
1964
  codeScopePath,
1965
+ compareRanks,
1748
1966
  countsForThreshold,
1749
1967
  dispatchByType,
1750
1968
  displayLabel,
@@ -1782,6 +2000,7 @@ function metricBinding(opts) {
1782
2000
  pathAfterOrigin,
1783
2001
  pathShape,
1784
2002
  patternHole,
2003
+ rangedHole,
1785
2004
  referenceFromName,
1786
2005
  referenceName,
1787
2006
  referenceOf,
@@ -1789,11 +2008,14 @@ function metricBinding(opts) {
1789
2008
  resourceNameIn,
1790
2009
  restBinding,
1791
2010
  routePathAdmits,
2011
+ routePathsMeet,
1792
2012
  ruleBoundaryMatchesKey,
1793
2013
  runtimeConfigBinding,
1794
2014
  semanticsAgree,
1795
2015
  semconvAttributes,
1796
2016
  servesRequest,
2017
+ setPiece,
2018
+ spansBuckets,
1797
2019
  spellingTokens,
1798
2020
  statesAnOrigin,
1799
2021
  storageBinding,
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { T as TypeShape, M as MessageBusSemantics, D as DeployableUnit, S as Semantics, B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, d as SourceLocationSchema, e as MessageBusTechnology } from './schemas-Dn1AzzWd.cjs';
3
- export { f as DeployableUnitSchema, E as EVERY_FIELD, F as FunctionCallSemantics, g as FunctionCallSemanticsSchema, G as GraphqlOperationSemantics, h as GraphqlOperationSemanticsSchema, i as GraphqlResolverSemantics, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, R as RestSemantics, l as RestSemanticsSchema, m as RuntimeConfigSemantics, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, p as StorageSemantics, q as StorageSemanticsSchema, r as TypeShapeSchema, s as ecsContainerInstanceName, t as methodsAgree, u as normalizePath, v as pathShape, w as routePathAdmits, x as storageContainerLabel, y as storageLabel, z as typeDefinitionKey, A as withDefinitionsInlined } from './schemas-Dn1AzzWd.cjs';
2
+ import { T as TypeShape, M as MessageBusSemantics, D as DeployableUnit, S as Semantics, B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, d as SourceLocationSchema, e as MessageBusTechnology } from './schemas-BDB_vB6m.cjs';
3
+ export { f as DeployableUnitSchema, E as EVERY_FIELD, F as FunctionCallSemantics, g as FunctionCallSemanticsSchema, G as GraphqlOperationSemantics, h as GraphqlOperationSemanticsSchema, i as GraphqlResolverSemantics, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, R as RestSemantics, l as RestSemanticsSchema, m as RuntimeConfigSemantics, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, p as StorageSemantics, q as StorageSemanticsSchema, r as TypeShapeSchema, s as ecsContainerInstanceName, t as methodsAgree, u as normalizePath, v as pathShape, w as routePathAdmits, x as routePathsMeet, y as storageContainerLabel, z as storageLabel, A as typeDefinitionKey, H as withDefinitionsInlined } from './schemas-BDB_vB6m.cjs';
4
4
 
5
5
  /**
6
6
  * The boundary-name syntax, parsed and printed in one place.
@@ -248,6 +248,24 @@ interface BoundaryBehavior<S extends {
248
248
  * does not define it always agrees.
249
249
  */
250
250
  sidesAgree?(a: S, b: S): boolean;
251
+ /**
252
+ * Whether this boundary's bucket can meet buckets with other keys. A
253
+ * REST path with a hole that spans some number of segments has a key
254
+ * of its own and serves what several other keys serve, so the pairing
255
+ * pass compares it against every bucket on the other side with
256
+ * `bucketsMeet`. A variant that does not define it meets only its own
257
+ * key.
258
+ */
259
+ spansBuckets?(semantics: S): boolean;
260
+ /** Whether two buckets describe at least one boundary in common. */
261
+ bucketsMeet?(a: S, b: S): boolean;
262
+ /**
263
+ * How narrowly this bucket states what it serves, compared
264
+ * lexicographically. When a consumer meets more than one bucket, the
265
+ * one ranking highest is the one it reaches, and an even contest is
266
+ * reported rather than paired.
267
+ */
268
+ bucketRank?(semantics: S): readonly number[];
251
269
  /** The line a reader sees for this boundary. Defaults to `identityKey`. */
252
270
  displayLabel?(semantics: S): string | null;
253
271
  /**
@@ -484,6 +502,12 @@ declare function groundBinding(binding: BoundaryBinding, deployment: Deployment)
484
502
  declare function nameReference(binding: BoundaryBinding): Reference | null;
485
503
  declare function pairingKey(binding: BoundaryBinding): string | null;
486
504
  declare function semanticsAgree(a: Semantics, b: Semantics): boolean;
505
+ /** Whether the binding's bucket can meet buckets with other keys. */
506
+ declare function spansBuckets(binding: BoundaryBinding): boolean;
507
+ /** Whether two bindings' buckets describe a boundary in common. */
508
+ declare function bucketsMeet(a: BoundaryBinding, b: BoundaryBinding): boolean;
509
+ /** How narrowly the binding's bucket states what it serves; see `compareRanks`. */
510
+ declare function bucketRank(binding: BoundaryBinding): readonly number[];
487
511
  declare function boundaryLabel(binding: BoundaryBinding): string | null;
488
512
  declare function displayLabel(binding: BoundaryBinding): string;
489
513
  /**
@@ -671,6 +695,33 @@ declare const EffectRelationSchema: z.ZodEnum<{
671
695
  }>;
672
696
  type EffectRelation = z.infer<typeof EffectRelationSchema>;
673
697
 
698
+ /**
699
+ * pathPattern.ts: whether two route paths describe a request in common.
700
+ *
701
+ * A normalized path is text with holes in it. `{id}` is exactly one
702
+ * segment, `{tenant?}` is zero or one, `{rest+}` is one or more and
703
+ * `{rest*}` is zero or more, the modifiers Express puts on `:name`. A
704
+ * bare `*` segment is zero or more segments, Express 4's reading of a
705
+ * star. A set piece is written `(v1|v2)` and matches any one of its
706
+ * options, and an option can contain a slash.
707
+ *
708
+ * `pathsMeet` expands the sets into alternatives, splits each one into
709
+ * segments, and walks the two segment lists with a reachability table
710
+ * in which a hole absorbs as many segments as its range allows.
711
+ */
712
+ /** How many segments a hole takes, in the words the value domain uses. */
713
+ type HoleRange = "one" | "optional" | "many" | "any";
714
+ /** How a hole taking `range` segments is spelled in a path. */
715
+ declare function rangedHole(name: string, range: HoleRange): string;
716
+ /**
717
+ * How a piece that is one of several texts is spelled in a path, or
718
+ * null when an option would be read as something else, such as a set
719
+ * boundary or the start of a query.
720
+ */
721
+ declare function setPiece(options: readonly string[]): string | null;
722
+ /** Negative when `a` ranks below `b`, positive above, zero when equal. */
723
+ declare function compareRanks(a: readonly number[], b: readonly number[]): number;
724
+
674
725
  /**
675
726
  * The suppression pipeline, over the smallest finding both checkers share.
676
727
  *
@@ -957,4 +1008,4 @@ declare function metricBinding(opts: {
957
1008
  metricType: string | null;
958
1009
  }): BoundaryBinding;
959
1010
 
960
- export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundaryName, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, DeployableUnit, type Deployment, type DispatchTable, type EffectRelation, EffectRelationSchema, type FindingSuppression, type FnIdentityKey, type GqlIdentityKey, type MatchResult, MessageBusSemantics, MessageBusTechnology, type MetricIdentityKey, type MetricSemantics, MetricSemanticsSchema, NOTHING_DEPLOYED, type NamePart, type ParsedChannel, type Reference, type Relation, RelationSchema, Semantics, type SemconvAttribute, type SemconvMapping, type SourceLocation, SourceLocationSchema, type SuppressableSeverity, type SuppressibleFinding, type SuppressionFile, SuppressionFileSchema, type SuppressionRule, SuppressionRuleSchema, TypeShape, type UnitIdentityKey, type UnitInvocationSemantics, UnitInvocationSemanticsSchema, applySuppressionsToFindings, bindingIs, bindingTokens, bodyShapesMatch, boundaryKey, boundaryLabel, boundaryNameString, busIdentityKey, busesAgree, canPair, channelsPair, codeScopePath, countsForThreshold, dispatchByType, displayLabel, exchangesHttpResponses, fileInCodeScope, fixedTextLength, fnIdentityKey, formatChannel, functionCallBinding, gqlIdentityKey, graphqlOperationBinding, graphqlResolverBinding, groundBinding, groundedPairingKey, hasNameHole, isGraphqlOperationBinding, messageBusBinding, metricBinding, metricIdentityKey, namePatternFromSub, namePatternKey, nameReference, namesAgree, namesBoundary, namesBoundaryExactly, namesNothing, normalizeRuleBoundary, packageExportBinding, pairingKey, parseBoundaryName, parseChannel, pathAfterOrigin, patternHole, referenceFromName, referenceName, referenceOf, reportsUnpairedItself, resourceNameIn, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, semconvAttributes, servesRequest, spellingTokens, statesAnOrigin, storageBinding, unitIdentityKey, unitInvocationBinding, validateRule, withRewrittenPaths, withinScope };
1011
+ export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundaryName, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, DeployableUnit, type Deployment, type DispatchTable, type EffectRelation, EffectRelationSchema, type FindingSuppression, type FnIdentityKey, type GqlIdentityKey, type HoleRange, type MatchResult, MessageBusSemantics, MessageBusTechnology, type MetricIdentityKey, type MetricSemantics, MetricSemanticsSchema, NOTHING_DEPLOYED, type NamePart, type ParsedChannel, type Reference, type Relation, RelationSchema, Semantics, type SemconvAttribute, type SemconvMapping, type SourceLocation, SourceLocationSchema, type SuppressableSeverity, type SuppressibleFinding, type SuppressionFile, SuppressionFileSchema, type SuppressionRule, SuppressionRuleSchema, TypeShape, type UnitIdentityKey, type UnitInvocationSemantics, UnitInvocationSemanticsSchema, applySuppressionsToFindings, bindingIs, bindingTokens, bodyShapesMatch, boundaryKey, boundaryLabel, boundaryNameString, bucketRank, bucketsMeet, busIdentityKey, busesAgree, canPair, channelsPair, codeScopePath, compareRanks, countsForThreshold, dispatchByType, displayLabel, exchangesHttpResponses, fileInCodeScope, fixedTextLength, fnIdentityKey, formatChannel, functionCallBinding, gqlIdentityKey, graphqlOperationBinding, graphqlResolverBinding, groundBinding, groundedPairingKey, hasNameHole, isGraphqlOperationBinding, messageBusBinding, metricBinding, metricIdentityKey, namePatternFromSub, namePatternKey, nameReference, namesAgree, namesBoundary, namesBoundaryExactly, namesNothing, normalizeRuleBoundary, packageExportBinding, pairingKey, parseBoundaryName, parseChannel, pathAfterOrigin, patternHole, rangedHole, referenceFromName, referenceName, referenceOf, reportsUnpairedItself, resourceNameIn, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, semconvAttributes, servesRequest, setPiece, spansBuckets, spellingTokens, statesAnOrigin, storageBinding, unitIdentityKey, unitInvocationBinding, validateRule, withRewrittenPaths, withinScope };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { T as TypeShape, M as MessageBusSemantics, D as DeployableUnit, S as Semantics, B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, d as SourceLocationSchema, e as MessageBusTechnology } from './schemas-Dn1AzzWd.js';
3
- export { f as DeployableUnitSchema, E as EVERY_FIELD, F as FunctionCallSemantics, g as FunctionCallSemanticsSchema, G as GraphqlOperationSemantics, h as GraphqlOperationSemanticsSchema, i as GraphqlResolverSemantics, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, R as RestSemantics, l as RestSemanticsSchema, m as RuntimeConfigSemantics, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, p as StorageSemantics, q as StorageSemanticsSchema, r as TypeShapeSchema, s as ecsContainerInstanceName, t as methodsAgree, u as normalizePath, v as pathShape, w as routePathAdmits, x as storageContainerLabel, y as storageLabel, z as typeDefinitionKey, A as withDefinitionsInlined } from './schemas-Dn1AzzWd.js';
2
+ import { T as TypeShape, M as MessageBusSemantics, D as DeployableUnit, S as Semantics, B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, d as SourceLocationSchema, e as MessageBusTechnology } from './schemas-BDB_vB6m.js';
3
+ export { f as DeployableUnitSchema, E as EVERY_FIELD, F as FunctionCallSemantics, g as FunctionCallSemanticsSchema, G as GraphqlOperationSemantics, h as GraphqlOperationSemanticsSchema, i as GraphqlResolverSemantics, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, R as RestSemantics, l as RestSemanticsSchema, m as RuntimeConfigSemantics, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, p as StorageSemantics, q as StorageSemanticsSchema, r as TypeShapeSchema, s as ecsContainerInstanceName, t as methodsAgree, u as normalizePath, v as pathShape, w as routePathAdmits, x as routePathsMeet, y as storageContainerLabel, z as storageLabel, A as typeDefinitionKey, H as withDefinitionsInlined } from './schemas-BDB_vB6m.js';
4
4
 
5
5
  /**
6
6
  * The boundary-name syntax, parsed and printed in one place.
@@ -248,6 +248,24 @@ interface BoundaryBehavior<S extends {
248
248
  * does not define it always agrees.
249
249
  */
250
250
  sidesAgree?(a: S, b: S): boolean;
251
+ /**
252
+ * Whether this boundary's bucket can meet buckets with other keys. A
253
+ * REST path with a hole that spans some number of segments has a key
254
+ * of its own and serves what several other keys serve, so the pairing
255
+ * pass compares it against every bucket on the other side with
256
+ * `bucketsMeet`. A variant that does not define it meets only its own
257
+ * key.
258
+ */
259
+ spansBuckets?(semantics: S): boolean;
260
+ /** Whether two buckets describe at least one boundary in common. */
261
+ bucketsMeet?(a: S, b: S): boolean;
262
+ /**
263
+ * How narrowly this bucket states what it serves, compared
264
+ * lexicographically. When a consumer meets more than one bucket, the
265
+ * one ranking highest is the one it reaches, and an even contest is
266
+ * reported rather than paired.
267
+ */
268
+ bucketRank?(semantics: S): readonly number[];
251
269
  /** The line a reader sees for this boundary. Defaults to `identityKey`. */
252
270
  displayLabel?(semantics: S): string | null;
253
271
  /**
@@ -484,6 +502,12 @@ declare function groundBinding(binding: BoundaryBinding, deployment: Deployment)
484
502
  declare function nameReference(binding: BoundaryBinding): Reference | null;
485
503
  declare function pairingKey(binding: BoundaryBinding): string | null;
486
504
  declare function semanticsAgree(a: Semantics, b: Semantics): boolean;
505
+ /** Whether the binding's bucket can meet buckets with other keys. */
506
+ declare function spansBuckets(binding: BoundaryBinding): boolean;
507
+ /** Whether two bindings' buckets describe a boundary in common. */
508
+ declare function bucketsMeet(a: BoundaryBinding, b: BoundaryBinding): boolean;
509
+ /** How narrowly the binding's bucket states what it serves; see `compareRanks`. */
510
+ declare function bucketRank(binding: BoundaryBinding): readonly number[];
487
511
  declare function boundaryLabel(binding: BoundaryBinding): string | null;
488
512
  declare function displayLabel(binding: BoundaryBinding): string;
489
513
  /**
@@ -671,6 +695,33 @@ declare const EffectRelationSchema: z.ZodEnum<{
671
695
  }>;
672
696
  type EffectRelation = z.infer<typeof EffectRelationSchema>;
673
697
 
698
+ /**
699
+ * pathPattern.ts: whether two route paths describe a request in common.
700
+ *
701
+ * A normalized path is text with holes in it. `{id}` is exactly one
702
+ * segment, `{tenant?}` is zero or one, `{rest+}` is one or more and
703
+ * `{rest*}` is zero or more, the modifiers Express puts on `:name`. A
704
+ * bare `*` segment is zero or more segments, Express 4's reading of a
705
+ * star. A set piece is written `(v1|v2)` and matches any one of its
706
+ * options, and an option can contain a slash.
707
+ *
708
+ * `pathsMeet` expands the sets into alternatives, splits each one into
709
+ * segments, and walks the two segment lists with a reachability table
710
+ * in which a hole absorbs as many segments as its range allows.
711
+ */
712
+ /** How many segments a hole takes, in the words the value domain uses. */
713
+ type HoleRange = "one" | "optional" | "many" | "any";
714
+ /** How a hole taking `range` segments is spelled in a path. */
715
+ declare function rangedHole(name: string, range: HoleRange): string;
716
+ /**
717
+ * How a piece that is one of several texts is spelled in a path, or
718
+ * null when an option would be read as something else, such as a set
719
+ * boundary or the start of a query.
720
+ */
721
+ declare function setPiece(options: readonly string[]): string | null;
722
+ /** Negative when `a` ranks below `b`, positive above, zero when equal. */
723
+ declare function compareRanks(a: readonly number[], b: readonly number[]): number;
724
+
674
725
  /**
675
726
  * The suppression pipeline, over the smallest finding both checkers share.
676
727
  *
@@ -957,4 +1008,4 @@ declare function metricBinding(opts: {
957
1008
  metricType: string | null;
958
1009
  }): BoundaryBinding;
959
1010
 
960
- export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundaryName, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, DeployableUnit, type Deployment, type DispatchTable, type EffectRelation, EffectRelationSchema, type FindingSuppression, type FnIdentityKey, type GqlIdentityKey, type MatchResult, MessageBusSemantics, MessageBusTechnology, type MetricIdentityKey, type MetricSemantics, MetricSemanticsSchema, NOTHING_DEPLOYED, type NamePart, type ParsedChannel, type Reference, type Relation, RelationSchema, Semantics, type SemconvAttribute, type SemconvMapping, type SourceLocation, SourceLocationSchema, type SuppressableSeverity, type SuppressibleFinding, type SuppressionFile, SuppressionFileSchema, type SuppressionRule, SuppressionRuleSchema, TypeShape, type UnitIdentityKey, type UnitInvocationSemantics, UnitInvocationSemanticsSchema, applySuppressionsToFindings, bindingIs, bindingTokens, bodyShapesMatch, boundaryKey, boundaryLabel, boundaryNameString, busIdentityKey, busesAgree, canPair, channelsPair, codeScopePath, countsForThreshold, dispatchByType, displayLabel, exchangesHttpResponses, fileInCodeScope, fixedTextLength, fnIdentityKey, formatChannel, functionCallBinding, gqlIdentityKey, graphqlOperationBinding, graphqlResolverBinding, groundBinding, groundedPairingKey, hasNameHole, isGraphqlOperationBinding, messageBusBinding, metricBinding, metricIdentityKey, namePatternFromSub, namePatternKey, nameReference, namesAgree, namesBoundary, namesBoundaryExactly, namesNothing, normalizeRuleBoundary, packageExportBinding, pairingKey, parseBoundaryName, parseChannel, pathAfterOrigin, patternHole, referenceFromName, referenceName, referenceOf, reportsUnpairedItself, resourceNameIn, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, semconvAttributes, servesRequest, spellingTokens, statesAnOrigin, storageBinding, unitIdentityKey, unitInvocationBinding, validateRule, withRewrittenPaths, withinScope };
1011
+ export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundaryName, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, DeployableUnit, type Deployment, type DispatchTable, type EffectRelation, EffectRelationSchema, type FindingSuppression, type FnIdentityKey, type GqlIdentityKey, type HoleRange, type MatchResult, MessageBusSemantics, MessageBusTechnology, type MetricIdentityKey, type MetricSemantics, MetricSemanticsSchema, NOTHING_DEPLOYED, type NamePart, type ParsedChannel, type Reference, type Relation, RelationSchema, Semantics, type SemconvAttribute, type SemconvMapping, type SourceLocation, SourceLocationSchema, type SuppressableSeverity, type SuppressibleFinding, type SuppressionFile, SuppressionFileSchema, type SuppressionRule, SuppressionRuleSchema, TypeShape, type UnitIdentityKey, type UnitInvocationSemantics, UnitInvocationSemanticsSchema, applySuppressionsToFindings, bindingIs, bindingTokens, bodyShapesMatch, boundaryKey, boundaryLabel, boundaryNameString, bucketRank, bucketsMeet, busIdentityKey, busesAgree, canPair, channelsPair, codeScopePath, compareRanks, countsForThreshold, dispatchByType, displayLabel, exchangesHttpResponses, fileInCodeScope, fixedTextLength, fnIdentityKey, formatChannel, functionCallBinding, gqlIdentityKey, graphqlOperationBinding, graphqlResolverBinding, groundBinding, groundedPairingKey, hasNameHole, isGraphqlOperationBinding, messageBusBinding, metricBinding, metricIdentityKey, namePatternFromSub, namePatternKey, nameReference, namesAgree, namesBoundary, namesBoundaryExactly, namesNothing, normalizeRuleBoundary, packageExportBinding, pairingKey, parseBoundaryName, parseChannel, pathAfterOrigin, patternHole, rangedHole, referenceFromName, referenceName, referenceOf, reportsUnpairedItself, resourceNameIn, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, semconvAttributes, servesRequest, setPiece, spansBuckets, spellingTokens, statesAnOrigin, storageBinding, unitIdentityKey, unitInvocationBinding, validateRule, withRewrittenPaths, withinScope };
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ import {
24
24
  busIdentityKey,
25
25
  busesAgree,
26
26
  channelsPair,
27
+ compareRanks,
27
28
  dispatchByType,
28
29
  ecsContainerInstanceName,
29
30
  fixedTextLength,
@@ -43,18 +44,21 @@ import {
43
44
  pathAfterOrigin,
44
45
  pathShape,
45
46
  patternHole,
47
+ rangedHole,
46
48
  referenceFromName,
47
49
  referenceName,
48
50
  referenceOf,
49
51
  routePathAdmits,
52
+ routePathsMeet,
50
53
  semconvMappingOf,
54
+ setPiece,
51
55
  statesAnOrigin,
52
56
  storageContainerLabel,
53
57
  storageLabel,
54
58
  typeDefinitionKey,
55
59
  unitIdentityKey,
56
60
  withDefinitionsInlined
57
- } from "./chunk-PPQWK62O.js";
61
+ } from "./chunk-I4WQM6F5.js";
58
62
 
59
63
  // src/semconv.ts
60
64
  function semconvAttributes(binding) {
@@ -114,6 +118,19 @@ function semanticsAgree(a, b) {
114
118
  const agree = behaviorOf(a).sidesAgree;
115
119
  return agree === void 0 ? true : agree(a, b);
116
120
  }
121
+ function spansBuckets(binding) {
122
+ return behaviorOf(binding.semantics).spansBuckets?.(binding.semantics) ?? false;
123
+ }
124
+ function bucketsMeet(a, b) {
125
+ if (a.semantics.name !== b.semantics.name) {
126
+ return false;
127
+ }
128
+ const meet = behaviorOf(a.semantics).bucketsMeet;
129
+ return meet !== void 0 && meet(a.semantics, b.semantics);
130
+ }
131
+ function bucketRank(binding) {
132
+ return behaviorOf(binding.semantics).bucketRank?.(binding.semantics) ?? [];
133
+ }
117
134
  function boundaryLabel(binding) {
118
135
  const behavior = behaviorOf(binding.semantics);
119
136
  return (behavior.displayLabel ?? behavior.identityKey)(binding.semantics);
@@ -654,11 +671,14 @@ export {
654
671
  boundaryKey,
655
672
  boundaryLabel,
656
673
  boundaryNameString,
674
+ bucketRank,
675
+ bucketsMeet,
657
676
  busIdentityKey,
658
677
  busesAgree,
659
678
  canPair,
660
679
  channelsPair,
661
680
  codeScopePath,
681
+ compareRanks,
662
682
  countsForThreshold,
663
683
  dispatchByType,
664
684
  displayLabel,
@@ -696,6 +716,7 @@ export {
696
716
  pathAfterOrigin,
697
717
  pathShape,
698
718
  patternHole,
719
+ rangedHole,
699
720
  referenceFromName,
700
721
  referenceName,
701
722
  referenceOf,
@@ -703,11 +724,14 @@ export {
703
724
  resourceNameIn,
704
725
  restBinding,
705
726
  routePathAdmits,
727
+ routePathsMeet,
706
728
  ruleBoundaryMatchesKey,
707
729
  runtimeConfigBinding,
708
730
  semanticsAgree,
709
731
  semconvAttributes,
710
732
  servesRequest,
733
+ setPiece,
734
+ spansBuckets,
711
735
  spellingTokens,
712
736
  statesAnOrigin,
713
737
  storageBinding,
@@ -178,7 +178,8 @@ type RestSemantics = z.infer<typeof RestSemanticsSchema>;
178
178
  /**
179
179
  * Normalize a route path to a canonical form for matching.
180
180
  *
181
- * - Converts Express-style params (`:id`) to brace-style (`{id}`)
181
+ * - Converts Express-style params (`:id`) to brace-style (`{id}`), and
182
+ * keeps a range modifier (`:id?`, `:rest+`, `:rest*`) inside the braces
182
183
  * - Strips trailing slashes (except bare `/`)
183
184
  * - Lowercases the static segments (params stay case-sensitive)
184
185
  */
@@ -189,6 +190,8 @@ declare function normalizePath(path: string): string;
189
190
  * requests each one serves, and what deciding whether two sides
190
191
  * describe one endpoint rests on. The name a parameter is written
191
192
  * under is worth keeping in a report and worth nothing in a comparison.
193
+ * A parameter's range stays, since `{tenant?}` serves a different set
194
+ * of requests from `{tenant}`.
192
195
  */
193
196
  declare function pathShape(path: string): string;
194
197
  /**
@@ -201,8 +204,15 @@ declare function pathShape(path: string): string;
201
204
  * here, so a wildcard pairs with whatever methods consumers write.
202
205
  */
203
206
  declare function methodsAgree(a: string | null, b: string | null): boolean;
204
- /** Whether a declared route path admits a concrete request path. */
207
+ /**
208
+ * Whether a declared route path admits a concrete request path. Both
209
+ * sides compare on their normalized forms, and a hole in the request
210
+ * is text like any other, so a route inside a mount pattern is admitted
211
+ * by it and a wider route is not.
212
+ */
205
213
  declare function routePathAdmits(declaredPath: string, requestPath: string): boolean;
214
+ /** Whether two declared route paths serve at least one request in common. */
215
+ declare function routePathsMeet(a: string, b: string): boolean;
206
216
 
207
217
  /**
208
218
  * The pairing key is `(deploymentTarget, instanceName)`, which is
@@ -491,4 +501,4 @@ declare const TypeShapeSchema: z.ZodType<TypeShape>;
491
501
  */
492
502
  declare function withDefinitionsInlined(shape: TypeShape, definitions: Record<string, TypeShape> | undefined, depth?: number, inProgress?: ReadonlySet<string>): TypeShape;
493
503
 
494
- export { withDefinitionsInlined as A, BoundaryBindingSchema as B, ConfidenceInfoSchema as C, type DeployableUnit as D, EVERY_FIELD as E, type FunctionCallSemantics as F, type GraphqlOperationSemantics as G, type MessageBusSemantics as M, type RestSemantics as R, type Semantics as S, type TypeShape as T, ConfidenceLevelSchema as a, ConfidenceSourceSchema as b, CorroborationSchema as c, SourceLocationSchema as d, type MessageBusTechnology as e, DeployableUnitSchema as f, FunctionCallSemanticsSchema as g, GraphqlOperationSemanticsSchema as h, type GraphqlResolverSemantics as i, GraphqlResolverSemanticsSchema as j, MessageBusSemanticsSchema as k, RestSemanticsSchema as l, type RuntimeConfigSemantics as m, RuntimeConfigSemanticsSchema as n, SemanticsSchema as o, type StorageSemantics as p, StorageSemanticsSchema as q, TypeShapeSchema as r, ecsContainerInstanceName as s, methodsAgree as t, normalizePath as u, pathShape as v, routePathAdmits as w, storageContainerLabel as x, storageLabel as y, typeDefinitionKey as z };
504
+ export { typeDefinitionKey as A, BoundaryBindingSchema as B, ConfidenceInfoSchema as C, type DeployableUnit as D, EVERY_FIELD as E, type FunctionCallSemantics as F, type GraphqlOperationSemantics as G, withDefinitionsInlined as H, type MessageBusSemantics as M, type RestSemantics as R, type Semantics as S, type TypeShape as T, ConfidenceLevelSchema as a, ConfidenceSourceSchema as b, CorroborationSchema as c, SourceLocationSchema as d, type MessageBusTechnology as e, DeployableUnitSchema as f, FunctionCallSemanticsSchema as g, GraphqlOperationSemanticsSchema as h, type GraphqlResolverSemantics as i, GraphqlResolverSemanticsSchema as j, MessageBusSemanticsSchema as k, RestSemanticsSchema as l, type RuntimeConfigSemantics as m, RuntimeConfigSemanticsSchema as n, SemanticsSchema as o, type StorageSemantics as p, StorageSemanticsSchema as q, TypeShapeSchema as r, ecsContainerInstanceName as s, methodsAgree as t, normalizePath as u, pathShape as v, routePathAdmits as w, routePathsMeet as x, storageContainerLabel as y, storageLabel as z };
@@ -178,7 +178,8 @@ type RestSemantics = z.infer<typeof RestSemanticsSchema>;
178
178
  /**
179
179
  * Normalize a route path to a canonical form for matching.
180
180
  *
181
- * - Converts Express-style params (`:id`) to brace-style (`{id}`)
181
+ * - Converts Express-style params (`:id`) to brace-style (`{id}`), and
182
+ * keeps a range modifier (`:id?`, `:rest+`, `:rest*`) inside the braces
182
183
  * - Strips trailing slashes (except bare `/`)
183
184
  * - Lowercases the static segments (params stay case-sensitive)
184
185
  */
@@ -189,6 +190,8 @@ declare function normalizePath(path: string): string;
189
190
  * requests each one serves, and what deciding whether two sides
190
191
  * describe one endpoint rests on. The name a parameter is written
191
192
  * under is worth keeping in a report and worth nothing in a comparison.
193
+ * A parameter's range stays, since `{tenant?}` serves a different set
194
+ * of requests from `{tenant}`.
192
195
  */
193
196
  declare function pathShape(path: string): string;
194
197
  /**
@@ -201,8 +204,15 @@ declare function pathShape(path: string): string;
201
204
  * here, so a wildcard pairs with whatever methods consumers write.
202
205
  */
203
206
  declare function methodsAgree(a: string | null, b: string | null): boolean;
204
- /** Whether a declared route path admits a concrete request path. */
207
+ /**
208
+ * Whether a declared route path admits a concrete request path. Both
209
+ * sides compare on their normalized forms, and a hole in the request
210
+ * is text like any other, so a route inside a mount pattern is admitted
211
+ * by it and a wider route is not.
212
+ */
205
213
  declare function routePathAdmits(declaredPath: string, requestPath: string): boolean;
214
+ /** Whether two declared route paths serve at least one request in common. */
215
+ declare function routePathsMeet(a: string, b: string): boolean;
206
216
 
207
217
  /**
208
218
  * The pairing key is `(deploymentTarget, instanceName)`, which is
@@ -491,4 +501,4 @@ declare const TypeShapeSchema: z.ZodType<TypeShape>;
491
501
  */
492
502
  declare function withDefinitionsInlined(shape: TypeShape, definitions: Record<string, TypeShape> | undefined, depth?: number, inProgress?: ReadonlySet<string>): TypeShape;
493
503
 
494
- export { withDefinitionsInlined as A, BoundaryBindingSchema as B, ConfidenceInfoSchema as C, type DeployableUnit as D, EVERY_FIELD as E, type FunctionCallSemantics as F, type GraphqlOperationSemantics as G, type MessageBusSemantics as M, type RestSemantics as R, type Semantics as S, type TypeShape as T, ConfidenceLevelSchema as a, ConfidenceSourceSchema as b, CorroborationSchema as c, SourceLocationSchema as d, type MessageBusTechnology as e, DeployableUnitSchema as f, FunctionCallSemanticsSchema as g, GraphqlOperationSemanticsSchema as h, type GraphqlResolverSemantics as i, GraphqlResolverSemanticsSchema as j, MessageBusSemanticsSchema as k, RestSemanticsSchema as l, type RuntimeConfigSemantics as m, RuntimeConfigSemanticsSchema as n, SemanticsSchema as o, type StorageSemantics as p, StorageSemanticsSchema as q, TypeShapeSchema as r, ecsContainerInstanceName as s, methodsAgree as t, normalizePath as u, pathShape as v, routePathAdmits as w, storageContainerLabel as x, storageLabel as y, typeDefinitionKey as z };
504
+ export { typeDefinitionKey as A, BoundaryBindingSchema as B, ConfidenceInfoSchema as C, type DeployableUnit as D, EVERY_FIELD as E, type FunctionCallSemantics as F, type GraphqlOperationSemantics as G, withDefinitionsInlined as H, type MessageBusSemantics as M, type RestSemantics as R, type Semantics as S, type TypeShape as T, ConfidenceLevelSchema as a, ConfidenceSourceSchema as b, CorroborationSchema as c, SourceLocationSchema as d, type MessageBusTechnology as e, DeployableUnitSchema as f, FunctionCallSemanticsSchema as g, GraphqlOperationSemanticsSchema as h, type GraphqlResolverSemantics as i, GraphqlResolverSemanticsSchema as j, MessageBusSemanticsSchema as k, RestSemanticsSchema as l, type RuntimeConfigSemantics as m, RuntimeConfigSemanticsSchema as n, SemanticsSchema as o, type StorageSemantics as p, StorageSemanticsSchema as q, TypeShapeSchema as r, ecsContainerInstanceName as s, methodsAgree as t, normalizePath as u, pathShape as v, routePathAdmits as w, routePathsMeet as x, storageContainerLabel as y, storageLabel as z };
package/dist/schemas.cjs CHANGED
@@ -405,6 +405,187 @@ function pathAfterOrigin(text) {
405
405
  return cut === -1 ? withoutOrigin : withoutOrigin.slice(0, cut);
406
406
  }
407
407
 
408
+ // src/semantics/pathPattern.ts
409
+ var ONE = { kind: "one" };
410
+ var OPTIONAL = { kind: "optional" };
411
+ var STAR = { kind: "star" };
412
+ var HOLE_SEGMENT = /^\{[^{}]*?([?+*]?)\}$/;
413
+ var SET_PIECE = /\(([^()]*)\)/;
414
+ var ALTERNATIVE_CAP = 64;
415
+ function alternativesOf(path) {
416
+ let alternatives = [path];
417
+ for (; ; ) {
418
+ const next = [];
419
+ let expanded = false;
420
+ for (const alternative of alternatives) {
421
+ const set = SET_PIECE.exec(alternative);
422
+ if (set === null || set.index === void 0) {
423
+ next.push(alternative);
424
+ continue;
425
+ }
426
+ expanded = true;
427
+ const head = alternative.slice(0, set.index);
428
+ const tail = alternative.slice(set.index + set[0].length);
429
+ for (const option of (set[1] ?? "").split("|")) {
430
+ next.push(head + option + tail);
431
+ }
432
+ }
433
+ if (!expanded) {
434
+ return alternatives;
435
+ }
436
+ if (next.length > ALTERNATIVE_CAP) {
437
+ return [path.replace(new RegExp(SET_PIECE, "g"), "{value}")];
438
+ }
439
+ alternatives = next;
440
+ }
441
+ }
442
+ var HOLE_RANGE_ITEMS = {
443
+ "": [ONE],
444
+ "?": [OPTIONAL],
445
+ "+": [ONE, STAR],
446
+ "*": [STAR]
447
+ };
448
+ function escapedForRegex(text) {
449
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
450
+ }
451
+ function shapedItem(segment) {
452
+ const source = segment.split(/(\{[^}]*\}|\*)/g).map((part) => {
453
+ if (part === "*") {
454
+ return ".*";
455
+ }
456
+ if (part.startsWith("{")) {
457
+ return "[^/]+";
458
+ }
459
+ return escapedForRegex(part);
460
+ }).join("");
461
+ return {
462
+ kind: "shaped",
463
+ shape: segment.replace(/\{[^}]*\}/g, "{}"),
464
+ test: new RegExp(`^${source}$`)
465
+ };
466
+ }
467
+ function itemsOf(segment) {
468
+ if (segment === "*") {
469
+ return [STAR];
470
+ }
471
+ const hole = HOLE_SEGMENT.exec(segment);
472
+ if (hole !== null) {
473
+ return HOLE_RANGE_ITEMS[hole[1] ?? ""] ?? [ONE];
474
+ }
475
+ if (segment.includes("{") || segment.includes("*")) {
476
+ return [shapedItem(segment)];
477
+ }
478
+ return [{ kind: "text", text: segment }];
479
+ }
480
+ function segmentsOf(alternative) {
481
+ const trimmed = alternative.startsWith("/") ? alternative.slice(1) : alternative;
482
+ return trimmed === "" ? [] : trimmed.split("/");
483
+ }
484
+ function patternOf(path) {
485
+ return alternativesOf(path).map(
486
+ (alternative) => segmentsOf(alternative).flatMap(itemsOf)
487
+ );
488
+ }
489
+ function literalItemsOf(path) {
490
+ return segmentsOf(path).map((text) => ({ kind: "text", text }));
491
+ }
492
+ function absorbsAnything(item) {
493
+ return item.kind === "one" || item.kind === "optional" || item.kind === "star";
494
+ }
495
+ function meetOnOneSegment(a, b) {
496
+ if (absorbsAnything(a) || absorbsAnything(b)) {
497
+ return true;
498
+ }
499
+ if (a.kind === "text" && b.kind === "text") {
500
+ return a.text === b.text;
501
+ }
502
+ if (a.kind === "text" && b.kind === "shaped") {
503
+ return b.test.test(a.text);
504
+ }
505
+ if (a.kind === "shaped" && b.kind === "text") {
506
+ return a.test.test(b.text);
507
+ }
508
+ return a.kind === "shaped" && b.kind === "shaped" && a.shape === b.shape;
509
+ }
510
+ function skippable(item) {
511
+ return item.kind === "optional" || item.kind === "star";
512
+ }
513
+ function itemsMeet(a, b) {
514
+ const width = b.length + 1;
515
+ const seen = new Uint8Array((a.length + 1) * width);
516
+ const queue = [0];
517
+ seen[0] = 1;
518
+ const visit = (i, j) => {
519
+ const at = i * width + j;
520
+ if (seen[at] === 0) {
521
+ seen[at] = 1;
522
+ queue.push(at);
523
+ }
524
+ };
525
+ while (queue.length > 0) {
526
+ const at = queue.pop();
527
+ const i = Math.floor(at / width);
528
+ const j = at % width;
529
+ if (i === a.length && j === b.length) {
530
+ return true;
531
+ }
532
+ const left = a[i];
533
+ const right = b[j];
534
+ if (left !== void 0 && skippable(left)) {
535
+ visit(i + 1, j);
536
+ }
537
+ if (right !== void 0 && skippable(right)) {
538
+ visit(i, j + 1);
539
+ }
540
+ if (left !== void 0 && right !== void 0) {
541
+ if (meetOnOneSegment(left, right)) {
542
+ visit(
543
+ left.kind === "star" ? i : i + 1,
544
+ right.kind === "star" ? j : j + 1
545
+ );
546
+ }
547
+ }
548
+ }
549
+ return false;
550
+ }
551
+ function pathsMeet(a, b) {
552
+ const left = patternOf(a);
553
+ const right = patternOf(b);
554
+ return left.some((one) => right.some((other) => itemsMeet(one, other)));
555
+ }
556
+ function patternAdmits(declared, request) {
557
+ const literal = literalItemsOf(request);
558
+ return patternOf(declared).some((items) => itemsMeet(items, literal));
559
+ }
560
+ function pathSpansShapes(path) {
561
+ return /\{[^{}]*[?+*]\}|\(|(?:^|\/)\*(?:\/|$)/.test(path);
562
+ }
563
+ function countOf(items, kinds) {
564
+ return items.filter((item) => kinds.includes(item.kind)).length;
565
+ }
566
+ function pathSpecificity(path) {
567
+ const alternatives = patternOf(path);
568
+ const ranks = alternatives.map((items) => [
569
+ countOf(items, ["text"]),
570
+ countOf(items, ["shaped"]),
571
+ -countOf(items, ["optional", "star"])
572
+ ]);
573
+ const loosest = ranks.reduce(
574
+ (low, rank) => compareRanks(rank, low) < 0 ? rank : low
575
+ );
576
+ return [...loosest, 1 - alternatives.length];
577
+ }
578
+ function compareRanks(a, b) {
579
+ const length = Math.max(a.length, b.length);
580
+ for (let index = 0; index < length; index += 1) {
581
+ const difference = (a[index] ?? 0) - (b[index] ?? 0);
582
+ if (difference !== 0) {
583
+ return difference;
584
+ }
585
+ }
586
+ return 0;
587
+ }
588
+
408
589
  // src/semantics/rest.ts
409
590
  var RestSemanticsSchema = import_zod6.z.object({
410
591
  name: import_zod6.z.literal("rest"),
@@ -430,7 +611,7 @@ function baseUrlReference(semantics) {
430
611
  return label === void 0 ? null : referenceFromName(patternHole(label));
431
612
  }
432
613
  function normalizePath(path) {
433
- let normalized = path.replace(/:([a-zA-Z_]\w*)/g, "{$1}");
614
+ let normalized = path.replace(/:([a-zA-Z_]\w*)([?+*]?)/g, "{$1$2}");
434
615
  if (normalized.length > 1 && normalized.endsWith("/")) {
435
616
  normalized = normalized.slice(0, -1);
436
617
  }
@@ -441,7 +622,7 @@ function normalizePath(path) {
441
622
  return normalized;
442
623
  }
443
624
  function pathShape(path) {
444
- return normalizePath(path).replace(/\{[^}]*\}/g, "{}");
625
+ return normalizePath(path).replace(/\{[^{}]*?([?+*]?)\}/g, "{$1}");
445
626
  }
446
627
  function methodsAgree(a, b) {
447
628
  if (a === null || b === null) {
@@ -449,22 +630,11 @@ function methodsAgree(a, b) {
449
630
  }
450
631
  return a === b || a === "*" || b === "*";
451
632
  }
452
- function routePathRegex(pattern) {
453
- const source = pattern.split(/(\{[^}]+\}|\*)/g).map((part) => {
454
- if (part === "*") {
455
- return ".*";
456
- }
457
- if (part.startsWith("{") && part.endsWith("}")) {
458
- return "[^/]+";
459
- }
460
- return part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
461
- }).join("");
462
- return new RegExp(`^${source}$`);
463
- }
464
633
  function routePathAdmits(declaredPath, requestPath) {
465
- return routePathRegex(normalizePath(declaredPath)).test(
466
- normalizePath(requestPath)
467
- );
634
+ return patternAdmits(normalizePath(declaredPath), normalizePath(requestPath));
635
+ }
636
+ function routePathsMeet(a, b) {
637
+ return pathsMeet(normalizePath(a), normalizePath(b));
468
638
  }
469
639
  var restSemantics = defineBoundarySemantics({
470
640
  name: "rest",
@@ -509,6 +679,15 @@ var restSemantics = defineBoundarySemantics({
509
679
  sidesAgree(a, b) {
510
680
  return methodsAgree(a.method, b.method);
511
681
  },
682
+ spansBuckets(semantics) {
683
+ return semantics.path !== null && pathSpansShapes(normalizePath(semantics.path));
684
+ },
685
+ bucketsMeet(a, b) {
686
+ return a.path !== null && b.path !== null && routePathsMeet(a.path, b.path);
687
+ },
688
+ bucketRank(semantics) {
689
+ return semantics.path === null ? [] : pathSpecificity(normalizePath(semantics.path));
690
+ },
512
691
  /**
513
692
  * What the identity key says, with a missing half still readable:
514
693
  * ANY when no method was stated, and ? when no path was. Null when
@@ -1,2 +1,2 @@
1
1
  import 'zod';
2
- export { B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, f as DeployableUnitSchema, g as FunctionCallSemanticsSchema, h as GraphqlOperationSemanticsSchema, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, l as RestSemanticsSchema, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, d as SourceLocationSchema, q as StorageSemanticsSchema, T as TypeShape, r as TypeShapeSchema, z as typeDefinitionKey, A as withDefinitionsInlined } from './schemas-Dn1AzzWd.cjs';
2
+ export { B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, f as DeployableUnitSchema, g as FunctionCallSemanticsSchema, h as GraphqlOperationSemanticsSchema, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, l as RestSemanticsSchema, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, d as SourceLocationSchema, q as StorageSemanticsSchema, T as TypeShape, r as TypeShapeSchema, A as typeDefinitionKey, H as withDefinitionsInlined } from './schemas-BDB_vB6m.cjs';
package/dist/schemas.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  import 'zod';
2
- export { B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, f as DeployableUnitSchema, g as FunctionCallSemanticsSchema, h as GraphqlOperationSemanticsSchema, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, l as RestSemanticsSchema, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, d as SourceLocationSchema, q as StorageSemanticsSchema, T as TypeShape, r as TypeShapeSchema, z as typeDefinitionKey, A as withDefinitionsInlined } from './schemas-Dn1AzzWd.js';
2
+ export { B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, f as DeployableUnitSchema, g as FunctionCallSemanticsSchema, h as GraphqlOperationSemanticsSchema, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, l as RestSemanticsSchema, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, d as SourceLocationSchema, q as StorageSemanticsSchema, T as TypeShape, r as TypeShapeSchema, A as typeDefinitionKey, H as withDefinitionsInlined } from './schemas-BDB_vB6m.js';
package/dist/schemas.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  TypeShapeSchema,
18
18
  typeDefinitionKey,
19
19
  withDefinitionsInlined
20
- } from "./chunk-PPQWK62O.js";
20
+ } from "./chunk-I4WQM6F5.js";
21
21
  export {
22
22
  BoundaryBindingSchema,
23
23
  ConfidenceInfoSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suss/ir-core",
3
- "version": "0.22.1",
3
+ "version": "0.22.3",
4
4
  "type": "module",
5
5
  "description": "Shared IR primitives for suss — type shapes, boundary bindings, source locations, and confidence. Imported by both @suss/behavioral-ir and @suss/intent-ir so neither depends on the other.",
6
6
  "keywords": [