@suss/extractor 0.1.1 → 0.3.0
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/index.cjs +92 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +92 -0
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -32,6 +32,86 @@ __export(index_exports, {
|
|
|
32
32
|
module.exports = __toCommonJS(index_exports);
|
|
33
33
|
var import_node_crypto = require("crypto");
|
|
34
34
|
|
|
35
|
+
// src/inputReads.ts
|
|
36
|
+
function inputReadsOf(args) {
|
|
37
|
+
const found = /* @__PURE__ */ new Map();
|
|
38
|
+
const keep = (read) => {
|
|
39
|
+
if (read === null) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
found.set(`${read.input}.${read.path.join(".")}`, read);
|
|
43
|
+
};
|
|
44
|
+
for (const value of args.values) {
|
|
45
|
+
keep(readOf(value));
|
|
46
|
+
}
|
|
47
|
+
for (const list of args.conditions) {
|
|
48
|
+
for (const predicate of list) {
|
|
49
|
+
for (const value of valuesIn(predicate)) {
|
|
50
|
+
keep(readOf(value));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return [...found.values()].sort(
|
|
55
|
+
(a, b) => a.input.localeCompare(b.input) || a.path.join(".").localeCompare(b.path.join("."))
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
function readOf(value, depth = 0) {
|
|
59
|
+
if (depth > 12) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
if (value.type === "input") {
|
|
63
|
+
return { input: value.inputRef, path: [...value.path] };
|
|
64
|
+
}
|
|
65
|
+
if (value.type !== "derived") {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const inner = readOf(value.from, depth + 1);
|
|
69
|
+
if (inner === null) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
const step = stepOf(value.derivation);
|
|
73
|
+
return step === null ? inner : { input: inner.input, path: [...inner.path, step] };
|
|
74
|
+
}
|
|
75
|
+
function stepOf(derivation) {
|
|
76
|
+
if (derivation.type === "propertyAccess") {
|
|
77
|
+
return typeof derivation.property === "string" ? derivation.property : null;
|
|
78
|
+
}
|
|
79
|
+
if (derivation.type === "destructured") {
|
|
80
|
+
return typeof derivation.field === "string" ? derivation.field : null;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
function valuesIn(predicate, depth = 0) {
|
|
85
|
+
if (depth > 12) {
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
const out = [];
|
|
89
|
+
const record = predicate;
|
|
90
|
+
for (const value of Object.values(record)) {
|
|
91
|
+
if (value === null || typeof value !== "object") {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (Array.isArray(value)) {
|
|
95
|
+
for (const item of value) {
|
|
96
|
+
out.push(...nested(item, depth));
|
|
97
|
+
}
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
out.push(...nested(value, depth));
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
function nested(value, depth) {
|
|
105
|
+
if (value === null || typeof value !== "object") {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
const kind = value.type;
|
|
109
|
+
if (kind === "input" || kind === "derived") {
|
|
110
|
+
return [value];
|
|
111
|
+
}
|
|
112
|
+
return valuesIn(value, depth + 1);
|
|
113
|
+
}
|
|
114
|
+
|
|
35
115
|
// src/packHelpers.ts
|
|
36
116
|
function httpRouteDiscovery(opts) {
|
|
37
117
|
const kind = opts.kind ?? "handler";
|
|
@@ -52,6 +132,12 @@ function httpRouteDiscovery(opts) {
|
|
|
52
132
|
}
|
|
53
133
|
|
|
54
134
|
// src/index.ts
|
|
135
|
+
function valuesOfOutput(output) {
|
|
136
|
+
if (output.type === "response" && output.statusCode !== null) {
|
|
137
|
+
return [output.statusCode];
|
|
138
|
+
}
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
55
141
|
var DEFAULT_OPTIONS = { gapHandling: "permissive" };
|
|
56
142
|
function makeTransitionId(functionName, branch) {
|
|
57
143
|
const { terminal } = branch;
|
|
@@ -85,6 +171,10 @@ function assembleSummary(raw, options = DEFAULT_OPTIONS) {
|
|
|
85
171
|
const confidence = assessConfidence(raw);
|
|
86
172
|
const inputs = raw.parameters.map(paramToInput);
|
|
87
173
|
const metadata = buildMetadata(raw);
|
|
174
|
+
const reads = inputReadsOf({
|
|
175
|
+
conditions: transitions.map((t) => t.conditions),
|
|
176
|
+
values: transitions.flatMap((t) => valuesOfOutput(t.output))
|
|
177
|
+
});
|
|
88
178
|
return {
|
|
89
179
|
kind: raw.identity.kind,
|
|
90
180
|
location: {
|
|
@@ -102,6 +192,8 @@ function assembleSummary(raw, options = DEFAULT_OPTIONS) {
|
|
|
102
192
|
transitions,
|
|
103
193
|
gaps,
|
|
104
194
|
confidence,
|
|
195
|
+
...reads.length > 0 ? { inputReads: reads } : {},
|
|
196
|
+
...raw.definitions !== void 0 && raw.definitions !== null ? { definitions: raw.definitions } : {},
|
|
105
197
|
...metadata !== null ? { metadata } : {}
|
|
106
198
|
};
|
|
107
199
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1299,6 +1299,12 @@ interface RawDeclaredContract {
|
|
|
1299
1299
|
*/
|
|
1300
1300
|
type BodyContent = "absent" | "empty" | "statements" | "elsewhere";
|
|
1301
1301
|
interface RawCodeStructure {
|
|
1302
|
+
/**
|
|
1303
|
+
* The types this unit's shapes name rather than spell out. Carried
|
|
1304
|
+
* onto the summary as `definitions`, so a reader following a name has
|
|
1305
|
+
* somewhere to look.
|
|
1306
|
+
*/
|
|
1307
|
+
definitions?: Record<string, TypeShape> | null;
|
|
1302
1308
|
identity: {
|
|
1303
1309
|
name: string;
|
|
1304
1310
|
kind: CodeUnitKind;
|
package/dist/index.d.ts
CHANGED
|
@@ -1299,6 +1299,12 @@ interface RawDeclaredContract {
|
|
|
1299
1299
|
*/
|
|
1300
1300
|
type BodyContent = "absent" | "empty" | "statements" | "elsewhere";
|
|
1301
1301
|
interface RawCodeStructure {
|
|
1302
|
+
/**
|
|
1303
|
+
* The types this unit's shapes name rather than spell out. Carried
|
|
1304
|
+
* onto the summary as `definitions`, so a reader following a name has
|
|
1305
|
+
* somewhere to look.
|
|
1306
|
+
*/
|
|
1307
|
+
definitions?: Record<string, TypeShape> | null;
|
|
1302
1308
|
identity: {
|
|
1303
1309
|
name: string;
|
|
1304
1310
|
kind: CodeUnitKind;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,86 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { createHash } from "crypto";
|
|
3
3
|
|
|
4
|
+
// src/inputReads.ts
|
|
5
|
+
function inputReadsOf(args) {
|
|
6
|
+
const found = /* @__PURE__ */ new Map();
|
|
7
|
+
const keep = (read) => {
|
|
8
|
+
if (read === null) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
found.set(`${read.input}.${read.path.join(".")}`, read);
|
|
12
|
+
};
|
|
13
|
+
for (const value of args.values) {
|
|
14
|
+
keep(readOf(value));
|
|
15
|
+
}
|
|
16
|
+
for (const list of args.conditions) {
|
|
17
|
+
for (const predicate of list) {
|
|
18
|
+
for (const value of valuesIn(predicate)) {
|
|
19
|
+
keep(readOf(value));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return [...found.values()].sort(
|
|
24
|
+
(a, b) => a.input.localeCompare(b.input) || a.path.join(".").localeCompare(b.path.join("."))
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
function readOf(value, depth = 0) {
|
|
28
|
+
if (depth > 12) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
if (value.type === "input") {
|
|
32
|
+
return { input: value.inputRef, path: [...value.path] };
|
|
33
|
+
}
|
|
34
|
+
if (value.type !== "derived") {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const inner = readOf(value.from, depth + 1);
|
|
38
|
+
if (inner === null) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const step = stepOf(value.derivation);
|
|
42
|
+
return step === null ? inner : { input: inner.input, path: [...inner.path, step] };
|
|
43
|
+
}
|
|
44
|
+
function stepOf(derivation) {
|
|
45
|
+
if (derivation.type === "propertyAccess") {
|
|
46
|
+
return typeof derivation.property === "string" ? derivation.property : null;
|
|
47
|
+
}
|
|
48
|
+
if (derivation.type === "destructured") {
|
|
49
|
+
return typeof derivation.field === "string" ? derivation.field : null;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
function valuesIn(predicate, depth = 0) {
|
|
54
|
+
if (depth > 12) {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
const out = [];
|
|
58
|
+
const record = predicate;
|
|
59
|
+
for (const value of Object.values(record)) {
|
|
60
|
+
if (value === null || typeof value !== "object") {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (Array.isArray(value)) {
|
|
64
|
+
for (const item of value) {
|
|
65
|
+
out.push(...nested(item, depth));
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
out.push(...nested(value, depth));
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
function nested(value, depth) {
|
|
74
|
+
if (value === null || typeof value !== "object") {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
const kind = value.type;
|
|
78
|
+
if (kind === "input" || kind === "derived") {
|
|
79
|
+
return [value];
|
|
80
|
+
}
|
|
81
|
+
return valuesIn(value, depth + 1);
|
|
82
|
+
}
|
|
83
|
+
|
|
4
84
|
// src/packHelpers.ts
|
|
5
85
|
function httpRouteDiscovery(opts) {
|
|
6
86
|
const kind = opts.kind ?? "handler";
|
|
@@ -21,6 +101,12 @@ function httpRouteDiscovery(opts) {
|
|
|
21
101
|
}
|
|
22
102
|
|
|
23
103
|
// src/index.ts
|
|
104
|
+
function valuesOfOutput(output) {
|
|
105
|
+
if (output.type === "response" && output.statusCode !== null) {
|
|
106
|
+
return [output.statusCode];
|
|
107
|
+
}
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
24
110
|
var DEFAULT_OPTIONS = { gapHandling: "permissive" };
|
|
25
111
|
function makeTransitionId(functionName, branch) {
|
|
26
112
|
const { terminal } = branch;
|
|
@@ -54,6 +140,10 @@ function assembleSummary(raw, options = DEFAULT_OPTIONS) {
|
|
|
54
140
|
const confidence = assessConfidence(raw);
|
|
55
141
|
const inputs = raw.parameters.map(paramToInput);
|
|
56
142
|
const metadata = buildMetadata(raw);
|
|
143
|
+
const reads = inputReadsOf({
|
|
144
|
+
conditions: transitions.map((t) => t.conditions),
|
|
145
|
+
values: transitions.flatMap((t) => valuesOfOutput(t.output))
|
|
146
|
+
});
|
|
57
147
|
return {
|
|
58
148
|
kind: raw.identity.kind,
|
|
59
149
|
location: {
|
|
@@ -71,6 +161,8 @@ function assembleSummary(raw, options = DEFAULT_OPTIONS) {
|
|
|
71
161
|
transitions,
|
|
72
162
|
gaps,
|
|
73
163
|
confidence,
|
|
164
|
+
...reads.length > 0 ? { inputReads: reads } : {},
|
|
165
|
+
...raw.definitions !== void 0 && raw.definitions !== null ? { definitions: raw.definitions } : {},
|
|
74
166
|
...metadata !== null ? { metadata } : {}
|
|
75
167
|
};
|
|
76
168
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suss/extractor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
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,7 @@
|
|
|
45
45
|
"typecheck": "tsc --noEmit"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@suss/behavioral-ir": "0.
|
|
48
|
+
"@suss/behavioral-ir": "0.3.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"tsup": "*",
|