@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.
- package/dist/{chunk-PPQWK62O.js → chunk-I4WQM6F5.js} +216 -17
- package/dist/index.cjs +239 -17
- package/dist/index.d.cts +54 -3
- package/dist/index.d.ts +54 -3
- package/dist/index.js +25 -1
- package/dist/{schemas-Dn1AzzWd.d.cts → schemas-BDB_vB6m.d.cts} +13 -3
- package/dist/{schemas-Dn1AzzWd.d.ts → schemas-BDB_vB6m.d.ts} +13 -3
- package/dist/schemas.cjs +196 -17
- package/dist/schemas.d.cts +1 -1
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.js +1 -1
- package/package.json +1 -1
|
@@ -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(/\{[^}]
|
|
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
|
|
531
|
-
|
|
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(/\{[^}]
|
|
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
|
|
653
|
-
|
|
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-
|
|
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
|
|
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-
|
|
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
|
|
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-
|
|
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
|
-
/**
|
|
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 {
|
|
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
|
-
/**
|
|
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 {
|
|
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(/\{[^}]
|
|
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
|
|
466
|
-
|
|
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
|
package/dist/schemas.d.cts
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,
|
|
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,
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/ir-core",
|
|
3
|
-
"version": "0.22.
|
|
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": [
|