@suss/adapter-typescript 0.33.1 → 0.34.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.d.cts CHANGED
@@ -1,22 +1,64 @@
1
- import { SourceFile, Node, Project, FunctionDeclaration, FunctionExpression, ArrowFunction, MethodDeclaration, Symbol, CallExpression, PropertyAccessExpression, TaggedTemplateExpression, ImportDeclaration, ArrayLiteralExpression, ObjectLiteralExpression, ObjectLiteralElementLike, Expression, NewExpression, Identifier } from 'ts-morph';
2
- import { TransparentWrapper, RawCondition, DiscoveryPattern, TerminalPattern, InputMappingPattern, EffectArg, CallOps, LanguageAdapter, PatternPack, ExtractorOptions, TimingReport, CacheDiagnostic, ExtractionReport, InvocationRecognizer, AccessRecognizer, RawCodeStructure, RawTerminal, RawBranch, configuredCallOption, RawDeclaredContract, ContractPattern, AstCapableOps, ResponsePropertyMapping } from '@suss/extractor';
1
+ import { SourceFile, Node, Project, FunctionDeclaration, FunctionExpression, ArrowFunction, MethodDeclaration, Symbol, CallExpression, NewExpression, TaggedTemplateExpression, PropertyAccessExpression, ImportDeclaration, ArrayLiteralExpression, ObjectLiteralExpression, ObjectLiteralElementLike, Expression, Identifier } from 'ts-morph';
2
+ import { PatternPack, TransparentWrapper, ParameterSupplier, RawCondition, DiscoveryPattern, TerminalPattern, InputMappingPattern, ArgumentParser, StatedSlot, AstCapableOps, CallOps, EffectArg, LanguageAdapter, ExtractorOptions, TimingReport, CacheDiagnostic, ExtractionReport, DeclaredModule, InvocationRecognizer, AccessRecognizer, RawCodeStructure, RawTerminal, RawBranch, configuredCallOption, RawDeclaredContract, ContractPattern, ResponsePropertyMapping } from '@suss/extractor';
3
3
  export { EmptyStage, ExtractionReport, PackFunnel, Timer, TimingReport, computeContentHash } from '@suss/extractor';
4
- import { MessageBusSemantics, DeployableUnit, UnfollowedCall, WrapperReference, BehavioralSummary, BoundaryBinding, Predicate, TypeShape, ValueRef } from '@suss/behavioral-ir';
5
- import { ExplainStats, WhyExplained, ValueLocation } from '@suss/resolution';
4
+ import { MessageBusSemantics, DeployableUnit, UnfollowedCall, WrapperReference, Effect, BehavioralSummary, BoundaryBinding, Predicate, TypeShape, ValueRef } from '@suss/behavioral-ir';
5
+ import { ExplainStats, SourceLeaf, ValueUses, WhyExplained, ValueLocation } from '@suss/resolution';
6
6
  export { ExplainStats, ValueLocation, WhyExplained } from '@suss/resolution';
7
7
  import { Proof, Atom } from '@suss/datalog';
8
8
  import { z } from 'zod';
9
9
 
10
+ /** How the packs in a run spell the parts of the process nothing declares. */
11
+ interface RuntimeSpellings {
12
+ streamObjects: readonly string[];
13
+ exitCalls: readonly string[];
14
+ exitCodeWrites: readonly string[];
15
+ }
16
+
17
+ /**
18
+ * A library's own module, written into the project by that library's
19
+ * code generator.
20
+ *
21
+ * A pack says which file its generator leaves beside the module it
22
+ * wrote, and a directory containing that file counts as the package. A
23
+ * pack whose generator leaves no such file says instead where the
24
+ * project's configuration tells the generator to write. The README says
25
+ * why the import gate needs this.
26
+ */
27
+
28
+ type DirFinder = NonNullable<PatternPack["generatedModuleDirs"]>;
29
+ declare class GeneratedModules {
30
+ private readonly markers;
31
+ private readonly finders;
32
+ private readonly generatedDirs;
33
+ private readonly declaredDirs;
34
+ constructor(markers: ReadonlyArray<string>, finders?: ReadonlyArray<{
35
+ pack: string;
36
+ find: DirFinder;
37
+ }>);
38
+ /** Whether any pack asked for a generated module to be looked for. */
39
+ get declared(): boolean;
40
+ /** Distinguishes two asks about one package that declare different markers. */
41
+ get key(): string;
42
+ /**
43
+ * Whether any of this file's specifiers points into a directory the
44
+ * generator wrote. A specifier can name the directory itself or a
45
+ * file in it, so both are checked.
46
+ */
47
+ reachedFrom(fromFile: string, specifiers: ReadonlyArray<string>): boolean;
48
+ private isGenerated;
49
+ private isDeclaredOutput;
50
+ }
51
+
10
52
  /** One question: do these files reach any of these packages. */
