@suss/extractor 0.20.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -0
- package/dist/index.cjs +403 -84
- package/dist/index.d.cts +386 -15
- package/dist/index.d.ts +386 -15
- package/dist/index.js +391 -79
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -5,7 +5,8 @@ import {
|
|
|
5
5
|
withGraphqlMetadata,
|
|
6
6
|
withHttpMetadata,
|
|
7
7
|
withMountMetadata,
|
|
8
|
-
withSourceDocumentMetadata
|
|
8
|
+
withSourceDocumentMetadata,
|
|
9
|
+
withWrapperMetadata as withWrapperMetadata2
|
|
9
10
|
} from "@suss/behavioral-ir";
|
|
10
11
|
|
|
11
12
|
// src/inputReads.ts
|
|
@@ -98,80 +99,12 @@ function mergeInputReads(derived, syntactic) {
|
|
|
98
99
|
return [...found.values()];
|
|
99
100
|
}
|
|
100
101
|
|
|
101
|
-
// src/
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
type: "registrationCall",
|
|
108
|
-
importModule: opts.importModule,
|
|
109
|
-
importName,
|
|
110
|
-
registrationChain: [...opts.methods]
|
|
111
|
-
},
|
|
112
|
-
bindingExtraction: {
|
|
113
|
-
// `.all` registers every method, so it records "*", which the pairing
|
|
114
|
-
// engine treats as agreeing with any method at all.
|
|
115
|
-
method: {
|
|
116
|
-
type: "fromRegistration",
|
|
117
|
-
position: "methodName",
|
|
118
|
-
nameMap: { all: "*" }
|
|
119
|
-
},
|
|
120
|
-
path: { type: "fromArgument", position: 0 }
|
|
121
|
-
},
|
|
122
|
-
...opts.mount !== void 0 ? { mount: opts.mount } : {},
|
|
123
|
-
requiresImport: [opts.importModule]
|
|
124
|
-
}));
|
|
125
|
-
if (opts.importNames.length === 0) {
|
|
126
|
-
return calls;
|
|
127
|
-
}
|
|
128
|
-
return [
|
|
129
|
-
...calls,
|
|
130
|
-
// Routes registered in a loop over an array of specs, a shape
|
|
131
|
-
// registration-call discovery cannot see. The receiver comes from
|
|
132
|
-
// the same import declaration as the calls above, so a loop that
|
|
133
|
-
// never touches this library's routable is left alone.
|
|
134
|
-
{
|
|
135
|
-
kind,
|
|
136
|
-
match: {
|
|
137
|
-
type: "registrationLoop",
|
|
138
|
-
elementShape: LOOP_ELEMENT_SHAPE,
|
|
139
|
-
receiver: {
|
|
140
|
-
importModule: opts.importModule,
|
|
141
|
-
importNames: [...opts.importNames]
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
requiresImport: [opts.importModule]
|
|
145
|
-
}
|
|
146
|
-
];
|
|
147
|
-
}
|
|
148
|
-
var LOOP_ELEMENT_SHAPE = {
|
|
149
|
-
methodKey: "method",
|
|
150
|
-
pathKey: "path",
|
|
151
|
-
handlerKey: "handler"
|
|
152
|
-
};
|
|
153
|
-
function registrationHelperDiscovery(helpers, kind = "handler") {
|
|
154
|
-
return helpers.map((helper) => ({
|
|
155
|
-
kind,
|
|
156
|
-
match: {
|
|
157
|
-
type: "registrationTemplate",
|
|
158
|
-
helperName: helper.helperName,
|
|
159
|
-
...helper.importModule !== void 0 ? { importModule: helper.importModule } : {},
|
|
160
|
-
registrations: helper.registrations.map((one) => ({ ...one }))
|
|
161
|
-
}
|
|
162
|
-
}));
|
|
163
|
-
}
|
|
164
|
-
function unwrapJsonStringify(body) {
|
|
165
|
-
if (body === null || typeof body !== "object") {
|
|
166
|
-
return body;
|
|
167
|
-
}
|
|
168
|
-
const candidate = body;
|
|
169
|
-
if (candidate.kind !== "call" || candidate.callee !== "JSON.stringify") {
|
|
170
|
-
return body;
|
|
171
|
-
}
|
|
172
|
-
const inner = candidate.args?.[0];
|
|
173
|
-
return inner ?? body;
|
|
174
|
-
}
|
|
102
|
+
// src/composeWrappers.ts
|
|
103
|
+
import {
|
|
104
|
+
readWrapperMetadata,
|
|
105
|
+
withinScope,
|
|
106
|
+
withWrapperMetadata
|
|
107
|
+
} from "@suss/behavioral-ir";
|
|
175
108
|
|
|
176
109
|
// src/paths/enumeratePaths.ts
|
|
177
110
|
import { CATCH_ENTRY_TEXT } from "@suss/behavioral-ir";
|
|
@@ -588,23 +521,372 @@ function reasonToDegrade(error) {
|
|
|
588
521
|
return null;
|
|
589
522
|
}
|
|
590
523
|
|
|
591
|
-
// src/
|
|
524
|
+
// src/composeWrappers.ts
|
|
525
|
+
var BUDGET_GAP = {
|
|
526
|
+
type: "unreadOutcome",
|
|
527
|
+
conditions: [],
|
|
528
|
+
consequence: "unknown",
|
|
529
|
+
description: `Composing the wrappers registered around this unit would have gone past the path budget of ${MAX_PATHS}, so what each of them produces is reported beside this unit's own outcomes rather than under the conditions that reach it`
|
|
530
|
+
};
|
|
531
|
+
function composeWrappers(summaries) {
|
|
532
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
533
|
+
for (const summary of summaries) {
|
|
534
|
+
const key = summaryKey(summary.location.file, summary.identity.name);
|
|
535
|
+
if (!byKey.has(key)) {
|
|
536
|
+
byKey.set(key, summary);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return summaries.map((summary) => composeOne(summary, byKey));
|
|
540
|
+
}
|
|
541
|
+
function summaryKey(file, name) {
|
|
542
|
+
return `${file}::${name}`;
|
|
543
|
+
}
|
|
544
|
+
function composeOne(summary, byKey) {
|
|
545
|
+
const recorded = readWrapperMetadata(summary);
|
|
546
|
+
const applied = recorded?.applied ?? [];
|
|
547
|
+
const covering = applied.filter(
|
|
548
|
+
(reference) => coversUnit(reference, summary)
|
|
549
|
+
);
|
|
550
|
+
const narrowed = covering.length === applied.length ? summary : {
|
|
551
|
+
...summary,
|
|
552
|
+
metadata: withWrapperMetadata(summary.metadata, {
|
|
553
|
+
applied: covering
|
|
554
|
+
})
|
|
555
|
+
};
|
|
556
|
+
const wrappers = covering.flatMap((reference) => {
|
|
557
|
+
const found = byKey.get(summaryKey(reference.file, reference.name));
|
|
558
|
+
return found === void 0 ? [] : [{ reference, summary: found }];
|
|
559
|
+
});
|
|
560
|
+
if (wrappers.length === 0) {
|
|
561
|
+
return narrowed;
|
|
562
|
+
}
|
|
563
|
+
let composition = {
|
|
564
|
+
transitions: summary.transitions,
|
|
565
|
+
degraded: false
|
|
566
|
+
};
|
|
567
|
+
for (const wrapper of [...wrappers].reverse()) {
|
|
568
|
+
if (wrapper.reference.onThrow === true) {
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
composition = merge(composition, applyWrapper(wrapper, composition));
|
|
572
|
+
}
|
|
573
|
+
for (const wrapper of wrappers) {
|
|
574
|
+
if (wrapper.reference.onThrow !== true) {
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
composition = merge(composition, applyThrowWrapper(wrapper, composition));
|
|
578
|
+
}
|
|
579
|
+
if (composition.transitions === summary.transitions) {
|
|
580
|
+
return narrowed;
|
|
581
|
+
}
|
|
582
|
+
return {
|
|
583
|
+
...narrowed,
|
|
584
|
+
transitions: withDistinctIds(composition.transitions),
|
|
585
|
+
gaps: composition.degraded ? [...summary.gaps, BUDGET_GAP] : summary.gaps
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
function merge(before, step) {
|
|
589
|
+
return {
|
|
590
|
+
transitions: step.transitions,
|
|
591
|
+
degraded: before.degraded || step.degraded
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
function coversUnit(reference, summary) {
|
|
595
|
+
if (reference.scope === void 0) {
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
598
|
+
const binding = summary.identity.boundaryBinding;
|
|
599
|
+
return binding !== null && withinScope(binding, reference.scope);
|
|
600
|
+
}
|
|
601
|
+
function applyWrapper(wrapper, inner) {
|
|
602
|
+
const shortCircuits = attribute(
|
|
603
|
+
wrapper.summary.transitions.filter((t) => t.output.type !== "delegate"),
|
|
604
|
+
wrapper.reference
|
|
605
|
+
);
|
|
606
|
+
const passThroughs = wrapper.summary.transitions.filter(
|
|
607
|
+
(t) => t.output.type === "delegate"
|
|
608
|
+
);
|
|
609
|
+
if (passThroughs.length === 0 || shortCircuits.length + passThroughs.length * inner.transitions.length > MAX_PATHS) {
|
|
610
|
+
return {
|
|
611
|
+
transitions: [...shortCircuits, ...inner.transitions],
|
|
612
|
+
degraded: passThroughs.length > 0
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
const continued = passThroughs.flatMap(
|
|
616
|
+
(passThrough) => inner.transitions.map((transition) => splice(passThrough, transition))
|
|
617
|
+
);
|
|
618
|
+
return { transitions: [...shortCircuits, ...continued], degraded: false };
|
|
619
|
+
}
|
|
620
|
+
function applyThrowWrapper(wrapper, inner) {
|
|
621
|
+
const thrown = inner.transitions.filter((t) => t.output.type === "throw");
|
|
622
|
+
if (thrown.length === 0) {
|
|
623
|
+
return inner;
|
|
624
|
+
}
|
|
625
|
+
const rest = inner.transitions.filter((t) => t.output.type !== "throw");
|
|
626
|
+
const handled = wrapper.summary.transitions;
|
|
627
|
+
if (rest.length + thrown.length * handled.length > MAX_PATHS) {
|
|
628
|
+
return {
|
|
629
|
+
transitions: [
|
|
630
|
+
...inner.transitions,
|
|
631
|
+
...attribute(handled, wrapper.reference)
|
|
632
|
+
],
|
|
633
|
+
degraded: true
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
const composed = thrown.flatMap(
|
|
637
|
+
(transition) => attribute(
|
|
638
|
+
handled.map((handler) => splice(transition, handler)),
|
|
639
|
+
wrapper.reference
|
|
640
|
+
)
|
|
641
|
+
);
|
|
642
|
+
return { transitions: [...rest, ...composed], degraded: false };
|
|
643
|
+
}
|
|
644
|
+
function splice(outer, inner) {
|
|
645
|
+
return {
|
|
646
|
+
...inner,
|
|
647
|
+
id: `${inner.id}:via:${outer.id}`,
|
|
648
|
+
conditions: [...outer.conditions, ...inner.conditions],
|
|
649
|
+
effects: [...outer.effects, ...inner.effects],
|
|
650
|
+
isDefault: outer.isDefault && inner.isDefault
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
function attribute(transitions, reference) {
|
|
654
|
+
return transitions.map((transition) => ({
|
|
655
|
+
...transition,
|
|
656
|
+
metadata: withWrapperMetadata(transition.metadata, { from: reference })
|
|
657
|
+
}));
|
|
658
|
+
}
|
|
659
|
+
function withDistinctIds(transitions) {
|
|
660
|
+
const seen = /* @__PURE__ */ new Map();
|
|
661
|
+
return transitions.map((transition) => {
|
|
662
|
+
const taken = seen.get(transition.id);
|
|
663
|
+
seen.set(transition.id, (taken ?? 0) + 1);
|
|
664
|
+
return taken === void 0 ? transition : { ...transition, id: `${transition.id}#${taken + 1}` };
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// src/effectGuards.ts
|
|
592
669
|
var keyOf = (condition) => `${condition.polarity}:${condition.sourceText}`;
|
|
670
|
+
var opposite = (condition) => `${condition.polarity === "positive" ? "negative" : "positive"}:${condition.sourceText}`;
|
|
671
|
+
function guardsHoldOn(preconditions, conditions) {
|
|
672
|
+
if (preconditions === void 0 || preconditions.length === 0) {
|
|
673
|
+
return true;
|
|
674
|
+
}
|
|
675
|
+
const onBranch = new Set(conditions.map(keyOf));
|
|
676
|
+
return preconditions.every(
|
|
677
|
+
(precondition) => !onBranch.has(opposite(precondition))
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
function runsBefore(effectLine, terminalEndLine) {
|
|
681
|
+
return effectLine <= terminalEndLine;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// src/packHelpers.ts
|
|
685
|
+
function httpRouteDiscovery(opts) {
|
|
686
|
+
const kind = opts.kind ?? "handler";
|
|
687
|
+
const calls = opts.importNames.map((importName) => ({
|
|
688
|
+
kind,
|
|
689
|
+
match: {
|
|
690
|
+
type: "registrationCall",
|
|
691
|
+
importModule: opts.importModule,
|
|
692
|
+
importName,
|
|
693
|
+
registrationChain: [...opts.methods]
|
|
694
|
+
},
|
|
695
|
+
bindingExtraction: {
|
|
696
|
+
// `.all` registers every method, so it records "*", which the pairing
|
|
697
|
+
// engine treats as agreeing with any method at all.
|
|
698
|
+
method: {
|
|
699
|
+
type: "fromRegistration",
|
|
700
|
+
position: "methodName",
|
|
701
|
+
nameMap: { all: "*" }
|
|
702
|
+
},
|
|
703
|
+
path: { type: "fromArgument", position: 0 }
|
|
704
|
+
},
|
|
705
|
+
...opts.mount !== void 0 ? { mount: opts.mount } : {},
|
|
706
|
+
requiresImport: [opts.importModule]
|
|
707
|
+
}));
|
|
708
|
+
if (opts.importNames.length === 0) {
|
|
709
|
+
return calls;
|
|
710
|
+
}
|
|
711
|
+
return [
|
|
712
|
+
...calls,
|
|
713
|
+
// Routes registered in a loop over an array of specs, a shape
|
|
714
|
+
// registration-call discovery cannot see. The receiver comes from
|
|
715
|
+
// the same import declaration as the calls above, so a loop that
|
|
716
|
+
// never touches this library's routable is left alone.
|
|
717
|
+
{
|
|
718
|
+
kind,
|
|
719
|
+
match: {
|
|
720
|
+
type: "registrationLoop",
|
|
721
|
+
elementShape: LOOP_ELEMENT_SHAPE,
|
|
722
|
+
receiver: {
|
|
723
|
+
importModule: opts.importModule,
|
|
724
|
+
importNames: [...opts.importNames]
|
|
725
|
+
}
|
|
726
|
+
},
|
|
727
|
+
requiresImport: [opts.importModule]
|
|
728
|
+
}
|
|
729
|
+
];
|
|
730
|
+
}
|
|
731
|
+
function wrapperDiscovery(opts) {
|
|
732
|
+
return opts.importNames.flatMap(
|
|
733
|
+
(importName) => opts.wraps.map((wraps) => ({
|
|
734
|
+
kind: opts.kind ?? "middleware",
|
|
735
|
+
match: {
|
|
736
|
+
type: "registrationCall",
|
|
737
|
+
importModule: opts.importModule,
|
|
738
|
+
importName,
|
|
739
|
+
registrationChain: []
|
|
740
|
+
},
|
|
741
|
+
wraps: { ...wraps },
|
|
742
|
+
requiresImport: [opts.importModule]
|
|
743
|
+
}))
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
var LOOP_ELEMENT_SHAPE = {
|
|
747
|
+
methodKey: "method",
|
|
748
|
+
pathKey: "path",
|
|
749
|
+
handlerKey: "handler"
|
|
750
|
+
};
|
|
751
|
+
function registrationHelperDiscovery(helpers, kind = "handler") {
|
|
752
|
+
return helpers.map((helper) => ({
|
|
753
|
+
kind,
|
|
754
|
+
match: {
|
|
755
|
+
type: "registrationTemplate",
|
|
756
|
+
helperName: helper.helperName,
|
|
757
|
+
...helper.importModule !== void 0 ? { importModule: helper.importModule } : {},
|
|
758
|
+
...helper.subject !== void 0 ? { subject: helper.subject } : {},
|
|
759
|
+
registrations: helper.registrations.map((one) => ({ ...one }))
|
|
760
|
+
}
|
|
761
|
+
}));
|
|
762
|
+
}
|
|
763
|
+
function routeHelperIndex(opts) {
|
|
764
|
+
const methods = new Set(
|
|
765
|
+
opts.methods.map(
|
|
766
|
+
(method) => method.startsWith(".") ? method.slice(1) : method
|
|
767
|
+
)
|
|
768
|
+
);
|
|
769
|
+
return {
|
|
770
|
+
find: { by: "subject" },
|
|
771
|
+
declare: (helpers) => ({
|
|
772
|
+
discovery: registrationHelperDiscovery(
|
|
773
|
+
helpers.flatMap((helper) => routesRegisteredBy(helper, methods, opts)),
|
|
774
|
+
opts.kind ?? "handler"
|
|
775
|
+
)
|
|
776
|
+
})
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
function routesRegisteredBy(helper, methods, opts) {
|
|
780
|
+
const registrations = [];
|
|
781
|
+
let subjectArgument;
|
|
782
|
+
for (const sink of helper.sinks) {
|
|
783
|
+
const registration = routeRegisteredBy(helper, sink, methods);
|
|
784
|
+
if (registration === null) {
|
|
785
|
+
continue;
|
|
786
|
+
}
|
|
787
|
+
registrations.push(registration);
|
|
788
|
+
if (sink.receiver.as === "parameter") {
|
|
789
|
+
subjectArgument = sink.receiver.position;
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
if (registrations.length === 0 || subjectArgument === void 0) {
|
|
793
|
+
return [];
|
|
794
|
+
}
|
|
795
|
+
return [
|
|
796
|
+
{
|
|
797
|
+
helperName: helper.name,
|
|
798
|
+
importModule: helper.file,
|
|
799
|
+
subject: {
|
|
800
|
+
argument: subjectArgument,
|
|
801
|
+
importModule: opts.importModule,
|
|
802
|
+
importNames: [...opts.importNames]
|
|
803
|
+
},
|
|
804
|
+
registrations
|
|
805
|
+
}
|
|
806
|
+
];
|
|
807
|
+
}
|
|
808
|
+
function routeRegisteredBy(helper, sink, methods) {
|
|
809
|
+
if (sink.method === null || !methods.has(sink.method)) {
|
|
810
|
+
return null;
|
|
811
|
+
}
|
|
812
|
+
const { receiver } = sink;
|
|
813
|
+
if (receiver.as !== "parameter" || receiver.property !== void 0 || !helper.subjectParameters.includes(receiver.position)) {
|
|
814
|
+
return null;
|
|
815
|
+
}
|
|
816
|
+
const pathTemplate = sink.arguments[0];
|
|
817
|
+
const handler = sink.arguments[sink.arguments.length - 1];
|
|
818
|
+
if (sink.arguments.length < 2 || pathTemplate === void 0 || pathTemplate.as !== "text" || handler === void 0) {
|
|
819
|
+
return null;
|
|
820
|
+
}
|
|
821
|
+
const handlerArg = handlerSlot(handler);
|
|
822
|
+
return handlerArg === null ? null : {
|
|
823
|
+
// `.all` registers every method, which the pairing engine
|
|
824
|
+
// spells as a wildcard.
|
|
825
|
+
method: sink.method === "all" ? "*" : sink.method.toUpperCase(),
|
|
826
|
+
pathTemplate: pathTemplate.text,
|
|
827
|
+
handlerArg
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
function handlerSlot(value) {
|
|
831
|
+
if (value.as !== "parameter") {
|
|
832
|
+
return null;
|
|
833
|
+
}
|
|
834
|
+
return value.property === void 0 ? `{${value.position}}` : `{${value.position}}.${value.property}`;
|
|
835
|
+
}
|
|
836
|
+
function unwrapJsonStringify(body) {
|
|
837
|
+
if (body === null || typeof body !== "object") {
|
|
838
|
+
return body;
|
|
839
|
+
}
|
|
840
|
+
const candidate = body;
|
|
841
|
+
if (candidate.kind !== "call" || candidate.callee !== "JSON.stringify") {
|
|
842
|
+
return body;
|
|
843
|
+
}
|
|
844
|
+
const inner = candidate.args?.[0];
|
|
845
|
+
return inner ?? body;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// src/packOptions.ts
|
|
849
|
+
import { z } from "zod";
|
|
850
|
+
var storageSystemOption = z.enum([
|
|
851
|
+
"postgresql",
|
|
852
|
+
"mysql",
|
|
853
|
+
"sqlite"
|
|
854
|
+
]);
|
|
855
|
+
var scopeOption = z.string();
|
|
856
|
+
var configuredCallOption = z.object({
|
|
857
|
+
/** Module that declares the receiver's type. */
|
|
858
|
+
module: z.string(),
|
|
859
|
+
/** Type name of the receiver, as exported from that module. */
|
|
860
|
+
receiver: z.string(),
|
|
861
|
+
/** Method that performs the send. */
|
|
862
|
+
method: z.string(),
|
|
863
|
+
/** Argument index carrying the subject. */
|
|
864
|
+
subjectArg: z.number(),
|
|
865
|
+
/**
|
|
866
|
+
* Which argument the message body is. Left out when the method has no
|
|
867
|
+
* single body argument, as a batch method taking a list of entries
|
|
868
|
+
* does, and then no body is reported.
|
|
869
|
+
*/
|
|
870
|
+
bodyArg: z.number().optional()
|
|
871
|
+
}).strict();
|
|
872
|
+
|
|
873
|
+
// src/paths/gatingConditions.ts
|
|
874
|
+
var keyOf2 = (condition) => `${condition.polarity}:${condition.sourceText}`;
|
|
593
875
|
function sharedGatingConditions(paths, readPredicate) {
|
|
594
876
|
const [first, ...rest] = paths ?? [];
|
|
595
877
|
if (first === void 0) {
|
|
596
878
|
return [];
|
|
597
879
|
}
|
|
598
|
-
const shared = new Set(first.map(
|
|
880
|
+
const shared = new Set(first.map(keyOf2));
|
|
599
881
|
for (const path of rest) {
|
|
600
|
-
const here = new Set(path.map(
|
|
882
|
+
const here = new Set(path.map(keyOf2));
|
|
601
883
|
for (const value of shared) {
|
|
602
884
|
if (!here.has(value)) {
|
|
603
885
|
shared.delete(value);
|
|
604
886
|
}
|
|
605
887
|
}
|
|
606
888
|
}
|
|
607
|
-
return first.filter((condition) => shared.has(
|
|
889
|
+
return first.filter((condition) => shared.has(keyOf2(condition))).map((condition) => ({
|
|
608
890
|
sourceText: condition.sourceText,
|
|
609
891
|
structured: readPredicate === void 0 || condition.expression === null ? null : readPredicate(condition.expression),
|
|
610
892
|
polarity: condition.polarity,
|
|
@@ -658,6 +940,21 @@ var IdMap = class {
|
|
|
658
940
|
}
|
|
659
941
|
};
|
|
660
942
|
|
|
943
|
+
// src/paths/nodeWalk.ts
|
|
944
|
+
var SKIP_CHILDREN = /* @__PURE__ */ Symbol("skipChildren");
|
|
945
|
+
function walkDescendants(root, carried, visitor) {
|
|
946
|
+
for (const child of root.namedChildren) {
|
|
947
|
+
if (child === null) {
|
|
948
|
+
continue;
|
|
949
|
+
}
|
|
950
|
+
visitor.at(child, carried);
|
|
951
|
+
const inner = visitor.into(child, carried);
|
|
952
|
+
if (inner !== SKIP_CHILDREN) {
|
|
953
|
+
walkDescendants(child, inner, visitor);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
661
958
|
// src/reading.ts
|
|
662
959
|
function writtenReading(value, range) {
|
|
663
960
|
return { kind: "written", value, range };
|
|
@@ -861,6 +1158,9 @@ function buildMetadata(raw) {
|
|
|
861
1158
|
if (raw.mount !== void 0) {
|
|
862
1159
|
metadata = withMountMetadata(metadata, raw.mount);
|
|
863
1160
|
}
|
|
1161
|
+
if (raw.wrappers !== void 0 && raw.wrappers.length > 0) {
|
|
1162
|
+
metadata = withWrapperMetadata2(metadata, { applied: raw.wrappers });
|
|
1163
|
+
}
|
|
864
1164
|
return Object.keys(metadata).length > 0 ? metadata : null;
|
|
865
1165
|
}
|
|
866
1166
|
function buildHttpMetadataValue(raw) {
|
|
@@ -1123,27 +1423,39 @@ function paramToInput(param) {
|
|
|
1123
1423
|
export {
|
|
1124
1424
|
IdMap,
|
|
1125
1425
|
IdSet,
|
|
1426
|
+
MAX_PATHS,
|
|
1126
1427
|
PathBudgetExceeded,
|
|
1428
|
+
SKIP_CHILDREN,
|
|
1127
1429
|
UnmodeledFlow,
|
|
1128
1430
|
absentReading,
|
|
1129
1431
|
ambiguousReading,
|
|
1130
1432
|
andThenReading,
|
|
1131
1433
|
assembleSummary,
|
|
1132
1434
|
assessConfidence,
|
|
1435
|
+
composeWrappers,
|
|
1436
|
+
configuredCallOption,
|
|
1133
1437
|
detectGaps,
|
|
1134
1438
|
effectToIR,
|
|
1135
1439
|
enumerateOrDegrade,
|
|
1136
1440
|
enumerateStructuredPaths,
|
|
1137
1441
|
firstWrittenReading,
|
|
1442
|
+
guardsHoldOn,
|
|
1138
1443
|
httpRouteDiscovery,
|
|
1139
1444
|
makeTransitionId,
|
|
1140
1445
|
mapReading,
|
|
1141
1446
|
paramToInput,
|
|
1447
|
+
rawConditionToPredicate,
|
|
1142
1448
|
registrationHelperDiscovery,
|
|
1449
|
+
routeHelperIndex,
|
|
1450
|
+
runsBefore,
|
|
1451
|
+
scopeOption,
|
|
1143
1452
|
sharedGatingConditions,
|
|
1453
|
+
storageSystemOption,
|
|
1144
1454
|
terminalToOutput,
|
|
1145
1455
|
unreadableReading,
|
|
1146
1456
|
unwrapJsonStringify,
|
|
1147
1457
|
valueToReadFurtherFrom,
|
|
1458
|
+
walkDescendants,
|
|
1459
|
+
wrapperDiscovery,
|
|
1148
1460
|
writtenReading
|
|
1149
1461
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/extractor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Framework-agnostic extraction pipeline that turns raw extractions into suss behavioral summaries.",
|
|
6
6
|
"keywords": [
|
|
@@ -45,7 +45,8 @@
|
|
|
45
45
|
"typecheck": "tsc --noEmit"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@suss/behavioral-ir": "0.
|
|
48
|
+
"@suss/behavioral-ir": "0.21.1",
|
|
49
|
+
"zod": "^4.0.0"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
|
51
52
|
"tsup": "*",
|