@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 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.1.1",
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.1.1"
48
+ "@suss/behavioral-ir": "0.3.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "tsup": "*",