@suss/adapter-typescript 0.3.2 → 0.5.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/README.md CHANGED
@@ -6,11 +6,33 @@ TypeScript language adapter for suss. It extracts behavioral structure from Type
6
6
 
7
7
  `@suss/adapter-typescript` is the TypeScript language adapter. It walks ASTs via ts-morph, identifies code units (handlers, loaders, actions, client call sites), and emits `RawCodeStructure` objects that the extractor assembles into `BehavioralSummary` IR.
8
8
 
9
- Supports both provider-side extraction (handler registration, terminal discovery, contract reading, body-shape extraction) and client-side extraction (call-site discovery, enclosing-function lifting, response field tracking via `expectedInput`).
9
+ It supports both provider-side extraction (handler registration, terminal discovery, contract reading, body-shape extraction) and client-side extraction (call-site discovery, enclosing-function lifting, response field tracking via `expectedInput`).
10
10
 
11
- ## Where it sits in suss
11
+ ## Where it fits in suss
12
12
 
13
- Imports `@suss/behavioral-ir` for type references and `@suss/extractor` for the `RawCodeStructure` contract. Framework packs and the CLI consume it. It sits one level above the extractor in the pipeline, feeding it raw structures produced from TypeScript AST analysis.
13
+ It imports `@suss/behavioral-ir` for type references and `@suss/extractor` for the `RawCodeStructure` contract. Framework packs and the CLI consume it. It runs one level above the extractor in the pipeline, feeding it raw structures produced from TypeScript AST analysis.
14
+
15
+ ## How a project is loaded
16
+
17
+ ts-morph parses every file in the tsconfig include glob when a `Project` is constructed, which on a monorepo is thousands of files the extraction never touches. The bootstrap avoids that in four steps:
18
+
19
+ 1. Parse the tsconfig for its file list, without any AST work.
20
+ 2. Read each file concurrently and run `ts.preProcessFile`, a token scan roughly ten times cheaper than a parse.
21
+ 3. Keep the files whose imports match some active pack's `requiresImport` gate.
22
+ 4. Add only those to the `Project`.
23
+
24
+ The closure pass loads the rest as symbol resolution reaches them. It will only lazy-load files the tsconfig already knew about, so a run never pulls in `node_modules` content nobody asked for.
25
+
26
+ ### Deep re-export chains
27
+
28
+ The compiler finds files by recursing. It reads a file, resolves that file's imports, then reads each of those the same way. If you hand it one file at the top of a long chain, it will descend the entire chain in a single pass, and a barrel chain a few hundred modules deep will overflow the call stack. A gated run makes that likely, because the bootstrap only loaded the entry file.
29
+
30
+ Two passes get ahead of the compiler. Both walk the graph iteratively, starting from the far end, so that by the time the compiler asks about any module, the one below it has already been resolved.
31
+
32
+ - **Loading.** Before a run walks any file, we load that file's import graph bottom up, so nothing is added until everything it imports is already there. We work out the graph by scanning tokens and resolving module paths, never by building a program. We only load files the project could already reach; anything that resolves under `node_modules` we leave for whoever asks for it. All the roots share a single visited set, so a file that several roots reach gets read once instead of once per root. The pass runs at the start, as soon as we know which files the run will walk, because anything that touches the checker builds the program, and discovery gets there long before we ask a module what it exports. It cannot run any earlier than that: a file that showed up before we fixed the list would get walked for units too, and that would change what the run reports.
33
+ - **Alias warming.** Once the graph is loaded, we resolve each file's import bindings and export specifiers from the bottom up, so `export { x } from "./next"` never puts a whole chain on the stack. We only do this for graphs at least `WARM_DEPTH` deep. That number is well below the depth the compiler manages on its own, and well above anything an ordinary barrel file reaches, so all it decides is where we spend time. Warming changes the order things resolve in, never what they resolve to.
34
+
35
+ If the warmed compiler still cannot follow a chain, we record that rather than throwing. A provider whose exports we could not read would otherwise look exactly like one that exports nothing, so we note the file in the extraction report and let the run finish with the summaries it has.
14
36
 
15
37
  ## Status
16
38