11
53
  interface FileSetQuery {
12
54
  sourceFiles: ReadonlyArray<SourceFile>;
13
55
  packages: ReadonlyArray<string>;
14
56
  /**
15
- * Files the asking pack's code generator leaves beside a module it
16
- * wrote into the project. A relative import into such a directory
17
- * counts as an import of the package.
57
+ * Where the asking pack's code generator writes a module into the
58
+ * project. A relative import into such a directory counts as an
59
+ * import of the package.
18
60
  */
19
- generatedMarkers?: ReadonlyArray<string>;
61
+ generated?: GeneratedModules;
20
62
  }
21
63
 
22
64
  /**
@@ -33,6 +75,16 @@ interface FileSetQuery {
33
75
  * local barrel re-exports the SDK.
34
76
  */
35
77
 
78
+ /** One place a value's walk ended, with the nodes the store keyed it by. */
79
+ interface SourceFound {
80
+ leaf: SourceLeaf;
81
+ /** The node the walk ended at, or null when the store keyed none. */
82
+ node: Node | null;
83
+ /** The read at a computed key on the way, when there was one. */
84
+ computedAt: Node | null;
85
+ /** The function a parameter the walk ended at belongs to. */
86
+ parameterOf: Node | null;
87
+ }
36
88
  interface ExplainCallableOptions {
37
89
  /** A second file to walk out from; see `resolveCallable`. */
38
90
  alsoFrom?: SourceFile;
@@ -82,19 +134,25 @@ declare class ResolutionStore {
82
134
  /** Keyed by value and site both, since one value differs per site. */
83
135
  private readonly writtenUnderSite;
84
136
  private readonly constructionSites;
137
+ /** What each local's reads do with it, by its declaration. A local's function is walked whole, so an answer stays true. */
138
+ private readonly localUses;
85
139
  /** Files the most recent query read, for the memo to keep. */
86
140
  private lastQueryWalked;
87
141
  /** See `environmentSiteFiles`; null until the first env question. */
88
142
  private envSiteFiles;
89
143
  /** See `environmentAnswers`; null until the first env question. */
90
144
  private envAnswers;
145
+ /** See `streamAnswers`: the declared streams each expression reaches. */
146
+ private streamsReached;
91
147
  private readonly declarations;
92
148
  private readonly graph;
93
149
  /** See `notePossibleCallers`. */
94
150
  private readonly possibleCallers;
95
151
  private readonly callerFilesRead;
96
152
  private stale;
97
- constructor(wrappers?: TransparentWrapper[], environmentObjects?: readonly string[]);
153
+ constructor(wrappers?: TransparentWrapper[], environmentObjects?: readonly string[], runtime?: RuntimeSpellings, parameterSuppliers?: readonly ParameterSupplier[]);
154
+ /** A store with the wrappers and runtime objects these packs declare, as an extraction over them starts from. */
155
+ static forPacks(packs: readonly PatternPack[]): ResolutionStore;
98
156
  /**
99
157
  * `alsoFrom` is a second file to walk out from, for a caller that
100
158
  * knows where the value it is asking about was set up. The walk
@@ -110,6 +168,12 @@ declare class ResolutionStore {
110
168
  * folding into the same nothing as a chain that went nowhere.
111
169
  */
112
170
  resolveCallableSources(value: Node, alsoFrom?: SourceFile): Node[];
171
+ /**
172
+ * `resolveCallable` for several values, asked as one question. A file
173
+ * with a receiver at every call would otherwise derive and clear the
174
+ * rules once per receiver.
175
+ */
176
+ resolveCallables(values: readonly Node[]): Map<Node, Node | null>;
113
177
  /**
114
178
  * The witness proof behind `resolveCallable`'s answer. Resolves the
115
179
  * value first, which extracts the files the question demands, then
@@ -128,11 +192,43 @@ declare class ResolutionStore {
128
192
  * single-answer question here.
129
193
  */
130
194
  resolveReturnedCallable(call: Node): Node | null;
195
+ /**
196
+ * The function a call through this value runs: the one it comes down
197
+ * to, and failing that the one it gives back, so a name written as
198
+ * `useNavigator()` runs what that factory returned. Both answers come
199
+ * from the same derivation, so asking them together costs one query.
200
+ */
201
+ resolveCalledFunction(value: Node): Node | null;
202
+ /**
203
+ * The batched form, for a caller with a body's worth of callees: one
204
+ * demand set and one derivation shared by all of them, where asking
205
+ * each alone re-derives once per value.
206
+ */
207
+ resolveCalledFunctions(values: readonly Node[]): Map<Node, Node | null>;
208
+ private calledFunctionOf;
131
209
  /**
132
210
  * For a value that is neither a function nor an object, such as a
133
211
  * GraphQL document kept in a constant in another file.
134
212
  */
135
213
  resolveWrittenValue(value: Node): Node | null;
214
+ /**
215
+ * Where each value came from, asked as one question: every place the
216
+ * walk from it ended, with the node there and, for a parameter, the
217
+ * function it belongs to.
218
+ */
219
+ sourcesOf(values: readonly Node[]): Map<Node, SourceFound[]>;
220
+ /**
221
+ * `resolveWrittenValue` for several values, asked as one question.
222
+ * Values that share a declaration share one answer, as they do when
223
+ * asked one at a time.
224
+ */
225
+ resolveWrittenValues(values: readonly Node[]): Map<Node, Node | null>;
226
+ /**
227
+ * The class a name refers to, asked the same narrow way. A class is
228
+ * not an expression, so `resolveWrittenValue` never gives one back.
229
+ */
230
+ resolveWrittenClass(value: Node): Node | null;
231
+ private writtenAnswers;
136
232
  /**
137
233
  * The same question under one construction site: what the value is
138
234
  * when the receiver behind it is the instance that site made. A field
@@ -213,6 +309,36 @@ declare class ResolutionStore {
213
309
  * project's own sources and it happens once.
214
310
  */
215
311
  private environmentSiteFiles;
312
+ /**
313
+ * Which output stream a receiver is, for a writer standing at
314
+ * `out.write(...)`: the path a pack declared, such as
315
+ * `process.stdout`. Null when it is a stream and the source does not
316
+ * settle which one, and undefined when nothing says it is a stream.
317
+ *
318
+ * A receiver the source does not spell as a stream is looked up in
319
+ * one answer worked out for the whole run, so a question is never
320
+ * asked per call. A parameter nothing in the run passes a stream to
321
+ * is still a stream when it is annotated as one of `streamTypes`.
322
+ */
323
+ streamPathOf(receiver: Node, streamTypes: readonly string[]): string | null | undefined;
324
+ private streamAnswers;
325
+ /**
326
+ * The environment's loop for the streams: ask, read the callee of every
327
+ * call that hands a stream on, and ask again until no new call turns up.
328
+ */
329
+ private followStreams;
330
+ private askStreams;
331
+ /**
332
+ * The functions whose return becomes the process's exit code, asked
333
+ * once from the files that end the process or set its exit code. Each
334
+ * value that ends up as the code seeds the walk; DESIGN.md in the
335
+ * resolution package says how it gets from there to a function.
336
+ */
337
+ exitCodeFunctions(project: Project): readonly Node[];
338
+ /** The values that end up as the exit code: an exit call's first argument, or what is assigned to the code. */
339
+ private exitSinks;
340
+ /** Whether the parameter a name refers to is annotated as one of these types. */
341
+ private annotatedAsOneOf;
216
342
  /**
217
343
  * Whether running this function hands back that call: returned
218
344
  * outright, written into a name and returned, or a shorthand body.
@@ -220,6 +346,13 @@ declare class ResolutionStore {
220
346
  * what keeps a wrapper's own result apart from the library's.
221
347
  */
222
348
  returnsCall(func: Node, call: Node): boolean;
349
+ /**
350
+ * What the reads of a local do with it, when `receiver` is a local a
351
+ * function declares once as `construction`. Null for anything else,
352
+ * such as a module-level value, which some other file may serve.
353
+ */
354
+ usesOfLocal(receiver: Node, construction: Node): ValueUses | null;
355
+ private askLocalUses;
223
356
  /**
224
357
  * Files a later question about a parameter may find a caller in.
225
358
  * Without this the search falls back to every file the project has
@@ -255,7 +388,8 @@ declare class ResolutionStore {
255
388
  * declared name.
256
389
  */
257
390
  private constructionComesFrom;
258
- private calleeNameOf;
391
+ /** The callee of a call, as written. */
392
+ private calleeTextOf;
259
393
  /**
260
394
  * Which names from `modules` this value comes down to, either by being
261
395
  * one of them under a local name or by calling into one. Getting
@@ -295,6 +429,12 @@ declare class ResolutionStore {
295
429
  private lookupImportOrigins;
296
430
  private lookupImportedNames;
297
431
  private askAbout;
432
+ /**
433
+ * One question about several values: one demand set, one round of
434
+ * extraction and one derivation shared by all of them. Asking each
435
+ * alone pays the rounds, the clear and the allocation once per value.
436
+ */
437
+ private askAboutAll;
298
438
  /**
299
439
  * Extract the seed files, then every module the rules ask for, until
300
440
  * they ask for nothing new. The files a question reads are then fixed
@@ -331,7 +471,12 @@ declare class ResolutionStore {
331
471
  */
332
472
  private seedValue;
333
473
  private lookupObject;
474
+ /**
475
+ * A factory returning a wrapper's call gives back the wrapper's own
476
+ * closure and the function it unwraps. The unwrapped one wins.
477
+ */
334
478
  private lookupReturned;
479
+ private singleFunctionIn;
335
480
  /**
336
481
  * Two candidates give null, since ambiguity is nothing. The value
337
482
  * itself is never a result either, or an identifier whose chain went
@@ -341,6 +486,8 @@ declare class ResolutionStore {
341
486
  * construction makes an instance of. The README says why.
342
487
  */
343
488
  private lookupWritten;
489
+ /** The one class among what a value is written as, under the same policy. */
490
+ private lookupWrittenClass;
344
491
  /**
345
492
  * Read these files' facts now, before anything asks a question.
346
493
  *
@@ -388,6 +535,27 @@ declare class ResolutionStore {
388
535
  private extractFile;
389
536
  }
390
537
 
538
+ /**
539
+ * The path an application puts in front of every route it serves.
540
+ *
541
+ * NestJS serves each decorated route under whatever the bootstrap's
542
+ * `app.setGlobalPrefix("api")` says, in a file with no controller in it.
543
+ * A call counts when the store says its receiver is the app the
544
+ * framework's factory made, following a parameter to every caller. The
545
+ * prefix and its exclusions are read through the value evaluator, and
546
+ * every call in the run has to agree, or no prefix is applied.
547
+ */
548
+
549
+ /** A route the prefix leaves out. A null method leaves out every verb. */
550
+ interface ExcludedRoute {
551
+ path: string;
552
+ method: string | null;
553
+ }
554
+ interface GlobalPrefix {
555
+ prefix: string;
556
+ excluded: ExcludedRoute[];
557
+ }
558
+
391
559
  type FunctionRoot = FunctionDeclaration | FunctionExpression | ArrowFunction | MethodDeclaration;
392
560
  /**
393
561
  * Public API: returns RawCondition[] with structured: null.
@@ -564,6 +732,13 @@ interface DiscoveredUnit {
564
732
  method: string | null;
565
733
  path: string | null;
566
734
  };
735
+ /**
736
+ * The status the framework sends for a response this unit's body
737
+ * states none for, when the route declares one: `@HttpCode(204)`, or
738
+ * the 201 NestJS sends for `@Post`. It replaces the default on the
739
+ * pack's response terminals for this unit alone.
740
+ */
741
+ defaultStatusCode?: number;
567
742
  /**
568
743
  * Populated by a pack's `discoverUnits` callback for a message-bus
569
744
  * consumer whose channel the code gives (a handler factory whose
@@ -651,6 +826,11 @@ interface MountPrefixIndex {
651
826
  * re-checks a stored prefix against a rebuilt index this way).
652
827
  */
653
828
  prefixForId?(childId: string): string;
829
+ /**
830
+ * The prefix the calls keyed by `globalPrefixKey` agree an application
831
+ * puts in front of its routes. A key with no entry has none.
832
+ */
833
+ globalPrefixes?: ReadonlyMap<string, GlobalPrefix>;
654
834
  }
655
835
  /**
656
836
  * What the project helper index says it has already expanded, which the
@@ -666,6 +846,18 @@ interface ExpandedRegistrations {
666
846
  */
667
847
  declare function discoverUnits(sourceFile: SourceFile, patterns: DiscoveryPattern[], resolution?: ResolutionStore, mountPrefixes?: MountPrefixIndex, expandedElsewhere?: ExpandedRegistrations): DiscoveredUnit[];
668
848
 
849
+ /**
850
+ * What every unit is read with beyond its own pack's patterns, whichever
851
+ * pack discovered it: the terminals a runtime ends the process with, and
852
+ * the command-line parsers it provides. A pack's recognizers reach every
853
+ * unit the same way, and are collected on their own.
854
+ */
855
+
856
+ interface EveryUnitDeclarations {
857
+ terminals: readonly TerminalPattern[];
858
+ argumentParsers: readonly ArgumentParser[];
859
+ }
860
+
669
861
  /**
670
862
  * Nested function nodes a pack claimed as sub-units. The unit-body
671
863
  * walkers stop at these so the sub-unit's behavior isn't double-counted
@@ -680,6 +872,71 @@ declare const NO_BARRIERS: DescentBarriers;
680
872
  */
681
873
  declare function startsItsOwnScope(node: Node): boolean;
682
874
 
875
+ /**
876
+ * What this adapter can tell a declared pack about a call.
877
+ *
878
+ * Every question here was already worked out somewhere in this adapter,
879
+ * once per pack that needed it. Collecting them behind the one
880
+ * interface `@suss/extractor` declares is what lets a pack stop being a
881
+ * walk over ts-morph and start being data.
882
+ *
883
+ * Two of the receiver origins are implemented. The migration plan for
884
+ * #542 lists four more, and each one adds an entry to `ORIGIN` beside
885
+ * the union member it matches.
886
+ */
887
+
888
+ /**
889
+ * A call, a construction, or a tagged template, which all ask the same
890
+ * questions. A tagged template is a call the source wrote without
891
+ * parentheses: the tag is the callee and the template is the one
892
+ * argument, which is how a pack reaches a statement written that way
893
+ * without a second grammar for it.
894
+ */
895
+ type Called = CallExpression | NewExpression | TaggedTemplateExpression;
896
+ /** One-hop lookup from a written name to the value it was bound to. */
897
+ type Resolve = (value: Node) => Node | null;
898
+ /**
899
+ * What the ops read a call through. A reading left out reads only what
900
+ * the source spells at the call.
901
+ */
902
+ interface CallReading {
903
+ /** One-hop lookup from a written name to the value it was bound to. */
904
+ readonly resolve?: Resolve;
905
+ readonly originatesFrom?: OriginatesFrom | undefined;
906
+ readonly anchorCallsOf?: AnchorCallsOf | undefined;
907
+ /** The run's store, which the value evaluator follows names through. */
908
+ readonly resolution?: ResolutionStore | undefined;
909
+ /**
910
+ * The arguments of the walk this call was visited by. A value is read
911
+ * through it in place of `resolve`, and it asks the store about any
912
+ * value it has no answer for.
913
+ */
914
+ readonly walk?: WalkArguments | undefined;
915
+ /** Where a recognizer's `statesSlots` goes, when somebody listens. */
916
+ readonly statesSlots?: ((effect: Effect, slots: readonly StatedSlot[]) => void) | undefined;
917
+ }
918
+ /**
919
+ * The arguments of every call one walk visits. A chain that steps to
920
+ * every argument would otherwise ask the store about each one at each
921
+ * call, and each question runs and clears the rules once.
922
+ */
923
+ interface WalkArguments {
924
+ /** Ask about these positions of every call in the walk, in one question. */
925
+ settle(first: number, last?: number): void;
926
+ /**
927
+ * Ask about the receiver of every call in the walk whose method is one
928
+ * of these, in one question.
929
+ */
930
+ settleReceivers(methods: ReadonlySet<string>): void;
931
+ /**
932
+ * What a value was written as: the walk's own answer for an argument
933
+ * a `settle` covered, and the store's for anything else.
934
+ */
935
+ writtenValueOf(value: Node): Node | null;
936
+ }
937
+ /** What a declared pack can ask about one TypeScript call. */
938
+ declare function callOpsFor(call: Called, reading?: CallReading): AstCapableOps;
939
+
683
940
  /**
684
941
  * invocationEffects.ts: capture every call in a unit's body as an
685
942
  * `invocation` RawEffect, wherever the call is written: a statement of
@@ -695,6 +952,24 @@ declare function startsItsOwnScope(node: Node): boolean;
695
952
  * ordered and what `async` means.
696
953
  */
697
954
 
955
+ /** A column a recognized effect writes or picks rows by, and its value. */
956
+ interface SlotValue {
957
+ slot: StatedSlot["slot"];
958
+ name: string;
959
+ value: Node;
960
+ }
961
+ /**
962
+ * What a recognizer says about each effect it built at one call, kept
963
+ * until the dispatch loop knows which effects the recognizer returned.
964
+ */
965
+ declare class SlotsStated {
966
+ private readonly byEffect;
967
+ readonly listen: (effect: Effect, slots: readonly StatedSlot[]) => void;
968
+ /** The slots stated for an effect, ready to spread onto its location. */
969
+ of(effect: Effect): {
970
+ slots?: SlotValue[];
971
+ };
972
+ }
698
973
  /**
699
974
  * Context handed to TypeScript-adapter access recognizers: sister
700
975
  * to TsInvocationRecognizerContext but for property-access nodes.
@@ -790,7 +1065,7 @@ interface TsInvocationRecognizerContext {
790
1065
  * A pack's tests build it here too, so a pack that passes them has run
791
1066
  * against the context extraction gives it.
792
1067
  */
793
- declare function invocationContextFor(call: CallExpression, resolution?: ResolutionStore, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf): TsInvocationRecognizerContext;
1068
+ declare function invocationContextFor(call: CallExpression, resolution?: ResolutionStore, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf, walk?: WalkArguments, stated?: SlotsStated): TsInvocationRecognizerContext;
794
1069
  /**
795
1070
  * Whether a value's chain reaches the module, asked of the store. The
796
1071
  * adapter binds it; a context built bare falls back to the checker's
@@ -823,7 +1098,7 @@ type Accessed = PropertyAccessExpression | CallExpression | TaggedTemplateExpres
823
1098
  * A pack's tests build it here too, so a pack that passes them has run
824
1099
  * against the context extraction gives it.
825
1100
  */
826
- declare function accessContextFor(node: Accessed, sourceFile: SourceFile, resolution?: ResolutionStore, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf): TsAccessRecognizerContext;
1101
+ declare function accessContextFor(node: Accessed, sourceFile: SourceFile, resolution?: ResolutionStore, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf, walk?: WalkArguments, stated?: SlotsStated): TsAccessRecognizerContext;
827
1102
 
828
1103
  /** Resolves a helper callee to its declaration; the adapter binds the store's ask. */
829
1104
  type ResolveCallee = (callee: Node) => Node | null;
@@ -843,7 +1118,7 @@ type ResolveCallee = (callee: Node) => Node | null;
843
1118
  * framework or a runtime belongs to a pack.
844
1119
  */
845
1120
 
846
- declare function extractCodeStructure(unit: DiscoveredUnit, pack: PatternPack, invocationRecognizers?: InvocationRecognizer[], accessRecognizers?: AccessRecognizer[], barriers?: DescentBarriers, resolution?: ResolutionStore, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf, resolveCallee?: ResolveCallee): RawCodeStructure;
1121
+ declare function extractCodeStructure(unit: DiscoveredUnit, pack: PatternPack, invocationRecognizers?: InvocationRecognizer[], accessRecognizers?: AccessRecognizer[], barriers?: DescentBarriers, resolution?: ResolutionStore, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf, resolveCallee?: ResolveCallee, everyUnit?: EveryUnitDeclarations): RawCodeStructure;
847
1122
  interface TypeScriptAdapterConfig {
848
1123
  tsConfigFilePath?: string;
849
1124
  /**
@@ -864,12 +1139,36 @@ interface TypeScriptAdapterConfig {
864
1139
  onExtractionReport?: (report: ExtractionReport) => void;
865
1140
  /** Absolute. `.suss/cache/` beside the tsconfig; `null` turns it off. */
866
1141
  cacheDir?: string | null;
1142
+ /** The modules the project lists in `suss.json`, with absolute paths. */
1143
+ modules?: readonly DeclaredModule[];
867
1144
  }
868
1145
  interface TypeScriptAdapter extends LanguageAdapter {
869
1146
  /** Kept off `LanguageAdapter`, so a caller needing ts-morph asks for it. */
870
1147
  readonly tsProject: Project;
871
1148
  extractFromFiles(filePaths: string[]): Promise<BehavioralSummary[]>;
872
1149
  extractAll(): Promise<BehavioralSummary[]>;
1150
+ /**
1151
+ * Re-reads the files that changed on disk since the last `extractAll`,
1152
+ * so the next one describes the tree as it is now and keeps the parse
1153
+ * of every other file. A process that keeps the adapter between runs
1154
+ * calls this before each one. `changedPaths` are files the caller knows
1155
+ * were written; the rest are found by their stamps.
1156
+ */
1157
+ refresh(changedPaths?: readonly string[]): RefreshReport;
1158
+ /**
1159
+ * Loads the files a run walks and everything they import, and builds
1160
+ * the compiler's program, without extracting. A run served whole from
1161
+ * the cache loads nothing, so a process that keeps the adapter calls
1162
+ * this once while nobody is waiting, and the first edit after that
1163
+ * finds the program built.
1164
+ */
1165
+ loadProgram(): Promise<void>;
1166
+ }
1167
+ interface RefreshReport {
1168
+ /** Files parsed again because their text changed. */
1169
+ changed: string[];
1170
+ /** Why the adapter started over with a new project, or null. */
1171
+ startedOver: string | null;
873
1172
  }
874
1173
  declare function createTypeScriptAdapter(suppliedConfig: TypeScriptAdapterConfig): TypeScriptAdapter;
875
1174
 
@@ -1220,6 +1519,8 @@ declare function writtenNodeOf(value: Node, resolution: ResolutionStore | undefi
1220
1519
  * empty" from "could not read" (#123).
1221
1520
  */
1222
1521
  declare function stringValueOf(value: Node, resolution: ResolutionStore | undefined): string | null;
1522
+ /** The number this value comes to, or null when it does not settle to one. */
1523
+ declare function numberValueOf(value: Node, resolution: ResolutionStore | undefined): number | null;
1223
1524
  /**
1224
1525
  * The string a named property of an object is set to, with the object
1225
1526
  * and the value each read through whatever name they were given.
@@ -1285,6 +1586,8 @@ declare function createTsDiscoveryContext(resolution?: ResolutionStore): TsDisco
1285
1586
  interface WhySessionOptions {
1286
1587
  /** The project root, which paths in every answer come out relative to. */
1287
1588
  dir: string;
1589
+ /** The packs the extraction ran with, for the wrappers and environment objects they declare. */
1590
+ packs?: readonly PatternPack[];
1288
1591
  }
1289
1592
  declare class TypeScriptWhySession {
1290
1593
  private readonly project;
@@ -1343,32 +1646,6 @@ declare function resolveAliasedSymbol(symbol: Symbol): Symbol | undefined;
1343
1646
  */
1344
1647
  declare function parseConditionExpression(expr: Expression, depth?: number): Predicate | null;
1345
1648
 
1346
- /**
1347
- * What this adapter can tell a declared pack about a call.
1348
- *
1349
- * Every question here was already worked out somewhere in this adapter,
1350
- * once per pack that needed it. Collecting them behind the one
1351
- * interface `@suss/extractor` declares is what lets a pack stop being a
1352
- * walk over ts-morph and start being data.
1353
- *
1354
- * Two of the receiver origins are implemented. The migration plan for
1355
- * #542 lists four more, and each one adds an entry to `ORIGIN` beside
1356
- * the union member it matches.
1357
- */
1358
-
1359
- /**
1360
- * A call, a construction, or a tagged template, which all ask the same
1361
- * questions. A tagged template is a call the source wrote without
1362
- * parentheses: the tag is the callee and the template is the one
1363
- * argument, which is how a pack reaches a statement written that way
1364
- * without a second grammar for it.
1365
- */
1366
- type Called = CallExpression | NewExpression | TaggedTemplateExpression;
1367
- /** One-hop lookup from a written name to the value it was bound to. */
1368
- type Resolve = (value: Node) => Node | null;
1369
- /** What a declared pack can ask about one TypeScript call. */
1370
- declare function callOpsFor(call: Called, resolveWrittenValue?: Resolve, originatesFrom?: OriginatesFrom, anchorCallsOf?: AnchorCallsOf): AstCapableOps;
1371
-
1372
1649
  /**
1373
1650
  * The one resolver from a reference to the function behind it.
1374
1651
  *
@@ -1590,6 +1867,49 @@ declare function createTsSubUnitContext(): TsSubUnitContext;
1590
1867
  */
1591
1868
  declare function workspaceRootFor(anchor: string): string;
1592
1869
 
1870
+ /** What a call writes out, and whether it was serialized as JSON first. */
1871
+ interface WrittenPayload {
1872
+ shape: TypeShape | null;
1873
+ serialized: "json" | "text";
1874
+ }
1875
+ /**
1876
+ * What a call writes, for a pack recording a write to a stream.
1877
+ * `JSON.stringify(report)` writes the report as JSON, and so does a
1878
+ * template that puts nothing but whitespace around one such call, the
1879
+ * way a command ends its report with a newline. Several arguments are
1880
+ * written one after another, so their shapes come back keyed by position.
1881
+ */
1882
+ declare function writtenPayloadOf(args: readonly Node[]): WrittenPayload;
1883
+
1884
+ /**
1885
+ * The named types behind a node's type, for a pack that recognizes a
1886
+ * call by what its receiver is rather than by what it is called.
1887
+ *
1888
+ * A library rarely hands back its type bare. A client factory can return
1889
+ * the library's class joined with an extra field (`Db & { $client: Pool }`),
1890
+ * and a project can declare the client as optional (`Db | undefined`), alias
1891
+ * it, subclass it, or pass it through a type parameter. A union or an
1892
+ * intersection has no symbol of its own, so this looks through each of
1893
+ * those to the named types underneath, and the pack tests each one.
1894
+ *
1895
+ * When the checker cannot resolve the type because the library is not
1896
+ * installed, the names come from the written type, with no declaring file.
1897
+ */
1898
+
1899
+ /** One named type a receiver is, and the files that declare it. */
1900
+ interface ReceiverType {
1901
+ name: string;
1902
+ declaredIn: readonly string[];
1903
+ /**
1904
+ * The base each declaring class is written as extending. When the
1905
+ * library is not installed the checker cannot see past a project's
1906
+ * `class Db extends Client`, and a pack asks where the base came from.
1907
+ */
1908
+ extendsWritten: readonly Node[];
1909
+ }
1910
+ /** Every named type the node's type is, nearest first. */
1911
+ declare function receiverTypesOf(node: Node): ReceiverType[];
1912
+
1593
1913
  /**
1594
1914
  * version.ts: this adapter's own half of the cache key.
1595
1915
  *
@@ -1619,19 +1939,23 @@ declare function computeAdapterPacksDigest(packVersions: ReadonlyArray<{
1619
1939
  /**
1620
1940
  * defaulted.ts: whether a read has something behind it.
1621
1941
  *
1622
- * `??` and `||` are ECMAScript, not anything a pack defines, so the
1623
- * packs that record a read ask here instead of each spelling the
1624
- * operators out. This is a separate file from unwrap.ts because that
1625
- * one is about wrappers, and a fallback is not one.
1942
+ * A read is defaulted when the program still works where the value is
1943
+ * missing. Either a `??` or `||` supplies a fallback value, or the
1944
+ * program tests the value for presence, only uses it where the test
1945
+ * passed, and the path a missing value takes does not end in a throw.
1946
+ * The test can be on the read itself or on a local the read
1947
+ * initializes: a truthiness check, a comparison with `undefined` or
1948
+ * `null`, or an `in` membership test.
1949
+ *
1950
+ * All of this is ECMAScript, so the packs that record a read ask here
1951
+ * instead of each spelling the forms out. The Python and Ruby adapters
1952
+ * define the same rule for their own syntax.
1626
1953
  */
1627
1954
 
1628
1955
  /**
1629
- * Whether something else supplies a value when this read comes back
1630
- * empty. `env.X ?? "default"` and `env.X || other` both do, and so does
1631
- * the middle of a chain: in `env.A || env.B || undefined`, B's fallback
1632
- * is the chain's tail. The climb stops when the read is the final
1633
- * operand (`getDefault() ?? env.X`), where the read is itself the
1634
- * fallback and its absence propagates.
1956
+ * Whether the program copes with this read coming back empty: something
1957
+ * falls back from it, or every use of its value runs only after a
1958
+ * presence test has passed.
1635
1959
  */
1636
1960
  declare function isDefaultedAt(node: Node): boolean;
1637
1961
 
@@ -1658,4 +1982,4 @@ declare function climbSyntax(node: Node): Node;
1658
1982
  */
1659
1983
  declare function peelValue(node: Node): Node;
1660
1984
 
1661
- export { ADAPTER_VERSION, type Accessed, type CallAccountingEntry, type CallAccountingOutcome, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DescentBarriers, type DiscoveredUnit, type EnvironmentNamers, type ExplainCallableOptions, type ExplainedResolution, type FoundTerminal, type FunctionRoot, GENERIC_TERMINALS, type ImportScanOptions, NO_BARRIERS, type ObservedStubCall, type RawBranchResult, type ReadNameOptions, ResolutionStore, type StubCallEvidence, type StubEvidenceOptions, TSCONFIG_NAMES, type TsDiscoveryContext, type TsInvocationRecognizerContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, TypeScriptWhySession, type WhySessionOptions, accessContextFor, arrayLiteralOf, buildProjectHelperIndex, callOpsFor, climbSyntax, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, couldNameAValue, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, declarationsBehind, discoverUnits, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findEnclosingFunction, findNearestTsconfig, findTerminals, functionTargetOf, functionValueOf, hasBody, importDeclarationsOf, importedNamesOf, importedRootsOf, invocationContextFor, isDefaultedAt, isImportedFrom, methodDeclaredIn, namedImportsOf, objectLiteralOf, parseConditionExpression, peelSyntax, peelValue, propertiesOf, propertyFunctionOf, propertyNameOf, propertyOf, propertyValueOf, readConfiguredCall, readContract, readContractForClientCall, readName, resolveAliasedSymbol, resolveSubject, rootIdentifier, startsItsOwnScope, stringPropertyOf, stringValueOf, stubEvidence, stubEvidenceIn, symbolBehind, toFunctionRoot, workspaceRootFor, writtenNodeOf };
1985
+ export { ADAPTER_VERSION, type Accessed, type CallAccountingEntry, type CallAccountingOutcome, type ClientCallSite, type ConfiguredCallContext, type ConfiguredCallRead, type ConfiguredCallSpec, type ContractReadResult, type DescentBarriers, type DiscoveredUnit, type EnvironmentNamers, type ExplainCallableOptions, type ExplainedResolution, type FoundTerminal, type FunctionRoot, GENERIC_TERMINALS, type ImportScanOptions, NO_BARRIERS, type ObservedStubCall, type RawBranchResult, type ReadNameOptions, type ReceiverType, type RefreshReport, ResolutionStore, type StubCallEvidence, type StubEvidenceOptions, TSCONFIG_NAMES, type TsAccessRecognizerContext, type TsDiscoveryContext, type TsInvocationRecognizerContext, type TsJsxAttributeLocation, type TsSubUnitContext, type TypeScriptAdapter, type TypeScriptAdapterConfig, TypeScriptWhySession, type WhySessionOptions, type WrittenPayload, accessContextFor, arrayLiteralOf, buildProjectHelperIndex, callOpsFor, climbSyntax, collectAncestorBranches, collectClientFieldAccesses, computeAdapterPacksDigest, couldNameAValue, createProjectWithoutTsconfig, createTsDiscoveryContext, createTsSubUnitContext, createTypeScriptAdapter, declarationsBehind, discoverUnits, exportedDeclarationsOf, extractCodeStructure, extractRawBranches, findEnclosingFunction, findNearestTsconfig, findTerminals, functionTargetOf, functionValueOf, hasBody, importDeclarationsOf, importedNamesOf, importedRootsOf, invocationContextFor, isDefaultedAt, isImportedFrom, methodDeclaredIn, namedImportsOf, numberValueOf, objectLiteralOf, parseConditionExpression, peelSyntax, peelValue, propertiesOf, propertyFunctionOf, propertyNameOf, propertyOf, propertyValueOf, readConfiguredCall, readContract, readContractForClientCall, readName, receiverTypesOf, resolveAliasedSymbol, resolveSubject, rootIdentifier, startsItsOwnScope, stringPropertyOf, stringValueOf, stubEvidence, stubEvidenceIn, symbolBehind, toFunctionRoot, workspaceRootFor, writtenNodeOf, writtenPayloadOf };