@suss/extractor 0.33.1 → 0.34.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 +3 -3
- package/dist/index.cjs +982 -225
- package/dist/index.d.cts +1335 -936
- package/dist/index.d.ts +1335 -936
- package/dist/index.js +952 -212
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { Effect, MessageBusSemantics, DeployableUnit, CodeUnitKind, RequestSpellingMetadata, BehavioralSummary, Predicate,
|
|
1
|
+
import { Effect, MessageBusSemantics, DeployableUnit, CodeUnitKind, RequestSpellingMetadata, BehavioralSummary, TypeShape, Predicate, ValueRef, RenderNode, ProvenanceSlot, BoundaryBinding, WrapperReference, TestMetadata, GraphqlDeclaredContract, ConfidenceInfo, Transition, Gap, Input, Output } from '@suss/behavioral-ir';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* What a unit reads out of
|
|
5
|
+
* What a unit reads out of its inputs.
|
|
6
6
|
*
|
|
7
7
|
* A summary already describes this, but only as a chain of `derived` nodes
|
|
8
8
|
* nested one inside the next, which anyone who wants the list has to walk
|
|
9
9
|
* themselves. The `path` on an input reference is empty, so querying the
|
|
10
10
|
* field that looks like the answer gives nothing back.
|
|
11
11
|
*
|
|
12
|
-
* This module flattens
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* This module flattens those chains into a list of everything a unit reads
|
|
13
|
+
* through its inputs, once each, sorted by input and then by path. The list
|
|
14
|
+
* goes on the summary as `inputReads`.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
/** One thing a unit read, and the way it reached it. */
|
|
@@ -31,10 +31,10 @@ interface InputRead {
|
|
|
31
31
|
* is a parameter. The call site has the literals and no library; the
|
|
32
32
|
* helper body has the library and no literals.
|
|
33
33
|
*
|
|
34
|
-
* A pack asks
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
34
|
+
* A pack asks for the helper to be read once, over the whole project,
|
|
35
|
+
* before any file is walked. What comes back says what the body does in
|
|
36
|
+
* terms of the helper's own parameters, and the pack turns that into
|
|
37
|
+
* discovery patterns and invocation recognizers.
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
40
|
/**
|
|
@@ -45,8 +45,8 @@ interface InputRead {
|
|
|
45
45
|
*/
|
|
46
46
|
type HelperValue =
|
|
47
47
|
/**
|
|
48
|
-
* A string, with `{N}`
|
|
49
|
-
*
|
|
48
|
+
* A string, with `{N}` wherever parameter N was interpolated. A
|
|
49
|
+
* literal with no interpolation comes back unchanged.
|
|
50
50
|
*/
|
|
51
51
|
{
|
|
52
52
|
as: "text";
|
|
@@ -83,11 +83,11 @@ interface HelperSink {
|
|
|
83
83
|
}
|
|
84
84
|
/** A function the project declares, as the index read it. */
|
|
85
85
|
interface ProjectHelper {
|
|
86
|
-
/**
|
|
86
|
+
/** The declared name, which is the name call sites use. */
|
|
87
87
|
name: string;
|
|
88
88
|
/** Absolute path of the file declaring it. */
|
|
89
89
|
file: string;
|
|
90
|
-
/**
|
|
90
|
+
/** Parameter names in declaration order. */
|
|
91
91
|
parameters: string[];
|
|
92
92
|
/**
|
|
93
93
|
* Parameters some caller handed this pack's own value to. Empty when
|
|
@@ -100,11 +100,11 @@ interface ProjectHelper {
|
|
|
100
100
|
/**
|
|
101
101
|
* How the index picks out which of the project's functions to read.
|
|
102
102
|
*
|
|
103
|
-
* `subject` starts at a call site: a function the project
|
|
104
|
-
* this pack's own values to is
|
|
103
|
+
* `subject` starts at a call site: a function the project passes one of
|
|
104
|
+
* this pack's own values to is one of the pack's helpers, whatever the
|
|
105
105
|
* helper's file imports. `text` starts at the body, for a pack whose
|
|
106
106
|
* library is reached over the wire and has no import to look for. Both
|
|
107
|
-
*
|
|
107
|
+
* searches use only facts about the library, as `requiresImport` does.
|
|
108
108
|
*/
|
|
109
109
|
type HelperSearch = {
|
|
110
110
|
by: "subject";
|
|
@@ -117,30 +117,30 @@ interface HelperDeclarations {
|
|
|
117
117
|
discovery?: DiscoveryPattern[];
|
|
118
118
|
invocationRecognizers?: InvocationRecognizer[];
|
|
119
119
|
}
|
|
120
|
-
/** A pack's
|
|
120
|
+
/** A pack's request to have the project's helpers read before extraction. */
|
|
121
121
|
interface ProjectHelpers {
|
|
122
122
|
find: HelperSearch;
|
|
123
123
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
124
|
+
* Called once, before the first file is walked, to turn the helpers
|
|
125
|
+
* into patterns and recognizers. It receives data and never an AST, so
|
|
126
|
+
* a pack that declares it runs on any adapter that reads helpers.
|
|
127
127
|
*/
|
|
128
128
|
declare(helpers: readonly ProjectHelper[]): HelperDeclarations;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
|
-
* The `PatternPack` interface
|
|
133
|
-
*
|
|
134
|
-
*
|
|
132
|
+
* The `PatternPack` interface a framework pack hands to a language adapter.
|
|
133
|
+
* The pack describes what to look for (an import, a call, a decorator), and
|
|
134
|
+
* the adapter finds it in its own language's syntax tree.
|
|
135
135
|
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
136
|
+
* Most of a pack is data, so one pack description works with any adapter
|
|
137
|
+
* that reads these patterns. When a pack needs to compute something, the
|
|
138
|
+
* usual fix is another declarative field here. The function hooks
|
|
139
|
+
* (`subUnits`, `discoverUnits` and the recognizers) cover what data cannot.
|
|
139
140
|
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* semantics say which property is the body and which is the status.
|
|
141
|
+
* Sections follow the order an adapter uses them. The pack patterns
|
|
142
|
+
* reference at https://suss.sh/packs/patterns shows each variant with the
|
|
143
|
+
* code it matches.
|
|
144
144
|
*/
|
|
145
145
|
|
|
146
146
|
type DiscoveryMatch = {
|
|
@@ -165,21 +165,18 @@ type DiscoveryMatch = {
|
|
|
165
165
|
* Unset means any method call (or bare call for globals). */
|
|
166
166
|
methodFilter?: string[];
|
|
167
167
|
/**
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
* treat `api.get(...)` (where `api = axios.create(...)`) the same as
|
|
173
|
-
* `axios.get(...)`.
|
|
168
|
+
* Methods on the import that build a client instance. A variable
|
|
169
|
+
* initialized from one of these calls is a client too, so with
|
|
170
|
+
* `factoryMethods: ["create"]`, `api.get(...)` after
|
|
171
|
+
* `api = axios.create(...)` matches the same as `axios.get(...)`.
|
|
174
172
|
*/
|
|
175
173
|
factoryMethods?: string[];
|
|
176
174
|
/**
|
|
177
|
-
* The
|
|
178
|
-
* request through the instance
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
* provider's paths
|
|
182
|
-
* consumer's.
|
|
175
|
+
* The option on the factory call's config that sets a base path for
|
|
176
|
+
* every request through the instance, `baseURL` for axios. The
|
|
177
|
+
* adapter puts it in front of each call's path, so the consumer's
|
|
178
|
+
* route lines up with a spec whose `servers[0].url` adds the same
|
|
179
|
+
* prefix to the provider's paths.
|
|
183
180
|
*/
|
|
184
181
|
basePathOption?: string;
|
|
185
182
|
/**
|
|
@@ -190,88 +187,54 @@ type DiscoveryMatch = {
|
|
|
190
187
|
callable?: boolean;
|
|
191
188
|
} | {
|
|
192
189
|
/**
|
|
193
|
-
* A constructor or factory call
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
* GraphQL type names (`Query`, `Mutation`, `Subscription`, or
|
|
197
|
-
* object-type names like `User`), and inner keys are field names
|
|
198
|
-
* whose values are resolver functions.
|
|
190
|
+
* A constructor or factory call whose config object contains a
|
|
191
|
+
* two-level resolver map, the usual way to write a code-first GraphQL
|
|
192
|
+
* server. Outer keys are type names and inner keys are field names:
|
|
199
193
|
*
|
|
200
|
-
* Example (Apollo Server v4):
|
|
201
194
|
* ```ts
|
|
202
|
-
* new ApolloServer({
|
|
203
|
-
* typeDefs,
|
|
204
|
-
* resolvers: {
|
|
205
|
-
* Query: { users: async () => {...} },
|
|
206
|
-
* Mutation: { createUser: async (_, {input}) => {...} },
|
|
207
|
-
* User: { fullName: (parent) => `${parent.first} ${parent.last}` },
|
|
208
|
-
* },
|
|
209
|
-
* });
|
|
195
|
+
* new ApolloServer({ typeDefs, resolvers: { Query: { users: async () => {...} } } });
|
|
210
196
|
* ```
|
|
211
197
|
*
|
|
212
|
-
* Each inner function becomes one
|
|
213
|
-
*
|
|
214
|
-
* `
|
|
215
|
-
*
|
|
198
|
+
* Each inner function becomes one unit bound as
|
|
199
|
+
* `graphql-resolver(typeName, fieldName)`. Both `new Ctor(cfg)` and
|
|
200
|
+
* `ctor(cfg)` match, since Apollo's standalone server uses `new` and
|
|
201
|
+
* yoga uses a bare call.
|
|
216
202
|
*/
|
|
217
203
|
type: "resolverMap";
|
|
218
204
|
importModule: string;
|
|
219
205
|
importName: string;
|
|
220
206
|
/**
|
|
221
|
-
* The
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
* spell it `"resolvers"`.
|
|
207
|
+
* The config property that contains the resolver map. The key belongs
|
|
208
|
+
* to the library, so the adapter has no default. Apollo, yoga and
|
|
209
|
+
* graphql-tools all use `"resolvers"`.
|
|
225
210
|
*/
|
|
226
211
|
mapProperty: string;
|
|
227
212
|
/**
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
* differently later. Leave it unset to discover every type.
|
|
213
|
+
* Types whose fields are not discovered as resolvers, such as
|
|
214
|
+
* `Subscription`. Leave it unset to discover every type.
|
|
231
215
|
*/
|
|
232
216
|
excludeTypes?: string[];
|
|
233
217
|
} | {
|
|
234
218
|
/**
|
|
235
219
|
* A consumer-side GraphQL hook call, the way Apollo Client and urql
|
|
236
|
-
* are normally used. Each call to
|
|
237
|
-
*
|
|
238
|
-
* `graphql-operation(operationType, operationName?)`.
|
|
220
|
+
* are normally used. Each call to a listed hook becomes a `client`
|
|
221
|
+
* unit bound as `graphql-operation(operationType, operationName?)`.
|
|
239
222
|
*
|
|
240
|
-
* The document
|
|
241
|
-
*
|
|
242
|
-
* from
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
* summary as `metadata.graphql.unresolvedDocument`, so the boundary is
|
|
248
|
-
* kept rather than dropped.
|
|
249
|
-
*
|
|
250
|
-
* Example:
|
|
251
|
-
* ```ts
|
|
252
|
-
* import { gql, useQuery } from "@apollo/client";
|
|
253
|
-
* const GET_USER = gql`query GetUser($id: ID!) { user(id: $id) { id } }`;
|
|
254
|
-
* function UserPage({ id }) {
|
|
255
|
-
* const { data } = useQuery(GET_USER, { variables: { id } });
|
|
256
|
-
* ...
|
|
257
|
-
* }
|
|
258
|
-
* ```
|
|
259
|
-
*
|
|
260
|
-
* The adapter records the operation name and type on the
|
|
261
|
-
* DiscoveredUnit's `operationInfo`, and binding construction uses that
|
|
262
|
-
* to emit `graphql-operation(...)`. The per-hook `operationType`
|
|
263
|
-
* wins when the document header cannot be read, the same way
|
|
264
|
-
* `graphqlImperativeCall.methods` does.
|
|
223
|
+
* The document can be an inline `gql` template, a const in this
|
|
224
|
+
* module or an imported one, a `.graphql` or `.gql` file import, or a
|
|
225
|
+
* `TypedDocumentNode` from graphql-codegen. When the body cannot be
|
|
226
|
+
* read, the operation header comes from the `TypedDocumentNode` type
|
|
227
|
+
* arguments. A document that still cannot be resolved is kept on the
|
|
228
|
+
* summary as `metadata.graphql.unresolvedDocument`, so the boundary
|
|
229
|
+
* stays.
|
|
265
230
|
*/
|
|
266
231
|
type: "graphqlHookCall";
|
|
267
232
|
importModule: string;
|
|
268
233
|
/**
|
|
269
|
-
* Hooks
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
* Each hook is reported as `kind = "client"` unless a pack overrides
|
|
274
|
-
* that through the enclosing `DiscoveryPattern.kind`.
|
|
234
|
+
* Hooks on that import, each with the operation type it performs
|
|
235
|
+
* (`useQuery` performs a query). The type is used when the document's
|
|
236
|
+
* header cannot be read. A matched call is a `client` unit unless the
|
|
237
|
+
* enclosing `DiscoveryPattern.kind` says otherwise.
|
|
275
238
|
*/
|
|
276
239
|
hooks: Array<{
|
|
277
240
|
hookName: string;
|
|
@@ -279,21 +242,17 @@ type DiscoveryMatch = {
|
|
|
279
242
|
}>;
|
|
280
243
|
} | {
|
|
281
244
|
/**
|
|
282
|
-
* An imperative Apollo
|
|
283
|
-
* `client.mutate({ mutation })
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
* Discovery only fires when the named constructor (usually
|
|
288
|
-
* `ApolloClient`) is imported, because otherwise any object at all
|
|
289
|
-
* with a `query` method would look like a match.
|
|
245
|
+
* An imperative Apollo Client call: `client.query({ query })`,
|
|
246
|
+
* `client.mutate({ mutation })` or `client.subscribe({ query })`. The
|
|
247
|
+
* document is on a config property instead of the first argument,
|
|
248
|
+
* which is why this is separate from `graphqlHookCall`.
|
|
290
249
|
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
250
|
+
* Discovery fires only when the named constructor (usually
|
|
251
|
+
* `ApolloClient`) is imported, since otherwise any object with a
|
|
252
|
+
* `query` method would match. Each `methods` entry gives the method,
|
|
253
|
+
* the config property with the document on it, and the operation type
|
|
254
|
+
* to use when the document's header is anonymous. A named header takes
|
|
255
|
+
* precedence.
|
|
297
256
|
*/
|
|
298
257
|
type: "graphqlImperativeCall";
|
|
299
258
|
importModule: string;
|
|
@@ -305,41 +264,29 @@ type DiscoveryMatch = {
|
|
|
305
264
|
}>;
|
|
306
265
|
} | {
|
|
307
266
|
/**
|
|
308
|
-
*
|
|
309
|
-
* boundary. The adapter reads
|
|
310
|
-
* resolves each
|
|
311
|
-
* `exports`), follows barrel re-exports, and emits one
|
|
312
|
-
* unit per exported function.
|
|
313
|
-
* an in-process `function-call` boundary.
|
|
267
|
+
* A TypeScript package's public exports, as the provider side of an
|
|
268
|
+
* in-process `function-call` boundary. The adapter reads
|
|
269
|
+
* `package.json`, resolves each entry point (the root `.` and any
|
|
270
|
+
* sub-path in `exports`), follows barrel re-exports, and emits one
|
|
271
|
+
* unit per exported function.
|
|
314
272
|
*
|
|
315
|
-
*
|
|
316
|
-
* `
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
* A sub-path export is identified as, for example,
|
|
323
|
-
* `@suss/behavioral-ir/schemas::BehavioralSummarySchema`, giving
|
|
324
|
-
* `exportPath = ["schemas", "BehavioralSummarySchema"]`. A root export
|
|
325
|
-
* leaves the sub-path segment out.
|
|
326
|
-
*
|
|
327
|
-
* As of v0 this resolves the `types`, `default`, and `import`
|
|
328
|
-
* conditions on `exports`, and falls back to `types`, `main`, `module`
|
|
329
|
-
* when there is no `exports` field. Pattern exports (`./utils/*`) and
|
|
330
|
-
* `development` conditions are not handled yet.
|
|
273
|
+
* Each binding is keyed by package and export path, so
|
|
274
|
+
* `@suss/behavioral-ir/schemas::BehavioralSummarySchema` has
|
|
275
|
+
* `exportPath = ["schemas", "BehavioralSummarySchema"]`. The `types`,
|
|
276
|
+
* `default` and `import` conditions are resolved, with `types`, `main`
|
|
277
|
+
* and `module` as the fallback when there is no `exports` field.
|
|
278
|
+
* Pattern exports (`./utils/*`) and `development` conditions are not.
|
|
331
279
|
*/
|
|
332
280
|
type: "packageExports";
|
|
333
281
|
/**
|
|
334
282
|
* Absolute path to the package's `package.json`. Left out when
|
|
335
|
-
* `workspaces` is set, since the workspace
|
|
283
|
+
* `workspaces` is set, since the workspace manifest lists the packages.
|
|
336
284
|
*/
|
|
337
285
|
packageJsonPath?: string;
|
|
338
286
|
/**
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
* manifest and applies this pattern once per package it finds.
|
|
287
|
+
* Apply the pattern to every package the workspace declares. Those
|
|
288
|
+
* packages belong to the project, so the pack cannot list them; the
|
|
289
|
+
* adapter reads the workspace manifest and applies the pattern to each.
|
|
343
290
|
*/
|
|
344
291
|
workspaces?: true;
|
|
345
292
|
/**
|
|
@@ -355,113 +302,134 @@ type DiscoveryMatch = {
|
|
|
355
302
|
excludeNames?: string[];
|
|
356
303
|
} | {
|
|
357
304
|
/**
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
305
|
+
* The public exports of one module the project lists in `suss.json`,
|
|
306
|
+
* read the way `packageExports` reads a package's entry points: one
|
|
307
|
+
* unit per exported function, class methods surfaced, barrels
|
|
308
|
+
* followed. Each binding is keyed `fn:<module>::<exportName>`. The
|
|
309
|
+
* adapter writes these patterns from the module list, so no pack
|
|
310
|
+
* declares one.
|
|
311
|
+
*/
|
|
312
|
+
type: "moduleSurface";
|
|
313
|
+
/** The module's name, as `suss.json` gives it. */
|
|
314
|
+
module: string;
|
|
315
|
+
/** Absolute paths of the files whose exports are the surface. */
|
|
316
|
+
publicFiles: string[];
|
|
317
|
+
} | {
|
|
318
|
+
/**
|
|
319
|
+
* Methods with one of `methodDecorators` on a class with one of
|
|
320
|
+
* `classDecorators`, the way NestJS declares resolvers. At least one
|
|
321
|
+
* method decorator has to be imported from `importModule`, so a
|
|
322
|
+
* project decorator that only shares a name does not match. A NestJS
|
|
323
|
+
* GraphQL pack sets `classDecorators: ["Resolver"]` and
|
|
324
|
+
* `methodDecorators: ["Query", "Mutation", "ResolveField", "Subscription"]`.
|
|
372
325
|
*
|
|
373
|
-
* The
|
|
374
|
-
* comes
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
* decorator's
|
|
378
|
-
* `"User"`). `fieldName` comes from the method decorator's `{ name }`
|
|
379
|
-
* option when that is set, and otherwise from the method name.
|
|
326
|
+
* The binding comes out as `graphql-resolver(typeName, fieldName)`.
|
|
327
|
+
* `typeName` comes from `methodDecoratorTypeMap` when the method
|
|
328
|
+
* decorator is in it, and otherwise from the class decorator's first
|
|
329
|
+
* argument (`@Resolver(() => User)` gives `"User"`). `fieldName` comes
|
|
330
|
+
* from the method decorator's `{ name }` option, or the method name.
|
|
380
331
|
*/
|
|
381
332
|
type: "decoratedMethod";
|
|
382
333
|
/**
|
|
383
|
-
* The
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
* those. Pass an array of acceptable modules and any one of them
|
|
387
|
-
* matching is enough.
|
|
334
|
+
* The modules a decorator may be imported from. A project that wraps
|
|
335
|
+
* a framework decorator and re-exports it needs its own module listed
|
|
336
|
+
* too. Any one module in the list matching is enough.
|
|
388
337
|
*/
|
|
389
338
|
importModule: string | string[];
|
|
390
339
|
/**
|
|
391
|
-
* Class decorators to
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
* its options instead.
|
|
340
|
+
* Class decorators to match. The first one found on a class supplies
|
|
341
|
+
* `typeName`, and the rest are fallbacks for projects with several
|
|
342
|
+
* wrapper styles. A pack lists only its own framework's decorators and
|
|
343
|
+
* takes a project's wrappers through its options.
|
|
396
344
|
*/
|
|
397
345
|
classDecorators: string[];
|
|
398
346
|
methodDecorators: string[];
|
|
399
347
|
/**
|
|
400
|
-
* Maps a method decorator to the type its field belongs to
|
|
401
|
-
*
|
|
402
|
-
*
|
|
403
|
-
* says, so an entry here wins over the class decorator's argument.
|
|
348
|
+
* Maps a method decorator to the type its field belongs to. NestJS
|
|
349
|
+
* puts `@Query` on the root `Query` type whatever the class says, so an
|
|
350
|
+
* entry here takes precedence over the class decorator's argument.
|
|
404
351
|
*
|
|
405
|
-
* When the map
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
* of claiming a field the schema does not have.
|
|
352
|
+
* When neither the map nor the class decorator gives a type, the
|
|
353
|
+
* binding goes out with no type and pairs with nothing. That is safer
|
|
354
|
+
* than claiming a field the schema does not have.
|
|
409
355
|
*/
|
|
410
356
|
methodDecoratorTypeMap: Record<string, string>;
|
|
411
357
|
} | {
|
|
412
358
|
/**
|
|
413
|
-
* NestJS-style REST controller
|
|
414
|
-
* `@Controller(
|
|
415
|
-
* `@
|
|
416
|
-
*
|
|
417
|
-
*
|
|
418
|
-
*
|
|
419
|
-
* argument, and both of those are optional.
|
|
359
|
+
* A NestJS-style REST controller: a class decorated with
|
|
360
|
+
* `@Controller(prefix?)` and methods decorated with `@Get(subpath?)`,
|
|
361
|
+
* `@Post` and so on. The method decorator's name gives the HTTP method
|
|
362
|
+
* through `methodDecoratorRouteMap`. The path is the class decorator's
|
|
363
|
+
* first argument joined to the method decorator's, and both are
|
|
364
|
+
* optional. The binding comes out as `rest(method, path)`.
|
|
420
365
|
*
|
|
421
|
-
*
|
|
422
|
-
* `
|
|
423
|
-
*
|
|
424
|
-
* are matched by name alone, so a project's own wrapper around the
|
|
425
|
-
* framework's decorator matches once the project lists it in the
|
|
426
|
-
* pack's options.
|
|
427
|
-
*
|
|
428
|
-
* The adapter fills in `DiscoveredUnit.routeInfo` so the binding comes
|
|
429
|
-
* out as `rest(method, path)`.
|
|
366
|
+
* At least one route decorator on a method has to be imported from
|
|
367
|
+
* `importModule`. Class decorators match by name alone, so a project's
|
|
368
|
+
* own wrapper matches once the project lists it in the pack's options.
|
|
430
369
|
*/
|
|
431
370
|
type: "decoratedRoute";
|
|
432
371
|
importModule: string | string[];
|
|
433
372
|
classDecorators: string[];
|
|
434
373
|
/**
|
|
435
|
-
*
|
|
436
|
-
*
|
|
437
|
-
*
|
|
438
|
-
* become the `method` field on the REST binding, and `"*"` is fine for
|
|
439
|
-
* a catch-all decorator.
|
|
374
|
+
* Decorator name to HTTP method, one entry per verb decorator. The
|
|
375
|
+
* value becomes the REST binding's `method`; use `"*"` for a
|
|
376
|
+
* catch-all decorator such as NestJS's `@All`.
|
|
440
377
|
*/
|
|
441
378
|
methodDecoratorRouteMap: Record<string, string>;
|
|
379
|
+
/**
|
|
380
|
+
* The status the framework sends when a handler returns without
|
|
381
|
+
* stating one, keyed by method decorator, for the decorators whose
|
|
382
|
+
* status differs from the response terminals' `defaultStatusCode`.
|
|
383
|
+
* NestJS sends 201 for `@Post`.
|
|
384
|
+
*/
|
|
385
|
+
defaultStatusCodes?: Record<string, number>;
|
|
386
|
+
/**
|
|
387
|
+
* A method decorator, imported from `importModule`, whose first
|
|
388
|
+
* argument sets the status of every response the handler returns
|
|
389
|
+
* without stating its own, NestJS's `@HttpCode(204)`. It wins over
|
|
390
|
+
* `defaultStatusCodes`.
|
|
391
|
+
*/
|
|
392
|
+
statusCodeDecorator?: string;
|
|
393
|
+
/**
|
|
394
|
+
* The number each of a library's own status constants is, by the
|
|
395
|
+
* path of the export (`HttpStatus.NO_CONTENT`), for when the
|
|
396
|
+
* library is not installed and its declaration cannot give them.
|
|
397
|
+
* `importModule` says which module exports them.
|
|
398
|
+
*/
|
|
399
|
+
statusCodeConstants?: Record<string, number>;
|
|
400
|
+
/**
|
|
401
|
+
* The call that puts one path in front of every route the
|
|
402
|
+
* application serves, NestJS's `app.setGlobalPrefix("api")`.
|
|
403
|
+
*/
|
|
404
|
+
globalPrefix?: GlobalPrefixCall;
|
|
405
|
+
/**
|
|
406
|
+
* How a route states an API version and how the application serves
|
|
407
|
+
* one, NestJS's `@Controller({ version })` with
|
|
408
|
+
* `app.enableVersioning()`.
|
|
409
|
+
*/
|
|
410
|
+
versioning?: RouteVersioning;
|
|
411
|
+
/**
|
|
412
|
+
* Decorators, on the route's method or its class, that list a
|
|
413
|
+
* status the route can respond with, such as `@nestjs/swagger`'s
|
|
414
|
+
* `@ApiNotFoundResponse()`. A generated spec declares these
|
|
415
|
+
* statuses because of the decorators, so a check does not expect a
|
|
416
|
+
* path to produce them.
|
|
417
|
+
*/
|
|
418
|
+
declaredStatuses?: DeclaredStatusDecorators;
|
|
442
419
|
} | {
|
|
443
420
|
/**
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
* registration. Used for patterns like:
|
|
421
|
+
* A `for-of` loop over a literal array of route specs, read as one
|
|
422
|
+
* inline registration per element:
|
|
447
423
|
*
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
* for (const r of routes) app[r.method](r.path, r.handler);
|
|
453
|
-
*
|
|
454
|
-
* `elementShape` declares which keys on each element give the method,
|
|
455
|
-
* the path, and the handler. The loop body has to contain at least
|
|
456
|
-
* one call expression that references the
|
|
457
|
-
* loop variable, which filters out unrelated loops. Nothing else
|
|
458
|
-
* about that call is checked.
|
|
459
|
-
*
|
|
460
|
-
* An iterable that resolves to an `ArrayLiteralExpression`, inline or
|
|
461
|
-
* bound to a `const` one hop away, gets expanded. Cross-file and
|
|
462
|
-
* computed iterables are outside v0.
|
|
424
|
+
* ```ts
|
|
425
|
+
* const routes = [{ method: "get", path: "/users", handler: getUsers }];
|
|
426
|
+
* for (const r of routes) app[r.method](r.path, r.handler);
|
|
427
|
+
* ```
|
|
463
428
|
*
|
|
464
|
-
*
|
|
429
|
+
* `elementShape` says which keys give the method, path and handler.
|
|
430
|
+
* The loop body has to contain a call that uses the loop variable,
|
|
431
|
+
* which filters out unrelated loops. The array can be inline or a
|
|
432
|
+
* `const` one hop away. An array from another file is not expanded.
|
|
465
433
|
*/
|
|
466
434
|
type: "registrationLoop";
|
|
467
435
|
elementShape: {
|
|
@@ -483,33 +451,26 @@ type DiscoveryMatch = {
|
|
|
483
451
|
};
|
|
484
452
|
} | {
|
|
485
453
|
/**
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
* `registrationCall` discovery cannot see today.
|
|
454
|
+
* A helper call read as several inline registrations, with the call's
|
|
455
|
+
* arguments substituted into a template for each. It covers helpers
|
|
456
|
+
* like `registerCrud(app, "users", userHandlers)`, which
|
|
457
|
+
* `registrationCall` cannot see.
|
|
491
458
|
*
|
|
492
|
-
* Each
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
*
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
*
|
|
500
|
-
* `importModule` optionally narrows matches to helpers imported from
|
|
501
|
-
* one specific module, which helps when two packages happen to export
|
|
502
|
-
* a function with the same name.
|
|
503
|
-
*
|
|
504
|
-
* Pack-author docs: `design/proposals/dynamic-registration.md`.
|
|
459
|
+
* Each `registrations` entry is one route the helper produces.
|
|
460
|
+
* `pathTemplate` and `handlerArg` use `{N}` for the call's Nth
|
|
461
|
+
* argument: its value when it is a string literal, and otherwise its
|
|
462
|
+
* source text with the slot marked opaque. `{N}.prop` reads `prop` from
|
|
463
|
+
* the argument's resolved object. `importModule` narrows matches to a
|
|
464
|
+
* helper imported from that module, for when two packages export the
|
|
465
|
+
* same name.
|
|
505
466
|
*/
|
|
506
467
|
type: "registrationTemplate";
|
|
507
468
|
helperName: string;
|
|
508
469
|
importModule?: string;
|
|
509
470
|
/**
|
|
510
|
-
* Which argument is the routable
|
|
511
|
-
*
|
|
512
|
-
* middleware registered
|
|
471
|
+
* Which argument is the routable. A route the helper registers then
|
|
472
|
+
* belongs to the same app as a route written beside the call, and the
|
|
473
|
+
* middleware registered on that app applies to it too.
|
|
513
474
|
*/
|
|
514
475
|
subject?: {
|
|
515
476
|
argument: number;
|
|
@@ -523,32 +484,23 @@ type DiscoveryMatch = {
|
|
|
523
484
|
}>;
|
|
524
485
|
} | {
|
|
525
486
|
/**
|
|
526
|
-
* Routes declared as JSX elements, the way client-side routers
|
|
527
|
-
*
|
|
528
|
-
*
|
|
529
|
-
*
|
|
530
|
-
*
|
|
531
|
-
*
|
|
532
|
-
* factory call whose first argument is an array of route
|
|
533
|
-
* objects using the same property names).
|
|
487
|
+
* Routes declared as JSX elements, the way client-side routers write
|
|
488
|
+
* them. It reads the tree form, where a child path joins its parent's
|
|
489
|
+
* and an index route takes its parent's path, and the object form,
|
|
490
|
+
* where a factory call takes an array of route objects with the same
|
|
491
|
+
* property names. The pack supplies every name, and the adapter only
|
|
492
|
+
* walks JSX and arrays.
|
|
534
493
|
*
|
|
535
|
-
*
|
|
536
|
-
*
|
|
537
|
-
*
|
|
538
|
-
*
|
|
539
|
-
*
|
|
540
|
-
* Each route with a readable path becomes one unit whose target
|
|
541
|
-
* is the component the element attribute references, resolved
|
|
542
|
-
* only when the reference is a single identifier. A route whose
|
|
543
|
-
* component cannot be read is still reported, as a boundary with
|
|
544
|
-
* nothing behind it. A route whose path cannot be read gets no path
|
|
545
|
-
* and reports that in a gap instead of guessing at one.
|
|
494
|
+
* Each route with a readable path becomes one unit whose target is the
|
|
495
|
+
* component its element attribute references, when that reference is
|
|
496
|
+
* a single identifier. A route whose component cannot be read is still
|
|
497
|
+
* reported, as a boundary with nothing behind it. A route whose path
|
|
498
|
+
* cannot be read gets no path and a gap saying why.
|
|
546
499
|
*/
|
|
547
500
|
type: "jsxElementRoute";
|
|
548
501
|
/**
|
|
549
|
-
*
|
|
550
|
-
*
|
|
551
|
-
* import declarations; aliased imports are followed.
|
|
502
|
+
* Modules the route element and factories must be imported from,
|
|
503
|
+
* matched exactly. An aliased import still matches.
|
|
552
504
|
*/
|
|
553
505
|
importModule: string | string[];
|
|
554
506
|
/** The route element's exported name. */
|
|
@@ -578,12 +530,10 @@ type DiscoveryMatch = {
|
|
|
578
530
|
*/
|
|
579
531
|
routeObjectFactories?: string[];
|
|
580
532
|
/**
|
|
581
|
-
* Factory functions that turn JSX route elements into
|
|
582
|
-
*
|
|
583
|
-
*
|
|
584
|
-
*
|
|
585
|
-
* here is what stops that case from being reported as an
|
|
586
|
-
* unreadable route array.
|
|
533
|
+
* Factory functions that turn JSX route elements into route objects.
|
|
534
|
+
* The JSX walk already reads those elements wherever they appear.
|
|
535
|
+
* Listing the factory keeps a route-object factory that is handed one
|
|
536
|
+
* of these calls from being reported as an unreadable route array.
|
|
587
537
|
*/
|
|
588
538
|
elementsFactories?: string[];
|
|
589
539
|
/**
|
|
@@ -594,23 +544,17 @@ type DiscoveryMatch = {
|
|
|
594
544
|
method: string;
|
|
595
545
|
} | {
|
|
596
546
|
/**
|
|
597
|
-
*
|
|
598
|
-
* imports of the listed packages
|
|
599
|
-
*
|
|
600
|
-
* function
|
|
601
|
-
* `
|
|
602
|
-
* summaries `packageExports` produces.
|
|
603
|
-
*
|
|
604
|
-
* `packages` lists exact package names to track imports of, possibly
|
|
605
|
-
* with a sub-path such as `"@suss/behavioral-ir/schemas"`. Pass
|
|
606
|
-
* several package names to track a family at
|
|
607
|
-
* once. Imports of any other package are ignored.
|
|
547
|
+
* The consumer side of the package-export boundary. The adapter finds
|
|
548
|
+
* imports of the listed packages, records every call site, and emits
|
|
549
|
+
* one `caller` unit per enclosing function, bound as
|
|
550
|
+
* `function-call { package, exportPath }` to pair with the providers
|
|
551
|
+
* `packageExports` finds.
|
|
608
552
|
*
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
*
|
|
612
|
-
*
|
|
613
|
-
*
|
|
553
|
+
* `packages` takes exact package names, with a sub-path where needed,
|
|
554
|
+
* such as `"@suss/behavioral-ir/schemas"`. Named and default imports
|
|
555
|
+
* are tracked. Namespace imports (`import * as X`) are not yet. When a
|
|
556
|
+
* file in the consumer's repo re-exports the package and another file
|
|
557
|
+
* imports it from there, the unit binds to that intermediate file.
|
|
614
558
|
*/
|
|
615
559
|
type: "packageImport";
|
|
616
560
|
/** Left out when `workspaces` is set. */
|
|
@@ -621,7 +565,61 @@ type DiscoveryMatch = {
|
|
|
621
565
|
* side of the package-export boundary, whichever two they are.
|
|
622
566
|
*/
|
|
623
567
|
workspaces?: true;
|
|
624
|
-
};
|
|
568
|
+
} | TestCaseMatch;
|
|
569
|
+
/**
|
|
570
|
+
* Test cases written as nested calls, the way vitest, jest and mocha
|
|
571
|
+
* write them: `describe("orders", () => { it("cancels", () => ...) })`.
|
|
572
|
+
* Each case becomes a unit named by its title path, the suite titles
|
|
573
|
+
* then its own, joined with ` > `. A title the adapter cannot read as a
|
|
574
|
+
* string keeps its source text and is recorded as unresolved.
|
|
575
|
+
*/
|
|
576
|
+
interface TestCaseMatch {
|
|
577
|
+
type: "testCase";
|
|
578
|
+
style: "block";
|
|
579
|
+
/** The module the runner's functions are imported from, e.g. "vitest". */
|
|
580
|
+
importModule: string;
|
|
581
|
+
/** The functions that open a group of cases, e.g. ["describe", "suite"]. */
|
|
582
|
+
suiteNames: string[];
|
|
583
|
+
/** The functions that declare one case, e.g. ["it", "test"]. */
|
|
584
|
+
caseNames: string[];
|
|
585
|
+
/**
|
|
586
|
+
* Modifiers that mean the case does not run, written after a suite
|
|
587
|
+
* or case name: `it.skip`, `describe.todo`. A case under a skipped
|
|
588
|
+
* suite is skipped too.
|
|
589
|
+
*/
|
|
590
|
+
skipModifiers: string[];
|
|
591
|
+
/**
|
|
592
|
+
* Modifiers that take arguments of their own and return the function
|
|
593
|
+
* to call, such as `it.skipIf(condition)`. The case called through one
|
|
594
|
+
* is read like any other.
|
|
595
|
+
*/
|
|
596
|
+
argumentModifiers: string[];
|
|
597
|
+
/**
|
|
598
|
+
* Modifiers that take a table and declare one case per row, such as
|
|
599
|
+
* `it.each(rows)`. The runner fills the title in per row, so the case
|
|
600
|
+
* is read once, under the title as written, and that title is
|
|
601
|
+
* recorded as unresolved.
|
|
602
|
+
*/
|
|
603
|
+
rowModifiers: string[];
|
|
604
|
+
/**
|
|
605
|
+
* How the runner replaces something before a case runs. `object` is
|
|
606
|
+
* the runner's helper object, imported from `importModule`.
|
|
607
|
+
* `moduleMethods` replace a whole module given its specifier
|
|
608
|
+
* (`vi.mock("./orders.js")`), and `memberMethods` replace one member
|
|
609
|
+
* given the object and the member's name (`vi.spyOn(orders, "cancel")`).
|
|
610
|
+
*/
|
|
611
|
+
mocks?: {
|
|
612
|
+
object: string;
|
|
613
|
+
moduleMethods: string[];
|
|
614
|
+
memberMethods: string[];
|
|
615
|
+
};
|
|
616
|
+
/**
|
|
617
|
+
* Walk only these files, matched on whole path segments from the end,
|
|
618
|
+
* so `src/orders.test.ts` matches `/repo/pkg/src/orders.test.ts`. Left
|
|
619
|
+
* out, every file that imports the runner is walked.
|
|
620
|
+
*/
|
|
621
|
+
files?: string[];
|
|
622
|
+
}
|
|
625
623
|
type BindingExtraction = {
|
|
626
624
|
method: {
|
|
627
625
|
type: "fromRegistration";
|
|
@@ -657,11 +655,9 @@ type BindingExtraction = {
|
|
|
657
655
|
property: string;
|
|
658
656
|
} | {
|
|
659
657
|
/**
|
|
660
|
-
* The route path comes from where the file is on disk,
|
|
661
|
-
* Next.js and React Router describe
|
|
662
|
-
*
|
|
663
|
-
* about files and the pack knows what the framework does with their
|
|
664
|
-
* names.
|
|
658
|
+
* The route path comes from where the file is on disk, the way
|
|
659
|
+
* Next.js and React Router describe routes. The pack gives the
|
|
660
|
+
* framework's filename convention, and the adapter applies it.
|
|
665
661
|
*
|
|
666
662
|
* `app/api/orders/[id]/route.ts` under `{ root: "app",
|
|
667
663
|
* dropBasenames: ["route"], dynamic: "brackets" }` comes out as
|
|
@@ -700,6 +696,14 @@ type BindingExtraction = {
|
|
|
700
696
|
} | {
|
|
701
697
|
type: "fromClientMethod";
|
|
702
698
|
};
|
|
699
|
+
/**
|
|
700
|
+
* Which argument is the request's options object, for a call that
|
|
701
|
+
* takes one: fetch's second argument, the config axios takes after the
|
|
702
|
+
* URL or after the body. The pack's `redirectOption` is read off it.
|
|
703
|
+
*/
|
|
704
|
+
options?: {
|
|
705
|
+
position: number;
|
|
706
|
+
};
|
|
703
707
|
};
|
|
704
708
|
/**
|
|
705
709
|
* Where a declared channel's spelling comes from.
|
|
@@ -707,8 +711,8 @@ type BindingExtraction = {
|
|
|
707
711
|
* `decoratorArgument` reads the argument off the same decorator the
|
|
708
712
|
* match selected the handler by, so `@EventPattern("order.placed")`
|
|
709
713
|
* gives "order.placed". `literal` is for a wire whose channel the
|
|
710
|
-
* library fixes. `unstated`
|
|
711
|
-
* not,
|
|
714
|
+
* library fixes. `unstated` means the wire is known and the channel is
|
|
715
|
+
* not, and it pairs the same as a null channel.
|
|
712
716
|
*/
|
|
713
717
|
type ChannelSource = {
|
|
714
718
|
from: "decoratorArgument";
|
|
@@ -721,15 +725,10 @@ type ChannelSource = {
|
|
|
721
725
|
};
|
|
722
726
|
/**
|
|
723
727
|
* A binding the pattern states outright, for a boundary the match
|
|
724
|
-
* cannot read from the source.
|
|
725
|
-
*
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
* was pushed into a callback, which pack health then reports as an
|
|
729
|
-
* ast-link. This is the same vocabulary `DiscoveredCustomUnit` already
|
|
730
|
-
* has, declared instead of returned. Message bus only for now; the
|
|
731
|
-
* design note in the proposals directory says what comes next and why
|
|
732
|
-
* the rest stays put.
|
|
728
|
+
* cannot read from the source. `bindingExtraction` only covers REST, so
|
|
729
|
+
* a declarative pack for a queue or a topic states its binding here
|
|
730
|
+
* instead of writing a callback. The fields are the ones a
|
|
731
|
+
* `DiscoveredCustomUnit` returns. Only the message bus is supported.
|
|
733
732
|
*/
|
|
734
733
|
type DeclaredBinding = {
|
|
735
734
|
semantics: "message-bus";
|
|
@@ -789,6 +788,95 @@ interface WrapperMethodRegistration extends WrapperFunctionShape {
|
|
|
789
788
|
*/
|
|
790
789
|
arity?: number;
|
|
791
790
|
}
|
|
791
|
+
/**
|
|
792
|
+
* A call on the application object that puts one path in front of
|
|
793
|
+
* every route, with the path as its first argument. The adapter reads
|
|
794
|
+
* it in whichever file makes it, and applies the prefix to every route
|
|
795
|
+
* the pattern finds when all such calls in the run agree on it.
|
|
796
|
+
*/
|
|
797
|
+
interface GlobalPrefixCall {
|
|
798
|
+
/** The method on the application object, NestJS's `setGlobalPrefix`. */
|
|
799
|
+
method: string;
|
|
800
|
+
/**
|
|
801
|
+
* How the application object is made: `NestFactory.create(...)`, where
|
|
802
|
+
* `NestFactory` is imported from `@nestjs/core`. A call on anything
|
|
803
|
+
* else is not read, including a parameter some caller passes anything
|
|
804
|
+
* else to.
|
|
805
|
+
*/
|
|
806
|
+
application: {
|
|
807
|
+
importModule: string;
|
|
808
|
+
importName: string;
|
|
809
|
+
factory: string;
|
|
810
|
+
};
|
|
811
|
+
/**
|
|
812
|
+
* The routes the prefix leaves out, listed under `option` on the
|
|
813
|
+
* object the call takes second. An entry is a path, or an object with
|
|
814
|
+
* the path under `pathKey` and the method under `methodKey`, written
|
|
815
|
+
* as a member of the library's method enum. `methods` maps each
|
|
816
|
+
* member's number to its verb, with `*` for every verb.
|
|
817
|
+
*/
|
|
818
|
+
exclude?: {
|
|
819
|
+
option: string;
|
|
820
|
+
pathKey: string;
|
|
821
|
+
methodKey: string;
|
|
822
|
+
methods: Record<number, string>;
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
/** Decorators that list a status a route can respond with. */
|
|
826
|
+
interface DeclaredStatusDecorators {
|
|
827
|
+
/** The modules the decorators are imported from. */
|
|
828
|
+
importModule: string | string[];
|
|
829
|
+
/**
|
|
830
|
+
* The status each decorator declares, or null for one that reads the
|
|
831
|
+
* status from `statusKey` in its options object, `@ApiResponse({ status })`.
|
|
832
|
+
*/
|
|
833
|
+
decorators: Readonly<Record<string, number | null>>;
|
|
834
|
+
statusKey: string;
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Where an application puts the version a route serves. `path` puts it
|
|
838
|
+
* in the URL as a segment. `outsidePath` reads it from somewhere else
|
|
839
|
+
* in the request, such as a header, so every version of a route shares
|
|
840
|
+
* one path.
|
|
841
|
+
*/
|
|
842
|
+
type VersionPlacement = "path" | "outsidePath";
|
|
843
|
+
/**
|
|
844
|
+
* API versions on decorated routes. A route serves the versions its own
|
|
845
|
+
* method decorator states, or else the ones its class decorator's
|
|
846
|
+
* options state, or else the application's default. The application
|
|
847
|
+
* ignores every version until a call on it turns versioning on.
|
|
848
|
+
*/
|
|
849
|
+
interface RouteVersioning {
|
|
850
|
+
/** The key in the class decorator's options object, NestJS's `version`. */
|
|
851
|
+
option: string;
|
|
852
|
+
/** A method decorator imported from `importModule` that sets one route's version, NestJS's `Version`. */
|
|
853
|
+
decorator: string;
|
|
854
|
+
/** The export from `importModule` that means every version, NestJS's `VERSION_NEUTRAL`. */
|
|
855
|
+
neutral: string;
|
|
856
|
+
/** The call on the application that turns versioning on, NestJS's `enableVersioning`. */
|
|
857
|
+
call: Pick<GlobalPrefixCall, "method" | "application">;
|
|
858
|
+
/** The key in the call's options that says the placement. */
|
|
859
|
+
typeKey: string;
|
|
860
|
+
/**
|
|
861
|
+
* The placement each of the library's constants means, by the path of
|
|
862
|
+
* the export (`VersioningType.URI`), and by the number the constant is
|
|
863
|
+
* equal to when the library is installed.
|
|
864
|
+
*/
|
|
865
|
+
types: Readonly<Record<string, VersionPlacement>>;
|
|
866
|
+
typeNumbers: Readonly<Record<number, VersionPlacement>>;
|
|
867
|
+
/** The placement when the call takes no options at all. */
|
|
868
|
+
defaultType: VersionPlacement;
|
|
869
|
+
/**
|
|
870
|
+
* The key for the text put before a version in the path, and the text
|
|
871
|
+
* when the options leave it out. `false` there means no text at all.
|
|
872
|
+
*/
|
|
873
|
+
pathPrefix: {
|
|
874
|
+
key: string;
|
|
875
|
+
default: string;
|
|
876
|
+
};
|
|
877
|
+
/** The key for the versions a route that states none serves. */
|
|
878
|
+
defaultVersionKey: string;
|
|
879
|
+
}
|
|
792
880
|
/** A wrapper handed to the routable's constructor as an option. */
|
|
793
881
|
interface WrapperOptionRegistration extends WrapperFunctionShape {
|
|
794
882
|
/** The option the wrapper is under, e.g. "defaultHook". */
|
|
@@ -804,22 +892,17 @@ interface DiscoveryPattern {
|
|
|
804
892
|
/** A binding the pattern states outright. See `DeclaredBinding`. */
|
|
805
893
|
binding?: DeclaredBinding;
|
|
806
894
|
/**
|
|
807
|
-
* How the routable this pattern discovers (Express's `Router()`,
|
|
808
|
-
*
|
|
809
|
-
*
|
|
810
|
-
* `
|
|
811
|
-
*
|
|
812
|
-
* because mount discovery reuses that match's `importModule` and
|
|
813
|
-
* `importName` to work out which variables in a file are the routable
|
|
814
|
-
* that a mount call is being made on.
|
|
895
|
+
* How the routable this pattern discovers (Express's `Router()`, Hono's
|
|
896
|
+
* `new Hono()`) is mounted on another under a path prefix, as in
|
|
897
|
+
* `app.use(prefix, router)` or `app.route(prefix, sub)`. It only applies
|
|
898
|
+
* when `match.type` is `"registrationCall"`, since mount discovery uses
|
|
899
|
+
* that match's `importModule` and `importName` to find the routables.
|
|
815
900
|
*
|
|
816
|
-
*
|
|
817
|
-
*
|
|
818
|
-
* declared in the mounting file or, by following the mounted value
|
|
819
|
-
* through an import, in whichever file declares it. A mount whose
|
|
901
|
+
* The adapter adds the prefix to every route on the mounted value, in
|
|
902
|
+
* the mounting file or in the file an import leads to. A mount whose
|
|
820
903
|
* prefix is not a string literal, or whose target the resolution store
|
|
821
|
-
* cannot follow
|
|
822
|
-
*
|
|
904
|
+
* cannot follow, adds nothing, and its routes keep the path they were
|
|
905
|
+
* written with.
|
|
823
906
|
*/
|
|
824
907
|
mount?: {
|
|
825
908
|
/** Method name that registers a sub-router at a prefix, e.g. "use" or "route". */
|
|
@@ -844,22 +927,14 @@ interface DiscoveryPattern {
|
|
|
844
927
|
*/
|
|
845
928
|
wraps?: WrapperRegistration;
|
|
846
929
|
/**
|
|
847
|
-
*
|
|
848
|
-
* specifiers
|
|
849
|
-
*
|
|
850
|
-
*
|
|
851
|
-
*
|
|
852
|
-
* "match every file" choice, usually because the pattern keys on
|
|
853
|
-
* something other than imports. The fetch runtime does that, since it
|
|
854
|
-
* matches global `fetch(...)` calls.
|
|
930
|
+
* Run this pattern only on files that import one of these module
|
|
931
|
+
* specifiers or a sub-path of one, so `"@nestjs/graphql"` also matches
|
|
932
|
+
* `"@nestjs/graphql/dist/foo"`. An empty array runs it on every file, the
|
|
933
|
+
* same as leaving it unset. Write `[]` out when that is deliberate, as
|
|
934
|
+
* the fetch runtime does for global `fetch(...)` calls.
|
|
855
935
|
*
|
|
856
|
-
*
|
|
857
|
-
*
|
|
858
|
-
* `from "@nestjs/graphql/dist/foo"` and any other sub-path.
|
|
859
|
-
*
|
|
860
|
-
* This pre-filter is only there for speed. The closure walk and the other
|
|
861
|
-
* post-passes can still reach every loaded file through symbol
|
|
862
|
-
* resolution.
|
|
936
|
+
* The gate only saves time. The closure walk and the passes after
|
|
937
|
+
* discovery can still reach every loaded file through symbol resolution.
|
|
863
938
|
*/
|
|
864
939
|
requiresImport?: string[];
|
|
865
940
|
}
|
|
@@ -869,13 +944,10 @@ type TerminalMatch = {
|
|
|
869
944
|
} | {
|
|
870
945
|
type: "returnStatement";
|
|
871
946
|
/**
|
|
872
|
-
* Skip
|
|
873
|
-
*
|
|
874
|
-
*
|
|
875
|
-
*
|
|
876
|
-
* terminals, one from the wrapping returnStatement and one from
|
|
877
|
-
* the inner method-call chain. Bare returns (`return user`,
|
|
878
|
-
* `return { id }`, `return await fn()`) still match.
|
|
947
|
+
* Skip a return whose value is a call or `new` expression. Set it when
|
|
948
|
+
* a `parameterMethodCall` terminal already matches the inner call, so
|
|
949
|
+
* `return reply.send(...)` produces one terminal instead of two.
|
|
950
|
+
* Returns like `return user` and `return await fn()` still match.
|
|
879
951
|
*/
|
|
880
952
|
excludeCallReturns?: boolean;
|
|
881
953
|
} | {
|
|
@@ -896,22 +968,16 @@ type TerminalMatch = {
|
|
|
896
968
|
type: "functionCall";
|
|
897
969
|
functionName: string;
|
|
898
970
|
/**
|
|
899
|
-
* Only match when the name was imported from one of these modules
|
|
900
|
-
*
|
|
901
|
-
* prefix: "react-router" also matches "react-router/server".
|
|
902
|
-
*
|
|
903
|
-
* Set it whenever the function belongs to a library, because matching
|
|
904
|
-
* on a bare name picks up every function with that name in the
|
|
905
|
-
* user's project too. `json` is a common name for a project's own
|
|
906
|
-
* response helper, and reading a library's argument order into one
|
|
907
|
-
* of those gives you a confident wrong answer.
|
|
971
|
+
* Only match when the name was imported from one of these modules,
|
|
972
|
+
* by prefix, the same as `DiscoveryPattern.requiresImport`.
|
|
908
973
|
*
|
|
909
|
-
*
|
|
910
|
-
*
|
|
911
|
-
*
|
|
912
|
-
*
|
|
913
|
-
*
|
|
914
|
-
*
|
|
974
|
+
* Set it whenever the function belongs to a library. A bare name also
|
|
975
|
+
* matches the project's own functions, and `json` is a common name
|
|
976
|
+
* for a project's response helper. Reading a library's argument order
|
|
977
|
+
* into one of those gives a confident wrong answer. To cover a project
|
|
978
|
+
* helper, declare the envelope with a `returnShape` terminal instead:
|
|
979
|
+
* the adapter follows a returned call into the project and reads the
|
|
980
|
+
* helper's parameters, whatever the helper is called.
|
|
915
981
|
*/
|
|
916
982
|
requiresImport?: string[];
|
|
917
983
|
} | {
|
|
@@ -924,26 +990,21 @@ type TerminalMatch = {
|
|
|
924
990
|
type: "jsxReturn";
|
|
925
991
|
} | {
|
|
926
992
|
/**
|
|
927
|
-
*
|
|
928
|
-
*
|
|
929
|
-
*
|
|
930
|
-
*
|
|
931
|
-
*
|
|
932
|
-
* handler
|
|
933
|
-
* `findTerminals` has nothing to match. A pack that always expects
|
|
934
|
-
* explicit returns (HTTP handlers) should leave this out of
|
|
935
|
-
* its terminals. A pack for callback bodies (React handlers,
|
|
936
|
-
* `useEffect` bodies, Node `.on(...)` callbacks) should include it.
|
|
993
|
+
* The implicit fall-through at the end of a function body. It fires
|
|
994
|
+
* when the last statement is neither a return nor a throw, which is
|
|
995
|
+
* how most event handlers and effect bodies end. Without it, such a
|
|
996
|
+
* summary comes out with no transitions. Packs for callback bodies
|
|
997
|
+
* (React handlers, `useEffect`, Node `.on(...)`) include it, and HTTP
|
|
998
|
+
* handler packs that expect explicit returns leave it out.
|
|
937
999
|
*/
|
|
938
1000
|
type: "functionFallthrough";
|
|
939
1001
|
} | {
|
|
940
1002
|
/**
|
|
941
1003
|
* A call to the parameter at this position, `next()` inside a
|
|
942
|
-
* middleware.
|
|
943
|
-
*
|
|
944
|
-
*
|
|
945
|
-
*
|
|
946
|
-
* composition tells the two apart.
|
|
1004
|
+
* middleware. Packs do not declare it; the adapter builds it from
|
|
1005
|
+
* `DiscoveryPattern.wraps.continuationParam`. A wrapper path that
|
|
1006
|
+
* hands control on then ends in a `delegate` output, and composition
|
|
1007
|
+
* uses that to tell it from a path that responds first.
|
|
947
1008
|
*/
|
|
948
1009
|
type: "parameterCall";
|
|
949
1010
|
parameterPosition: number;
|
|
@@ -981,10 +1042,21 @@ interface TerminalExtraction {
|
|
|
981
1042
|
defaultStatusCode?: number;
|
|
982
1043
|
}
|
|
983
1044
|
interface TerminalPattern {
|
|
984
|
-
/**
|
|
985
|
-
|
|
1045
|
+
/**
|
|
1046
|
+
* What kind of output this terminal produces. An `exit` terminal ends
|
|
1047
|
+
* the process, so a path that reaches one goes no further, and the
|
|
1048
|
+
* status code it extracts is the exit code.
|
|
1049
|
+
*/
|
|
1050
|
+
kind: "response" | "throw" | "return" | "render" | "delegate" | "exit";
|
|
986
1051
|
match: TerminalMatch;
|
|
987
1052
|
extraction: TerminalExtraction;
|
|
1053
|
+
/**
|
|
1054
|
+
* Read in every unit, whichever pack discovered it, the way an
|
|
1055
|
+
* invocation recognizer is. A runtime's own way of ending the process,
|
|
1056
|
+
* `process.exit(n)`, ends a route handler and a helper alike, and the
|
|
1057
|
+
* pack that declares it discovers no units of its own.
|
|
1058
|
+
*/
|
|
1059
|
+
inEveryUnit?: boolean;
|
|
988
1060
|
/**
|
|
989
1061
|
* On a throw terminal: the framework turns the thrown status into
|
|
990
1062
|
* the wire response, so a resolved status makes the output a
|
|
@@ -1007,9 +1079,8 @@ interface ContractPattern {
|
|
|
1007
1079
|
};
|
|
1008
1080
|
/**
|
|
1009
1081
|
* The properties an endpoint states its HTTP method and path under.
|
|
1010
|
-
*
|
|
1011
|
-
*
|
|
1012
|
-
* and the adapter reads whatever it is told.
|
|
1082
|
+
* The names belong to the library, so the pack supplies them. ts-rest
|
|
1083
|
+
* and zod-openapi both use `method` and `path`.
|
|
1013
1084
|
*/
|
|
1014
1085
|
methodProperty: string;
|
|
1015
1086
|
pathProperty: string;
|
|
@@ -1073,33 +1144,23 @@ type InputMappingPattern = {
|
|
|
1073
1144
|
wholeParamRole?: string;
|
|
1074
1145
|
} | {
|
|
1075
1146
|
/**
|
|
1076
|
-
*
|
|
1077
|
-
* parameter's name as its role
|
|
1078
|
-
* reachable-closure pass for internal library functions,
|
|
1079
|
-
*
|
|
1080
|
-
*
|
|
1081
|
-
* same way `objectParam` captures them, so `(ctx, { userId })`
|
|
1082
|
-
* gives two inputs, `ctx` and `userId`.
|
|
1147
|
+
* One input per declared parameter, in source order, with the
|
|
1148
|
+
* parameter's name as its role unless `defaultRole` is set. The
|
|
1149
|
+
* reachable-closure pass uses it for internal library functions,
|
|
1150
|
+
* where no framework assigns roles. Destructured parameters work as
|
|
1151
|
+
* in `objectParam`, so `(ctx, { userId })` gives `ctx` and `userId`.
|
|
1083
1152
|
*/
|
|
1084
1153
|
type: "allPositional";
|
|
1085
1154
|
defaultRole?: string;
|
|
1086
1155
|
} | {
|
|
1087
1156
|
/**
|
|
1088
|
-
*
|
|
1089
|
-
* parameter
|
|
1090
|
-
*
|
|
1091
|
-
*
|
|
1092
|
-
*
|
|
1093
|
-
* `
|
|
1094
|
-
*
|
|
1095
|
-
* For `@nestjs/graphql` resolvers:
|
|
1096
|
-
* `{ "Args": "args", "Parent": "parent",
|
|
1097
|
-
* "Context": "context", "Info": "info" }`.
|
|
1098
|
-
*
|
|
1099
|
-
* Decorators are matched by name alone, so if several frameworks
|
|
1100
|
-
* define `@Args`, all of them map. Packs that need to
|
|
1101
|
-
* tell them apart by import module can add that later, once there
|
|
1102
|
-
* is a use case worth the cost.
|
|
1157
|
+
* NestJS-style parameter decorators. The adapter looks up each
|
|
1158
|
+
* parameter's first decorator in `decoratorRoleMap`. A match gives the
|
|
1159
|
+
* role, and a parameter that matches nothing gets `defaultRole` or is
|
|
1160
|
+
* skipped. For `@nestjs/graphql` resolvers the map is
|
|
1161
|
+
* `{ Args: "args", Parent: "parent", Context: "context", Info: "info" }`.
|
|
1162
|
+
* Decorators match by name alone, so every framework's `@Args` maps
|
|
1163
|
+
* the same way.
|
|
1103
1164
|
*/
|
|
1104
1165
|
type: "decoratedParams";
|
|
1105
1166
|
decoratorRoleMap: Record<string, string>;
|
|
@@ -1123,6 +1184,18 @@ type ResponsePropertyMeaning = {
|
|
|
1123
1184
|
};
|
|
1124
1185
|
/** Whether a refused request comes back as a response or as an exception. */
|
|
1125
1186
|
type FailureDelivery = "response" | "exception";
|
|
1187
|
+
/** Whether the client follows a redirect itself or hands the 3xx to the caller. */
|
|
1188
|
+
type RedirectDelivery = "followed" | "response";
|
|
1189
|
+
/**
|
|
1190
|
+
* The request option that decides, for one call, whether the client
|
|
1191
|
+
* follows a redirect: `redirect` for fetch, `maxRedirects` for axios,
|
|
1192
|
+
* `allow_redirects` for requests. A call that sets it to one of
|
|
1193
|
+
* `handsBack` gets the 3xx, and any other value it settles on follows.
|
|
1194
|
+
*/
|
|
1195
|
+
interface RedirectOption {
|
|
1196
|
+
name: string;
|
|
1197
|
+
handsBack: ReadonlyArray<string | number | boolean>;
|
|
1198
|
+
}
|
|
1126
1199
|
interface ResponsePropertyMapping {
|
|
1127
1200
|
/** Property or method name on the response (e.g. "ok", "status", "json") */
|
|
1128
1201
|
name: string;
|
|
@@ -1138,31 +1211,57 @@ interface ResponsePropertyMapping {
|
|
|
1138
1211
|
* say so.
|
|
1139
1212
|
*/
|
|
1140
1213
|
interface TransparentWrapper {
|
|
1141
|
-
/** Callee text as written, e.g. "Sentry.wrapHandler". */
|
|
1142
|
-
callee: string;
|
|
1143
|
-
/** Which argument the wrapped function is passed as. */
|
|
1144
|
-
argument: number;
|
|
1145
1214
|
/**
|
|
1146
|
-
* The module
|
|
1147
|
-
*
|
|
1215
|
+
* The module that exports the wrapper, e.g. "@sentry/aws-serverless".
|
|
1216
|
+
* A call matches whatever the project calls the import, and a local
|
|
1217
|
+
* function spelled the same way does not match.
|
|
1148
1218
|
*/
|
|
1149
1219
|
module: string;
|
|
1220
|
+
/** The name the module exports the wrapper under, e.g. "wrapHandler". */
|
|
1221
|
+
name: string;
|
|
1222
|
+
/** Which argument the wrapped function is passed as. */
|
|
1223
|
+
argument: number;
|
|
1224
|
+
}
|
|
1225
|
+
/**
|
|
1226
|
+
* A library decorator that fills the parameter it decorates. The library
|
|
1227
|
+
* builds the value, so nothing in the project describes it, and the
|
|
1228
|
+
* decorator call is the only thing that says what the parameter is.
|
|
1229
|
+
*/
|
|
1230
|
+
interface ParameterSupplier {
|
|
1231
|
+
/** The module that exports the decorator, e.g. "@nestjs/typeorm". */
|
|
1232
|
+
module: string;
|
|
1233
|
+
/** The name the module exports the decorator under. */
|
|
1234
|
+
name: string;
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* A command-line parser a runtime or library provides, and where its
|
|
1238
|
+
* settings say which flags a command takes. `parseArgs({ args, options })`
|
|
1239
|
+
* from `node:util` is one: its options object lists every flag, and
|
|
1240
|
+
* nothing else in the command's body ever spells them.
|
|
1241
|
+
*/
|
|
1242
|
+
interface ArgumentParser {
|
|
1243
|
+
/** The module that exports the parser, e.g. `"node:util"`. */
|
|
1244
|
+
module: string;
|
|
1245
|
+
/** The name the module exports it under, e.g. `"parseArgs"`. */
|
|
1246
|
+
name: string;
|
|
1247
|
+
/** Which argument the settings object is passed as. */
|
|
1248
|
+
argument: number;
|
|
1249
|
+
/** The settings key the command-line arguments are passed under, e.g. `"args"`. */
|
|
1250
|
+
argsKey: string;
|
|
1251
|
+
/** The settings key whose object has one key per flag, e.g. `"options"`. */
|
|
1252
|
+
optionsKey: string;
|
|
1150
1253
|
}
|
|
1151
1254
|
interface PatternPack {
|
|
1152
1255
|
name: string;
|
|
1153
1256
|
/**
|
|
1154
|
-
*
|
|
1155
|
-
*
|
|
1156
|
-
* Format is opaque to the adapter, so semver or a content hash both
|
|
1157
|
-
* work.
|
|
1257
|
+
* The pack's version, part of the cache key. Change it whenever a change
|
|
1258
|
+
* affects discovered units or summaries; any string works.
|
|
1158
1259
|
*
|
|
1159
|
-
*
|
|
1160
|
-
*
|
|
1161
|
-
*
|
|
1162
|
-
*
|
|
1163
|
-
*
|
|
1164
|
-
* A pack with nothing to stamp comes out as `"unset"`, and a warm cache
|
|
1165
|
-
* will then serve results for code that has since changed.
|
|
1260
|
+
* It is optional because the CLI hashes the pack file it loaded and the
|
|
1261
|
+
* config it passed into the key, so an edit invalidates the cache
|
|
1262
|
+
* whether or not the version moved. A host that loads packs another way
|
|
1263
|
+
* has to do that itself. A pack with nothing to stamp is keyed as
|
|
1264
|
+
* `"unset"`, and a warm cache then serves stale results after an edit.
|
|
1166
1265
|
*/
|
|
1167
1266
|
version?: string;
|
|
1168
1267
|
/**
|
|
@@ -1196,18 +1295,12 @@ interface PatternPack {
|
|
|
1196
1295
|
*/
|
|
1197
1296
|
requestSpelling?: RequestSpellingMetadata;
|
|
1198
1297
|
/**
|
|
1199
|
-
*
|
|
1200
|
-
*
|
|
1201
|
-
*
|
|
1202
|
-
* does
|
|
1203
|
-
*
|
|
1204
|
-
*
|
|
1205
|
-
* that does not fit it.
|
|
1206
|
-
*
|
|
1207
|
-
* The pack's `name` separately fills in `BoundaryBinding.recognition`
|
|
1208
|
-
* on the summaries, so `{ transport, recognition }` come from
|
|
1209
|
-
* the pack directly and the adapter derives `semantics` from the
|
|
1210
|
-
* discovery pattern's binding-extraction rules.
|
|
1298
|
+
* The transport written into `BoundaryBinding.transport` on discovered
|
|
1299
|
+
* units, such as `"http"` or `"in-process"`. It is required so a pack
|
|
1300
|
+
* for React, queues or Lambda invocation never inherits an HTTP default
|
|
1301
|
+
* that does not fit it. The pack's `name` fills in
|
|
1302
|
+
* `BoundaryBinding.recognition`, and the adapter derives `semantics`
|
|
1303
|
+
* from the discovery pattern's binding extraction.
|
|
1211
1304
|
*/
|
|
1212
1305
|
protocol: string;
|
|
1213
1306
|
/**
|
|
@@ -1225,137 +1318,66 @@ interface PatternPack {
|
|
|
1225
1318
|
*/
|
|
1226
1319
|
failureDelivery?: FailureDelivery;
|
|
1227
1320
|
/**
|
|
1228
|
-
*
|
|
1229
|
-
*
|
|
1230
|
-
*
|
|
1231
|
-
*
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
*
|
|
1238
|
-
*
|
|
1239
|
-
*
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1242
|
-
*
|
|
1321
|
+
* What this client does with a redirect by default. `fetch` and axios
|
|
1322
|
+
* follow it, so the caller only ever sees the response at the end of
|
|
1323
|
+
* the chain. httpx and Faraday hand the 3xx back. Defaults to
|
|
1324
|
+
* `"response"`.
|
|
1325
|
+
*/
|
|
1326
|
+
redirectDelivery?: RedirectDelivery;
|
|
1327
|
+
/** The option one call sets to change `redirectDelivery` for itself. */
|
|
1328
|
+
redirectOption?: RedirectOption;
|
|
1329
|
+
/**
|
|
1330
|
+
* Build extra code units from a parent unit's body, for callbacks the
|
|
1331
|
+
* runtime schedules that are not top-level declarations: React event
|
|
1332
|
+
* handlers on JSX elements, `useEffect` bodies, Node `emitter.on(...)`
|
|
1333
|
+
* handlers. Each returned unit goes through the same extraction as a
|
|
1334
|
+
* discovered one and gets its own summary. Set `terminals` or
|
|
1335
|
+
* `inputMapping` on a sub-unit when it differs from the pack's defaults.
|
|
1243
1336
|
*
|
|
1244
|
-
*
|
|
1245
|
-
*
|
|
1246
|
-
*
|
|
1247
|
-
*
|
|
1248
|
-
* the parent pack's defaults.
|
|
1337
|
+
* `ctx` is `unknown` because each adapter defines its own context type
|
|
1338
|
+
* (`TsSubUnitContext` in `@suss/adapter-typescript`) with the primitives
|
|
1339
|
+
* for walking the parent's syntax tree. A pack casts to the context it
|
|
1340
|
+
* was written against, which ties the pack to that adapter.
|
|
1249
1341
|
*/
|
|
1250
1342
|
subUnits?: (parent: DiscoveredSubUnitParent, ctx: unknown) => DiscoveredSubUnit[];
|
|
1251
1343
|
/**
|
|
1252
|
-
*
|
|
1253
|
-
*
|
|
1254
|
-
*
|
|
1255
|
-
*
|
|
1256
|
-
*
|
|
1257
|
-
*
|
|
1258
|
-
*
|
|
1259
|
-
* Use this for framework-specific patterns that do not generalize:
|
|
1260
|
-
* React's component-export heuristic (PascalCase plus a JSX return),
|
|
1261
|
-
* Vue's `.vue` SFC slots, Solid's component conventions, Storybook's
|
|
1262
|
-
* `.stories.tsx` file convention. Those are all legitimate conventions,
|
|
1263
|
-
* but baking each one into the central `DiscoveryMatch` union forces
|
|
1264
|
-
* every unrelated pack to know about them. Callbacks leave the central
|
|
1265
|
-
* union for the generic primitives and let each pack own its own
|
|
1266
|
-
* conventions.
|
|
1267
|
-
*
|
|
1268
|
-
* `ctx` is typed `unknown` for the same reason as in `subUnits`: each
|
|
1269
|
-
* adapter ships its own context primitive (`TsDiscoveryContext` in
|
|
1270
|
-
* `@suss/adapter-typescript`) and a pack casts to whichever one it was
|
|
1271
|
-
* written against. That cast is how the pack says it requires the TS
|
|
1272
|
-
* adapter.
|
|
1344
|
+
* The pack's own top-level discovery, for a convention none of the
|
|
1345
|
+
* `DiscoveryMatch` variants fits, such as React's component-export
|
|
1346
|
+
* heuristic or Storybook's `.stories.tsx` files. Keeping those in the
|
|
1347
|
+
* pack leaves the `DiscoveryMatch` union to patterns any pack can share.
|
|
1348
|
+
* The adapter calls it once per source file beside the data-driven
|
|
1349
|
+
* discovery, and the units it returns go through the normal pipeline
|
|
1350
|
+
* with the same per-unit overrides.
|
|
1273
1351
|
*
|
|
1274
|
-
*
|
|
1275
|
-
*
|
|
1276
|
-
*
|
|
1277
|
-
*
|
|
1278
|
-
* `DiscoveredUnit` work the same way too.
|
|
1279
|
-
*
|
|
1280
|
-
* **Cross-pack dedup.** When this callback discovers a unit at the
|
|
1281
|
-
* same `(func, kind)` as a unit from another pack's data-driven
|
|
1282
|
-
* discovery, the adapter's cross-pack claim dedup keeps whichever
|
|
1283
|
-
* claimed it first. The order packs appear in the framework list is
|
|
1284
|
-
* what decides precedence.
|
|
1352
|
+
* `ctx` is `unknown` for the same reason as in `subUnits`
|
|
1353
|
+
* (`TsDiscoveryContext` in `@suss/adapter-typescript`). When this finds
|
|
1354
|
+
* a unit at the same function and kind as another pack's discovery, the
|
|
1355
|
+
* pack that comes first in the framework list claims it.
|
|
1285
1356
|
*/
|
|
1286
1357
|
discoverUnits?: (sourceFile: unknown, ctx: unknown) => DiscoveredCustomUnit[];
|
|
1287
1358
|
/**
|
|
1288
|
-
* Per-call
|
|
1289
|
-
*
|
|
1290
|
-
*
|
|
1291
|
-
*
|
|
1292
|
-
*
|
|
1293
|
-
* for each call. Walking skips nested function bodies (those are
|
|
1294
|
-
* their own units with their own recognizer dispatch). The walk is
|
|
1295
|
-
* INDEPENDENT of the existing invocation-effect walker, which is
|
|
1296
|
-
* deliberately narrow (it only captures
|
|
1297
|
-
* `invocation` effects from bare expression statements and container
|
|
1298
|
-
* composition, to avoid double-counting calls that already become
|
|
1299
|
-
* terminals). Recognizers do not have that problem, so they fire on
|
|
1300
|
-
* every call regardless of position, including
|
|
1301
|
-
* `const x = await fn(...)` initializers and nested call args
|
|
1302
|
-
* (which the invocation walker skips). This independence means
|
|
1303
|
-
* recognizer authors can rely on seeing every call in scope.
|
|
1304
|
-
*
|
|
1305
|
-
* **Cross-pack visibility.** Recognizers fire regardless of which pack
|
|
1306
|
-
* discovered the enclosing function, so
|
|
1307
|
-
* `@suss/framework-prisma`'s recognizer can fire on Prisma calls
|
|
1308
|
-
* inside an `@suss/framework-express` handler. Pack authors don't
|
|
1309
|
-
* need to coordinate.
|
|
1310
|
-
*
|
|
1311
|
-
* **Emission contract.** Returning effects ADDS them to the enclosing
|
|
1312
|
-
* default-branch transition, and the generic `invocation` effect is
|
|
1313
|
-
* kept either way (typed effects live alongside the raw
|
|
1314
|
-
* call capture, so inspect can still render the callee text and
|
|
1315
|
-
* arguments while the checker pairs on the typed form). Return `null`
|
|
1316
|
-
* or `[]` for no match.
|
|
1359
|
+
* Per-call recognizers that emit typed `Effect`s beside the generic
|
|
1360
|
+
* `invocation` effect. The adapter calls each one on every call in the
|
|
1361
|
+
* function body, whichever pack discovered the function, and skips
|
|
1362
|
+
* nested functions, which are units of their own. Calls the invocation
|
|
1363
|
+
* walk skips, such as `const x = await fn(...)` initializers, are included.
|
|
1317
1364
|
*
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
*
|
|
1323
|
-
*
|
|
1324
|
-
* logged to stderr with the file path and line number, and is skipped
|
|
1325
|
-
* for that one call while the extraction carries on. A buggy
|
|
1326
|
-
* recognizer will not crash the run.
|
|
1327
|
-
*
|
|
1328
|
-
* `call` is the language adapter's call-expression handle (opaque
|
|
1329
|
-
* here; ts-morph `CallExpression` in `@suss/adapter-typescript`).
|
|
1330
|
-
* `ctx` is the adapter's recognizer context (source file, an
|
|
1331
|
-
* `extractArgs()` helper that reuses the adapter's own EffectArg
|
|
1332
|
-
* builder). A recognizer casts both to the adapter context it was
|
|
1333
|
-
* written against, which is the same way `subUnits` says a pack
|
|
1334
|
-
* requires the TypeScript adapter.
|
|
1365
|
+
* Returned effects are added to the enclosing default transition, and
|
|
1366
|
+
* the `invocation` effect stays. Return `null` or `[]` for no match.
|
|
1367
|
+
* Nothing dedupes across calls, so a recognizer that should fire once
|
|
1368
|
+
* per identifier tracks that itself. One that throws is logged with its
|
|
1369
|
+
* file and line and skipped for that call. `call` and `ctx` are the
|
|
1370
|
+
* adapter's own types, which a recognizer casts to as `subUnits` does.
|
|
1335
1371
|
*/
|
|
1336
1372
|
invocationRecognizers?: InvocationRecognizer[];
|
|
1337
1373
|
/**
|
|
1338
|
-
*
|
|
1339
|
-
*
|
|
1340
|
-
*
|
|
1341
|
-
*
|
|
1342
|
-
* and
|
|
1343
|
-
*
|
|
1344
|
-
*
|
|
1345
|
-
* `@suss/framework-aws-sqs` declares `["@aws-sdk/client-sqs"]`,
|
|
1346
|
-
* `@suss/framework-prisma` declares `["@prisma/client"]`. Without
|
|
1347
|
-
* a gate, a recognizer-only pack walks every file in the project. That
|
|
1348
|
-
* is correct but wasteful in a large monorepo where most files never
|
|
1349
|
-
* import the library.
|
|
1350
|
-
*
|
|
1351
|
-
* A discovery-pattern pack already has a per-pattern `requiresImport`
|
|
1352
|
-
* on `DiscoveryPattern`. This is the pack-level version of that, for a
|
|
1353
|
-
* pack whose ONLY mechanism is recognizers and which has no discovery.
|
|
1354
|
-
*
|
|
1355
|
-
* Empty or undefined means no gate, so the pack walks every file (the
|
|
1356
|
-
* default for universal recognizers like `@suss/runtime-node`'s
|
|
1357
|
-
* process-surface and env-var recognizers, since `process.*` is
|
|
1358
|
-
* available without importing anything).
|
|
1374
|
+
* A pack-level import gate: the pack applies only to files that import
|
|
1375
|
+
* one of these modules, matched by prefix. A pack with only recognizers
|
|
1376
|
+
* uses it the way a discovery pattern uses its own `requiresImport`;
|
|
1377
|
+
* `@suss/framework-prisma` declares `["@prisma/client"]`. Without a gate
|
|
1378
|
+
* the pack walks every file, which gives the same result and is slow in
|
|
1379
|
+
* a large monorepo. Leave it empty for recognizers that apply
|
|
1380
|
+
* everywhere, such as `process.env` reads, which need no import.
|
|
1359
1381
|
*/
|
|
1360
1382
|
requiresImport?: string[];
|
|
1361
1383
|
/**
|
|
@@ -1368,6 +1390,16 @@ interface PatternPack {
|
|
|
1368
1390
|
* ordinary import would.
|
|
1369
1391
|
*/
|
|
1370
1392
|
generatedModuleMarkers?: string[];
|
|
1393
|
+
/**
|
|
1394
|
+
* The directories this library's code generator writes to, as the
|
|
1395
|
+
* project's own configuration says, for a generator that leaves no
|
|
1396
|
+
* marker file. Given the directory of a file that imports by relative
|
|
1397
|
+
* path, it returns the output directories the configuration governing
|
|
1398
|
+
* that file gives. An import into one counts as the gated package, the
|
|
1399
|
+
* same as a directory with a marker in it, even before the generator
|
|
1400
|
+
* has run.
|
|
1401
|
+
*/
|
|
1402
|
+
generatedModuleDirs?: (fromDir: string) => readonly string[];
|
|
1371
1403
|
/**
|
|
1372
1404
|
* Functions the project itself wrote in front of this library, read
|
|
1373
1405
|
* once across the whole project before any file is walked. What the
|
|
@@ -1376,14 +1408,13 @@ interface PatternPack {
|
|
|
1376
1408
|
*/
|
|
1377
1409
|
projectHelpers?: ProjectHelpers;
|
|
1378
1410
|
/**
|
|
1379
|
-
* Environment variables the
|
|
1380
|
-
*
|
|
1381
|
-
*
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
*
|
|
1385
|
-
*
|
|
1386
|
-
* scoped family like `@aws-lambda-powertools/`.
|
|
1411
|
+
* Environment variables the library reads from inside node_modules,
|
|
1412
|
+
* where no walk looks. Without them the checker would report a variable
|
|
1413
|
+
* in a template as unused when the library reads it on every invocation.
|
|
1414
|
+
* The adapter emits one marker summary per entry whose `module` some
|
|
1415
|
+
* project file imports, and runtime-config pairing checks the markers
|
|
1416
|
+
* before reporting. `module` matches as a prefix, so one entry covers a
|
|
1417
|
+
* family like `@aws-lambda-powertools/`.
|
|
1387
1418
|
*/
|
|
1388
1419
|
libraryEnvVars?: Array<{
|
|
1389
1420
|
/** Module-specifier prefix the library's imports start with. */
|
|
@@ -1394,16 +1425,18 @@ interface PatternPack {
|
|
|
1394
1425
|
names?: string[];
|
|
1395
1426
|
}>;
|
|
1396
1427
|
/**
|
|
1397
|
-
* Library wrappers that return the function they
|
|
1398
|
-
*
|
|
1399
|
-
*
|
|
1400
|
-
* pack has to say it: a call to `callee` resolves to its
|
|
1401
|
-
* `argument`-th argument.
|
|
1402
|
-
*
|
|
1403
|
-
* `callee` matches the call expression text as written, e.g.
|
|
1404
|
-
* `"Sentry.wrapHandler"`.
|
|
1428
|
+
* Library wrappers that return the function they were handed. A call to
|
|
1429
|
+
* the `name` that `module` exports resolves to its `argument`-th
|
|
1430
|
+
* argument. See `TransparentWrapper`.
|
|
1405
1431
|
*/
|
|
1406
1432
|
transparentWrappers?: TransparentWrapper[];
|
|
1433
|
+
/**
|
|
1434
|
+
* Parameter decorators whose call is the value a container passes
|
|
1435
|
+
* in. A constructor parameter written `@InjectRepository(User) repo`
|
|
1436
|
+
* then reads as that call, and a pack can match `this.repo.find()` by
|
|
1437
|
+
* the decorator it came from.
|
|
1438
|
+
*/
|
|
1439
|
+
parameterSuppliers?: ParameterSupplier[];
|
|
1407
1440
|
/**
|
|
1408
1441
|
* Objects whose properties are the process environment, written as
|
|
1409
1442
|
* the dotted path the code spells, e.g. `"process.env"`. The adapter
|
|
@@ -1412,6 +1445,27 @@ interface PatternPack {
|
|
|
1412
1445
|
* parameter gets its reads reported at the calls that named them.
|
|
1413
1446
|
*/
|
|
1414
1447
|
environmentObjects?: string[];
|
|
1448
|
+
/**
|
|
1449
|
+
* The process's output streams, written the same way, e.g.
|
|
1450
|
+
* `"process.stdout"`. The adapter follows each one into the helpers
|
|
1451
|
+
* it is passed to, so a write through a stream parameter can say
|
|
1452
|
+
* which stream it goes to.
|
|
1453
|
+
*/
|
|
1454
|
+
streamObjects?: string[];
|
|
1455
|
+
/**
|
|
1456
|
+
* Dotted paths a program assigns its exit code to without ending
|
|
1457
|
+
* there, e.g. `"process.exitCode"`. The value assigned, and the
|
|
1458
|
+
* argument of a call an `exit` terminal matches, are where the adapter
|
|
1459
|
+
* starts when it works out which functions' returns become the code.
|
|
1460
|
+
*/
|
|
1461
|
+
exitCodeWrites?: string[];
|
|
1462
|
+
/**
|
|
1463
|
+
* Command-line parsers, read in every unit whichever pack found it.
|
|
1464
|
+
* Each flag a call to one declares becomes an input read of `--flag`
|
|
1465
|
+
* off the parameter the call hands its arguments from, so a command's
|
|
1466
|
+
* intent can list its flags under `receives`.
|
|
1467
|
+
*/
|
|
1468
|
+
argumentParsers?: ArgumentParser[];
|
|
1415
1469
|
/**
|
|
1416
1470
|
* How this library's client object is constructed, so an operation
|
|
1417
1471
|
* summary can say which endpoint its calls go to. Each entry is a
|
|
@@ -1466,41 +1520,26 @@ interface PatternPack {
|
|
|
1466
1520
|
workspace: string;
|
|
1467
1521
|
}>;
|
|
1468
1522
|
/**
|
|
1469
|
-
* Per-
|
|
1470
|
-
*
|
|
1471
|
-
*
|
|
1472
|
-
*
|
|
1473
|
-
*
|
|
1474
|
-
*
|
|
1475
|
-
* A recognizer here is handed a property access, a call, or a tagged
|
|
1476
|
-
* template, and guards its own shapes. The tagged template is there
|
|
1477
|
-
* for a library that takes its whole argument as one, the way
|
|
1478
|
-
* `prisma.$queryRaw` and `gql` do.
|
|
1479
|
-
*
|
|
1480
|
-
* The scope rules are the same as for invocationRecognizers: it fires
|
|
1481
|
-
* on every such node in the function body and skips nested function
|
|
1482
|
-
* bodies. The emission contract is the same, so effects land on the
|
|
1483
|
-
* enclosing default-branch transition.
|
|
1484
|
-
*
|
|
1485
|
-
* The arguments are opaque here and narrowed by the adapter, for the
|
|
1486
|
-
* same reason as in invocationRecognizers.
|
|
1523
|
+
* Per-access recognizers, the counterpart to `invocationRecognizers` for
|
|
1524
|
+
* values read without a call, such as `process.env.X`. A recognizer is
|
|
1525
|
+
* handed a property access, a call or a tagged template, and checks the
|
|
1526
|
+
* node itself. The tagged template covers libraries that take a whole
|
|
1527
|
+
* template as one argument, like `prisma.$queryRaw` and `gql`. Scope,
|
|
1528
|
+
* emission and argument types follow the `invocationRecognizers` rules.
|
|
1487
1529
|
*/
|
|
1488
1530
|
accessRecognizers?: AccessRecognizer[];
|
|
1489
1531
|
/**
|
|
1490
|
-
* What the pack wrote as data
|
|
1491
|
-
*
|
|
1492
|
-
* itself the thing the report says.
|
|
1532
|
+
* What the pack wrote as data, for the pack health report. A pack
|
|
1533
|
+
* written as a hand-rolled walk leaves it out, and the report says so.
|
|
1493
1534
|
*/
|
|
1494
1535
|
declarations?: PackDeclarations;
|
|
1495
1536
|
}
|
|
1496
1537
|
/**
|
|
1497
|
-
*
|
|
1498
|
-
*
|
|
1499
|
-
*
|
|
1500
|
-
*
|
|
1501
|
-
*
|
|
1502
|
-
* answered with a function is code that only its own language runs.
|
|
1503
|
-
* Both are allowed, and the report says which is which.
|
|
1538
|
+
* How much of what a pack matches is declared as data and how much is
|
|
1539
|
+
* code, counted for the pack health report. A link given as data can be
|
|
1540
|
+
* inspected, serialized and run by any adapter. A link given as a
|
|
1541
|
+
* function only runs in its own language. Both are allowed, and the
|
|
1542
|
+
* report counts each kind.
|
|
1504
1543
|
*/
|
|
1505
1544
|
interface PackDeclarations {
|
|
1506
1545
|
declarations: DeclaredMatch[];
|
|
@@ -1523,22 +1562,19 @@ interface DeclaredMatch {
|
|
|
1523
1562
|
example: string | null;
|
|
1524
1563
|
}
|
|
1525
1564
|
/**
|
|
1526
|
-
* Per-call
|
|
1527
|
-
*
|
|
1565
|
+
* Per-call recognizer hook. `PatternPack.invocationRecognizers` says when
|
|
1566
|
+
* it is called and what it returns.
|
|
1528
1567
|
*/
|
|
1529
1568
|
type InvocationRecognizer<TCtx = unknown> = (call: unknown, ctx: TCtx) => Effect[] | null;
|
|
1530
1569
|
/**
|
|
1531
|
-
* Per-
|
|
1532
|
-
*
|
|
1570
|
+
* Per-access recognizer hook. `PatternPack.accessRecognizers` says when
|
|
1571
|
+
* it is called and what it returns.
|
|
1533
1572
|
*/
|
|
1534
1573
|
type AccessRecognizer<TCtx = unknown> = (access: unknown, ctx: TCtx) => Effect[] | null;
|
|
1535
1574
|
/**
|
|
1536
|
-
* The
|
|
1537
|
-
*
|
|
1538
|
-
*
|
|
1539
|
-
* the extractor only so `PatternPack` can refer to it, and the adapter-level
|
|
1540
|
-
* context types like `TsSubUnitContext` narrow `func` to a concrete AST
|
|
1541
|
-
* handle.
|
|
1575
|
+
* The parent unit a `subUnits` hook works inside. `func` is opaque because
|
|
1576
|
+
* each adapter has its own function-root type; adapter context types such
|
|
1577
|
+
* as `TsSubUnitContext` narrow it.
|
|
1542
1578
|
*/
|
|
1543
1579
|
interface DiscoveredSubUnitParent {
|
|
1544
1580
|
/** Handle to the parent's function body. Opaque at extractor level. */
|
|
@@ -1549,15 +1585,11 @@ interface DiscoveredSubUnitParent {
|
|
|
1549
1585
|
kind: string;
|
|
1550
1586
|
}
|
|
1551
1587
|
/**
|
|
1552
|
-
*
|
|
1553
|
-
*
|
|
1554
|
-
*
|
|
1555
|
-
*
|
|
1556
|
-
*
|
|
1557
|
-
*
|
|
1558
|
-
* Pack authors only ever see opaque handles: `func` is whatever the adapter's
|
|
1559
|
-
* primitive returned, and the adapter narrows it to its concrete
|
|
1560
|
-
* function-root type (`FunctionRoot` in `@suss/adapter-typescript`).
|
|
1588
|
+
* One top-level unit a pack's `discoverUnits` hook found. The adapter
|
|
1589
|
+
* widens it into its own internal unit type and runs it through the
|
|
1590
|
+
* normal extraction pipeline. `func` is whatever the adapter's primitive
|
|
1591
|
+
* returned, and the adapter narrows it to its function-root type
|
|
1592
|
+
* (`FunctionRoot` in `@suss/adapter-typescript`).
|
|
1561
1593
|
*/
|
|
1562
1594
|
interface DiscoveredCustomUnit {
|
|
1563
1595
|
/** Function body handle, opaque here. */
|
|
@@ -1567,10 +1599,9 @@ interface DiscoveredCustomUnit {
|
|
|
1567
1599
|
/** Discovered name (e.g. "UserCard"). */
|
|
1568
1600
|
name: string;
|
|
1569
1601
|
/**
|
|
1570
|
-
* The unit
|
|
1571
|
-
*
|
|
1572
|
-
*
|
|
1573
|
-
* adapter puts both on the unit's function-call binding.
|
|
1602
|
+
* The module the unit is exported from and its export name, when the
|
|
1603
|
+
* pack states them. Server actions use this so intent and keyed pairing
|
|
1604
|
+
* can refer to them. The adapter puts both on the function-call binding.
|
|
1574
1605
|
*/
|
|
1575
1606
|
functionCallInfo?: {
|
|
1576
1607
|
module: string;
|
|
@@ -1587,19 +1618,15 @@ interface DiscoveredCustomUnit {
|
|
|
1587
1618
|
*/
|
|
1588
1619
|
inputMapping?: InputMappingPattern;
|
|
1589
1620
|
/**
|
|
1590
|
-
* REST route
|
|
1591
|
-
*
|
|
1592
|
-
*
|
|
1593
|
-
*
|
|
1594
|
-
*
|
|
1595
|
-
* `routeInfo`, and the discoverUnits callback never has to reach into
|
|
1596
|
-
* the adapter's binding machinery. Either half is null when the
|
|
1597
|
-
* source does not state it, and a binding missing one pairs with
|
|
1598
|
-
* nothing.
|
|
1621
|
+
* The REST route for a unit found through an external manifest, such as
|
|
1622
|
+
* a SAM template's `Events` block, instead of an in-code registration.
|
|
1623
|
+
* The adapter builds a `rest` binding from it, the same one a NestJS
|
|
1624
|
+
* controller gets. Leave either half null when the source does not
|
|
1625
|
+
* state it; a binding missing one pairs with nothing.
|
|
1599
1626
|
*
|
|
1600
|
-
*
|
|
1601
|
-
* per
|
|
1602
|
-
*
|
|
1627
|
+
* A function bound to several routes returns one unit per route. The
|
|
1628
|
+
* per-file claim dedup keys on function, kind, method and path, so all
|
|
1629
|
+
* of them are kept.
|
|
1603
1630
|
*/
|
|
1604
1631
|
routeInfo?: {
|
|
1605
1632
|
method: string | null;
|
|
@@ -1645,9 +1672,8 @@ interface DiscoveredCustomUnit {
|
|
|
1645
1672
|
metadata?: Record<string, unknown>;
|
|
1646
1673
|
}
|
|
1647
1674
|
/**
|
|
1648
|
-
*
|
|
1649
|
-
*
|
|
1650
|
-
* pipeline used for top-level-discovered units.
|
|
1675
|
+
* One child unit a pack's `subUnits` hook built. The adapter extracts and
|
|
1676
|
+
* assembles it the same way as a top-level unit.
|
|
1651
1677
|
*/
|
|
1652
1678
|
interface DiscoveredSubUnit {
|
|
1653
1679
|
/** Function body handle, opaque here. */
|
|
@@ -1681,8 +1707,8 @@ interface DiscoveredSubUnit {
|
|
|
1681
1707
|
* again.
|
|
1682
1708
|
*
|
|
1683
1709
|
* The `Cond` type parameter is the language's own handle for a condition
|
|
1684
|
-
* expression (a ts-morph Expression
|
|
1685
|
-
*
|
|
1710
|
+
* expression (a ts-morph Expression in TypeScript, a tree-sitter node in
|
|
1711
|
+
* Python and Ruby). The engine passes it through untouched for a caller
|
|
1686
1712
|
* to parse afterwards, and never looks inside it.
|
|
1687
1713
|
*/
|
|
1688
1714
|
/** Where a condition came from, in terms of what that branch's body does. */
|
|
@@ -1723,18 +1749,18 @@ interface CaseGroup<Cond> {
|
|
|
1723
1749
|
readonly body: StatementBlock<Cond>;
|
|
1724
1750
|
}
|
|
1725
1751
|
/**
|
|
1726
|
-
*
|
|
1752
|
+
* The fields every lowered statement has, whichever construct it is.
|
|
1727
1753
|
*
|
|
1728
1754
|
* The lowering works `exitKind` out by scanning the statement's own
|
|
1729
1755
|
* subtree for a return or a throw, skipping every nested function body.
|
|
1730
1756
|
*
|
|
1731
1757
|
* `callbacks` is the bodies of the functions this statement passes to
|
|
1732
|
-
* calls it makes,
|
|
1758
|
+
* calls it makes, when the language treats those as running for the
|
|
1733
1759
|
* enclosing unit. The engine walks them on the same path as the
|
|
1734
1760
|
* statement, so their branches are the unit's branches. Their `return`
|
|
1735
|
-
*
|
|
1736
|
-
* statement.
|
|
1737
|
-
*
|
|
1761
|
+
* does not leave the unit, so a path that ends inside one continues past
|
|
1762
|
+
* the statement. When a lowering leaves the field out, no callback bodies
|
|
1763
|
+
* are walked.
|
|
1738
1764
|
*/
|
|
1739
1765
|
interface LoweredStatementParts<Cond> {
|
|
1740
1766
|
readonly exitKind: ExitKind;
|
|
@@ -1765,7 +1791,7 @@ type StructuredStatement<Cond = unknown> = (LoweredStatementParts<Cond> & {
|
|
|
1765
1791
|
readonly kind: "try";
|
|
1766
1792
|
readonly tryBody: StatementBlock<Cond>;
|
|
1767
1793
|
readonly catchBody: StatementBlock<Cond> | null;
|
|
1768
|
-
/**
|
|
1794
|
+
/** Kept only for validation. The engine does not model a finally that exits or contains one of the caller's terminals, and never enumerates its conditions. */
|
|
1769
1795
|
readonly finallyBody: StatementBlock<Cond> | null;
|
|
1770
1796
|
}) | (LoweredStatementParts<Cond> & {
|
|
1771
1797
|
readonly kind: "exit";
|
|
@@ -1780,14 +1806,14 @@ type StructuredStatement<Cond = unknown> = (LoweredStatementParts<Cond> & {
|
|
|
1780
1806
|
* value in.
|
|
1781
1807
|
*
|
|
1782
1808
|
* A reader that returns `T | null` makes null mean three things at once: the
|
|
1783
|
-
* source left the value out, the source
|
|
1809
|
+
* source left the value out, the source wrote it and the reader could not
|
|
1784
1810
|
* evaluate it, or several candidates matched and the reader picked none.
|
|
1785
|
-
* Each needs
|
|
1786
|
-
*
|
|
1787
|
-
*
|
|
1811
|
+
* Each needs a different note on the summary, and `T | null` does not show
|
|
1812
|
+
* which case happened, so every new reader has to choose again and some
|
|
1813
|
+
* choose wrong.
|
|
1788
1814
|
*
|
|
1789
1815
|
* The rule that turns a reading into a claim, a library default, or a gap
|
|
1790
|
-
*
|
|
1816
|
+
* is in the summary builder in this package and is not exported.
|
|
1791
1817
|
*/
|
|
1792
1818
|
/** Where in a file a value is written, as byte offsets into that file. */
|
|
1793
1819
|
interface SourceRange {
|
|
@@ -1830,9 +1856,9 @@ declare const absentReading: Reading<never>;
|
|
|
1830
1856
|
*/
|
|
1831
1857
|
declare function unreadableReading<T>(reason: string, range: SourceRange): Reading<T>;
|
|
1832
1858
|
/**
|
|
1833
|
-
* Several values could be right and the reader picked none.
|
|
1834
|
-
*
|
|
1835
|
-
*
|
|
1859
|
+
* Several values could be right and the reader picked none. The candidates
|
|
1860
|
+
* are kept through every later step, so code that can choose among them
|
|
1861
|
+
* still has them.
|
|
1836
1862
|
*
|
|
1837
1863
|
* The range is where somebody should look to see the ambiguity. An ambiguity
|
|
1838
1864
|
* often spans more than one place (two mounts of one router, in two files),
|
|
@@ -1843,8 +1869,7 @@ declare function ambiguousReading<T>(candidates: readonly T[], reason: string, r
|
|
|
1843
1869
|
/**
|
|
1844
1870
|
* A reading paired with what the library does when the source says nothing.
|
|
1845
1871
|
* Only a pack may supply that default, so the value a summary claims for an
|
|
1846
|
-
* unstated field
|
|
1847
|
-
* everything else the pack already declares.
|
|
1872
|
+
* unstated field always comes from a pack's declaration about the library.
|
|
1848
1873
|
*/
|
|
1849
1874
|
interface DefaultedReading<T> {
|
|
1850
1875
|
/** What the source said. */
|
|
@@ -1871,9 +1896,8 @@ declare function mapReading<T, U>(reading: Reading<T>, f: (value: T) => U): Read
|
|
|
1871
1896
|
*
|
|
1872
1897
|
* `f` runs on each of an ambiguous reading's candidates too, and the ones
|
|
1873
1898
|
* that do read come back as the candidates of an ambiguous reading with the
|
|
1874
|
-
* same reason.
|
|
1875
|
-
*
|
|
1876
|
-
* that reads further.
|
|
1899
|
+
* same reason. The alternatives reach the summary instead of being dropped
|
|
1900
|
+
* at the first step that reads further.
|
|
1877
1901
|
*/
|
|
1878
1902
|
declare function andThenReading<T, U>(reading: Reading<T>, f: (value: T, range: SourceRange) => Reading<U>): Reading<U>;
|
|
1879
1903
|
/**
|
|
@@ -1888,10 +1912,10 @@ interface ChosenReading<T> {
|
|
|
1888
1912
|
*/
|
|
1889
1913
|
reading: Reading<T>;
|
|
1890
1914
|
/**
|
|
1891
|
-
* The readings the choice passed over
|
|
1892
|
-
* reading
|
|
1893
|
-
*
|
|
1894
|
-
*
|
|
1915
|
+
* The unreadable or ambiguous readings the choice passed over. A later
|
|
1916
|
+
* reading that supplies the value does not settle an earlier one that
|
|
1917
|
+
* could not be read, so these still go to the builder and their reasons
|
|
1918
|
+
* reach the summary.
|
|
1895
1919
|
*/
|
|
1896
1920
|
passedOver: readonly Reading<T>[];
|
|
1897
1921
|
}
|
|
@@ -1909,32 +1933,29 @@ declare function firstWrittenReading<T>(readings: readonly Reading<T>[]): Chosen
|
|
|
1909
1933
|
* parameters that decide what each of the handler's parameters is, and
|
|
1910
1934
|
* that has to be settled before there is a summary field to fill in.
|
|
1911
1935
|
*
|
|
1912
|
-
* This applies no default and gives no reason, so most
|
|
1913
|
-
*
|
|
1914
|
-
*
|
|
1915
|
-
* review can see it.
|
|
1936
|
+
* This applies no default and gives no reason, so most summary fields must
|
|
1937
|
+
* not be written from it. Pass the reading to the builder instead, which
|
|
1938
|
+
* applies the one rule for readings in a place a reviewer can find.
|
|
1916
1939
|
*
|
|
1917
1940
|
* The identity fields of a boundary binding are the exception, and the path
|
|
1918
|
-
*
|
|
1919
|
-
*
|
|
1920
|
-
*
|
|
1921
|
-
* put there is the value this gives back. Hand the reading over as well and
|
|
1922
|
-
* the reason still becomes a gap.
|
|
1941
|
+
* is one of them. No pack declares a default for what a boundary is called,
|
|
1942
|
+
* so the builder would write the same value this returns. Pass the reading
|
|
1943
|
+
* to the builder as well, so its reason still becomes a gap.
|
|
1923
1944
|
*/
|
|
1924
1945
|
declare function valueToReadFurtherFrom<T>(reading: Reading<T>): T | null;
|
|
1925
1946
|
|
|
1926
1947
|
/**
|
|
1927
|
-
*
|
|
1928
|
-
*
|
|
1948
|
+
* Folds the code registered around a unit, such as middleware, into what
|
|
1949
|
+
* the unit does.
|
|
1929
1950
|
*
|
|
1930
1951
|
* A wrapper is a meta-function: it takes a unit and returns a unit. The
|
|
1931
1952
|
* call to its continuation comes through as a `delegate` transition, so
|
|
1932
1953
|
* a path that ends before that call is a response the caller gets
|
|
1933
1954
|
* instead of the unit's own, and a path that reaches it hands the
|
|
1934
|
-
* request on without responding. The responses
|
|
1935
|
-
* outcomes
|
|
1936
|
-
* outcomes already say what happens on them.
|
|
1937
|
-
*
|
|
1955
|
+
* request on without responding. The responses are added beside the
|
|
1956
|
+
* unit's own outcomes. The pass-throughs are dropped, because the unit's
|
|
1957
|
+
* outcomes already say what happens on them. This package's DESIGN.md
|
|
1958
|
+
* works through an example and lists what composition does not read.
|
|
1938
1959
|
*/
|
|
1939
1960
|
|
|
1940
1961
|
/**
|
|
@@ -1951,6 +1972,57 @@ interface ComposeOptions {
|
|
|
1951
1972
|
*/
|
|
1952
1973
|
declare function composeWrappers(summaries: readonly BehavioralSummary[], options?: ComposeOptions): BehavioralSummary[];
|
|
1953
1974
|
|
|
1975
|
+
/**
|
|
1976
|
+
* The modules a project lists in `suss.json`, as every adapter reads them.
|
|
1977
|
+
*
|
|
1978
|
+
* A module is a name, a root folder, and the files whose exports other
|
|
1979
|
+
* modules are meant to call. The CLI reads the list and hands it to the
|
|
1980
|
+
* adapter with absolute paths. Which file is public when the list does not
|
|
1981
|
+
* say is a fact about the language, so each adapter settles that first.
|
|
1982
|
+
* The rest is the same in all three adapters: which module a file belongs
|
|
1983
|
+
* to, the module stamped on each summary, and the part of the cache key
|
|
1984
|
+
* that makes an edit to the list run discovery again.
|
|
1985
|
+
*/
|
|
1986
|
+
|
|
1987
|
+
/** The recognition on every module export's binding, in each language. */
|
|
1988
|
+
declare const MODULE_SURFACE_RECOGNITION = "modules";
|
|
1989
|
+
interface DeclaredModule {
|
|
1990
|
+
readonly name: string;
|
|
1991
|
+
/** Absolute. Every file under it belongs to the module. */
|
|
1992
|
+
readonly root: string;
|
|
1993
|
+
/**
|
|
1994
|
+
* Absolute. The files whose exports are the module's public surface.
|
|
1995
|
+
* Left out when `suss.json` does not say, and then the adapter's
|
|
1996
|
+
* convention for its language decides.
|
|
1997
|
+
*/
|
|
1998
|
+
readonly public?: readonly string[];
|
|
1999
|
+
}
|
|
2000
|
+
/** A module whose public files are settled. An empty list means it has none. */
|
|
2001
|
+
interface SettledModule extends DeclaredModule {
|
|
2002
|
+
readonly public: readonly string[];
|
|
2003
|
+
}
|
|
2004
|
+
/**
|
|
2005
|
+
* Each module with its public files. A module `suss.json` gave files for
|
|
2006
|
+
* keeps them. Otherwise the language's candidates are tried, and only the
|
|
2007
|
+
* ones on disk are kept. A candidate is a path relative to the module's
|
|
2008
|
+
* root, with `{name}` standing for the module's name, as in `index.ts`
|
|
2009
|
+
* or `../{name}.rb`.
|
|
2010
|
+
*/
|
|
2011
|
+
declare function settleModules(modules: readonly DeclaredModule[] | undefined, candidates: readonly string[]): SettledModule[];
|
|
2012
|
+
/**
|
|
2013
|
+
* The module a file belongs to. A public file belongs to its module even
|
|
2014
|
+
* when it is outside the root, as a Ruby `lib/billing.rb` is next to
|
|
2015
|
+
* `lib/billing/`. Otherwise the deepest root that contains the file
|
|
2016
|
+
* wins, so a module nested inside another's folder keeps its own files.
|
|
2017
|
+
*/
|
|
2018
|
+
declare function moduleOfFile(modules: readonly SettledModule[], file: string): SettledModule | undefined;
|
|
2019
|
+
/**
|
|
2020
|
+
* Writes each summary's module onto its location. `root` is the directory
|
|
2021
|
+
* a shortened `location.file` is relative to, when the adapter has
|
|
2022
|
+
* already shortened it.
|
|
2023
|
+
*/
|
|
2024
|
+
declare function stampModules(summaries: readonly BehavioralSummary[], modules: readonly SettledModule[], root: string | undefined): void;
|
|
2025
|
+
|
|
1954
2026
|
/**
|
|
1955
2027
|
* Which branch an effect belongs to.
|
|
1956
2028
|
*
|
|
@@ -1961,8 +2033,8 @@ declare function composeWrappers(summaries: readonly BehavioralSummary[], option
|
|
|
1961
2033
|
* attributes effects to branches reads from here, so they all decide
|
|
1962
2034
|
* it the same way.
|
|
1963
2035
|
*
|
|
1964
|
-
* Neither test is enough alone
|
|
1965
|
-
*
|
|
2036
|
+
* Neither test is enough alone. This package's DESIGN.md shows the two
|
|
2037
|
+
* cases where one test on its own gets the branch wrong.
|
|
1966
2038
|
*/
|
|
1967
2039
|
|
|
1968
2040
|
/**
|
|
@@ -1982,7 +2054,90 @@ declare function guardsHoldOn(preconditions: readonly RawCondition[] | undefined
|
|
|
1982
2054
|
declare function runsBefore(effectLine: number, terminalEndLine: number): boolean;
|
|
1983
2055
|
|
|
1984
2056
|
/**
|
|
1985
|
-
*
|
|
2057
|
+
* Marks the summaries whose return becomes the process's exit code, as
|
|
2058
|
+
* `metadata.process.exitCodeFrom: "return"`, and clears the mark from
|
|
2059
|
+
* every other one.
|
|
2060
|
+
*
|
|
2061
|
+
* Every adapter works the functions out once per run and calls this over
|
|
2062
|
+
* every summary the run hands back, reused ones included. The chain runs
|
|
2063
|
+
* from the file that sets the code into files that never record that
|
|
2064
|
+
* file as a dependency, so a mark a cache kept could otherwise outlive an
|
|
2065
|
+
* edit to the entry file.
|
|
2066
|
+
*/
|
|
2067
|
+
|
|
2068
|
+
/**
|
|
2069
|
+
* `returnsTheCode` contains function keys, the absolute file and the
|
|
2070
|
+
* function's span as `declarationKey` writes them. A summary whose file
|
|
2071
|
+
* was shortened is resolved against `workspaceRoot` first.
|
|
2072
|
+
*/
|
|
2073
|
+
declare function markReturnsAsExitCode(summaries: readonly BehavioralSummary[], returnsTheCode: ReadonlySet<string>, workspaceRoot?: string): void;
|
|
2074
|
+
|
|
2075
|
+
/**
|
|
2076
|
+
* Splices a project helper's paths into the caller that handed it a
|
|
2077
|
+
* value, so a client caller that leaves its status test to a helper
|
|
2078
|
+
* still shows which statuses it handles.
|
|
2079
|
+
*
|
|
2080
|
+
* resp = requests.get(url)
|
|
2081
|
+
* return check_response(resp)
|
|
2082
|
+
*
|
|
2083
|
+
* Each adapter finds the call, reads the helper's paths with the
|
|
2084
|
+
* caller's terminals, and says which parameter got which value. Splitting
|
|
2085
|
+
* the caller's branch along those paths is the same in every language,
|
|
2086
|
+
* so it lives here.
|
|
2087
|
+
*/
|
|
2088
|
+
|
|
2089
|
+
/**
|
|
2090
|
+
* Past this many paths a helper is doing more than reading a response,
|
|
2091
|
+
* and multiplying every caller path by it would bury the caller's own.
|
|
2092
|
+
*/
|
|
2093
|
+
declare const MAX_HELPER_PATHS = 16;
|
|
2094
|
+
/**
|
|
2095
|
+
* The caller's branch split along each path of the helper called at
|
|
2096
|
+
* `at`. A throw or an exit in the helper ends the caller at the call,
|
|
2097
|
+
* and a path that returns goes on to the caller's own ending.
|
|
2098
|
+
*/
|
|
2099
|
+
declare function throughHelper(branch: RawBranch, at: {
|
|
2100
|
+
start: number;
|
|
2101
|
+
end: number;
|
|
2102
|
+
}, helperBranches: readonly RawBranch[]): RawBranch[];
|
|
2103
|
+
/**
|
|
2104
|
+
* The fields two readers of one response read between them, as the
|
|
2105
|
+
* records of field names a branch's `expectedInput` lists.
|
|
2106
|
+
*/
|
|
2107
|
+
declare function mergeReadShapes(a: TypeShape | null, b: TypeShape | null): TypeShape | null;
|
|
2108
|
+
/** One call in a caller's body that hands a helper the response, in source order. */
|
|
2109
|
+
interface HandOffSite {
|
|
2110
|
+
/** The helper's paths, in the caller's terms. */
|
|
2111
|
+
helper: readonly RawBranch[];
|
|
2112
|
+
preconditions?: readonly RawCondition[] | undefined;
|
|
2113
|
+
/** The line the statement holding the call starts on, which decides whether a branch reaches it. */
|
|
2114
|
+
line: number;
|
|
2115
|
+
/** The lines the call is written on. */
|
|
2116
|
+
at: {
|
|
2117
|
+
start: number;
|
|
2118
|
+
end: number;
|
|
2119
|
+
};
|
|
2120
|
+
/** A call in a `finally` runs on every path, even one that left before it. */
|
|
2121
|
+
alwaysRuns?: boolean;
|
|
2122
|
+
}
|
|
2123
|
+
/**
|
|
2124
|
+
* The branch split at each hand-off on it, in source order. A path that
|
|
2125
|
+
* ended in one helper goes no further, so the hand-offs after it are not
|
|
2126
|
+
* asked about on that path.
|
|
2127
|
+
*/
|
|
2128
|
+
declare function splitAtHandOffs(branch: RawBranch, sites: readonly HandOffSite[], from?: number): RawBranch[];
|
|
2129
|
+
/**
|
|
2130
|
+
* A helper's paths with each test on a parameter it was handed turned
|
|
2131
|
+
* into a test on the caller's variable, keyed parameter to variable.
|
|
2132
|
+
* Null when no path tests what it was handed, or when there are too many
|
|
2133
|
+
* paths to splice. This is for an adapter that writes a variable's value
|
|
2134
|
+
* as a dependency on the variable's name, the way the caller's own tests
|
|
2135
|
+
* on it are written.
|
|
2136
|
+
*/
|
|
2137
|
+
declare function helperPathsOnVariables(helperBranches: readonly RawBranch[], passed: ReadonlyMap<string, string>): RawBranch[] | null;
|
|
2138
|
+
|
|
2139
|
+
/**
|
|
2140
|
+
* Writes `metadata.moduleImports` on a set of summaries.
|
|
1986
2141
|
*
|
|
1987
2142
|
* Every adapter records the project files a summary's own file depends
|
|
1988
2143
|
* on, and a checker rebuilds the module graph from that field to find
|
|
@@ -1999,15 +2154,14 @@ declare function runsBefore(effectLine: number, terminalEndLine: number): boolea
|
|
|
1999
2154
|
declare function stampModuleImports(summaries: BehavioralSummary[], importsOf: (file: string) => Iterable<string> | undefined): void;
|
|
2000
2155
|
|
|
2001
2156
|
/**
|
|
2002
|
-
*
|
|
2157
|
+
* Builds the raw structure for what a module does when it loads.
|
|
2003
2158
|
*
|
|
2004
2159
|
* A module's top-level statements run once, when it is first imported,
|
|
2005
|
-
* and a service
|
|
2006
|
-
*
|
|
2007
|
-
*
|
|
2008
|
-
*
|
|
2009
|
-
*
|
|
2010
|
-
* closure can reach the functions behind them.
|
|
2160
|
+
* and a service often reads its configuration there. Walking unit bodies
|
|
2161
|
+
* never sees that read, so the read gets a unit of its own: one per file,
|
|
2162
|
+
* named after the file, with no boundary. Attributing it to each handler
|
|
2163
|
+
* would report one read as several. The calls those statements make go on
|
|
2164
|
+
* the same unit, so the closure can reach the functions behind them.
|
|
2011
2165
|
*
|
|
2012
2166
|
* The one default branch has a `void` terminal, because module
|
|
2013
2167
|
* initialization returns to nobody. Every adapter builds it the same way.
|
|
@@ -2028,12 +2182,9 @@ interface ModuleInitOptions {
|
|
|
2028
2182
|
declare function moduleInitStructure(options: ModuleInitOptions): RawCodeStructure;
|
|
2029
2183
|
|
|
2030
2184
|
/**
|
|
2031
|
-
*
|
|
2032
|
-
*
|
|
2033
|
-
*
|
|
2034
|
-
* object the adapter interprets, and most differences between frameworks are
|
|
2035
|
-
* best expressed that way. A few patterns, though, repeat word for word
|
|
2036
|
-
* across packs, and this module collects those so they are written once.
|
|
2185
|
+
* Builders for the pack entries that several packs would otherwise copy
|
|
2186
|
+
* word for word. A pack is still a data object the adapter interprets;
|
|
2187
|
+
* these functions only write that data out.
|
|
2037
2188
|
*/
|
|
2038
2189
|
|
|
2039
2190
|
/**
|
|
@@ -2042,15 +2193,14 @@ declare function moduleInitStructure(options: ModuleInitOptions): RawCodeStructu
|
|
|
2042
2193
|
* like.
|
|
2043
2194
|
*
|
|
2044
2195
|
* Each `importNames` entry produces one DiscoveryPattern, because a library
|
|
2045
|
-
* usually
|
|
2046
|
-
*
|
|
2047
|
-
* `
|
|
2048
|
-
*
|
|
2049
|
-
* the same for every HTTP server framework we support.
|
|
2196
|
+
* usually exports more than one function that makes the routable instance
|
|
2197
|
+
* (Express has `express()` and `Router()`, Fastify has `fastify()` and
|
|
2198
|
+
* `Fastify`). The binding extraction, method from the registration and
|
|
2199
|
+
* path from position 0, is the same for every supported HTTP framework.
|
|
2050
2200
|
*
|
|
2051
|
-
* Callers
|
|
2052
|
-
*
|
|
2053
|
-
*
|
|
2201
|
+
* Callers pass the `methods` list themselves, because frameworks accept
|
|
2202
|
+
* different verbs: Fastify has `.head` and `.options`, and Express does
|
|
2203
|
+
* not by default.
|
|
2054
2204
|
*
|
|
2055
2205
|
* @example
|
|
2056
2206
|
* discovery: httpRouteDiscovery({
|
|
@@ -2077,7 +2227,7 @@ declare function httpRouteDiscovery(opts: {
|
|
|
2077
2227
|
* handlers: middleware, error handlers, validation hooks.
|
|
2078
2228
|
*
|
|
2079
2229
|
* A wrapper becomes a unit of its own, summarized like any other, so
|
|
2080
|
-
* these entries
|
|
2230
|
+
* these entries have no `bindingExtraction` and no registration chain.
|
|
2081
2231
|
* Their `match` is there for the import and the imported name, which is
|
|
2082
2232
|
* how wrapper discovery works out which variables in a file are the
|
|
2083
2233
|
* routable. One entry per (import name, wrapper shape) pair, since a
|
|
@@ -2095,7 +2245,7 @@ declare function wrapperDiscovery(opts: {
|
|
|
2095
2245
|
* placeholders for the call's positional arguments.
|
|
2096
2246
|
*/
|
|
2097
2247
|
interface RegistrationHelper {
|
|
2098
|
-
/**
|
|
2248
|
+
/** The helper's name as the project's code writes it. */
|
|
2099
2249
|
helperName: string;
|
|
2100
2250
|
/** The file declaring it, so a same-named function elsewhere is left alone. */
|
|
2101
2251
|
importModule?: string;
|
|
@@ -2122,9 +2272,8 @@ interface RegistrationHelper {
|
|
|
2122
2272
|
*/
|
|
2123
2273
|
declare function registrationHelperDiscovery(helpers: readonly RegistrationHelper[], kind?: string): DiscoveryPattern[];
|
|
2124
2274
|
/**
|
|
2125
|
-
*
|
|
2126
|
-
*
|
|
2127
|
-
* code rather than something the project restates in config.
|
|
2275
|
+
* Asks for the project's own route helpers to be read, so what each one
|
|
2276
|
+
* registers comes from the code instead of being restated in config.
|
|
2128
2277
|
*/
|
|
2129
2278
|
declare function routeHelperIndex(opts: {
|
|
2130
2279
|
importModule: string;
|
|
@@ -2136,8 +2285,8 @@ declare function routeHelperIndex(opts: {
|
|
|
2136
2285
|
/**
|
|
2137
2286
|
* The payload behind a `JSON.stringify(...)` call, or the argument
|
|
2138
2287
|
* unchanged when it is anything else. A producer serializes its message
|
|
2139
|
-
* before sending it,
|
|
2140
|
-
*
|
|
2288
|
+
* before sending it, so the value compared across the boundary is the
|
|
2289
|
+
* object that went into the string.
|
|
2141
2290
|
*/
|
|
2142
2291
|
declare function unwrapJsonStringify(body: EffectArg | null): EffectArg | null;
|
|
2143
2292
|
|
|
@@ -2145,13 +2294,12 @@ declare function unwrapJsonStringify(body: EffectArg | null): EffectArg | null;
|
|
|
2145
2294
|
* Option declarations more than one pack takes.
|
|
2146
2295
|
*
|
|
2147
2296
|
* A pack exports `optionsSchema` beside its factory, and the CLI parses
|
|
2148
|
-
* a `-f pack=config.json` file against it before the factory runs, so
|
|
2149
|
-
* key
|
|
2297
|
+
* a `-f pack=config.json` file against it before the factory runs, so an
|
|
2298
|
+
* undeclared key is refused by name instead of being silently ignored.
|
|
2150
2299
|
*
|
|
2151
|
-
* Four packs accept `storageSystem` and three accept `scope
|
|
2152
|
-
*
|
|
2153
|
-
*
|
|
2154
|
-
* `"postgres"` and the union allowed only `"postgresql"`.
|
|
2300
|
+
* Four packs accept `storageSystem` and three accept `scope`, so each
|
|
2301
|
+
* option is declared once here. With a copy per pack, one pack can end up
|
|
2302
|
+
* accepting a value the others reject.
|
|
2155
2303
|
*/
|
|
2156
2304
|
|
|
2157
2305
|
/**
|
|
@@ -2175,9 +2323,9 @@ declare const scopeOption: z.ZodString;
|
|
|
2175
2323
|
* A call the project has declared to be its own dispatcher, which both
|
|
2176
2324
|
* message-bus packs take under `producers`.
|
|
2177
2325
|
*
|
|
2178
|
-
* `receiver` is
|
|
2179
|
-
*
|
|
2180
|
-
*
|
|
2326
|
+
* `receiver` is a type name because a service may keep its dispatcher in
|
|
2327
|
+
* a field, a closure or a constructor parameter, and the type is the same
|
|
2328
|
+
* in all three.
|
|
2181
2329
|
*/
|
|
2182
2330
|
declare const configuredCallOption: z.ZodObject<{
|
|
2183
2331
|
module: z.ZodString;
|
|
@@ -2197,14 +2345,14 @@ declare const configuredCallOption: z.ZodObject<{
|
|
|
2197
2345
|
* Nothing here touches a language-specific AST node. A language adapter
|
|
2198
2346
|
* lowers its own tree into `StructuredStatement` and hands that over.
|
|
2199
2347
|
*
|
|
2200
|
-
*
|
|
2201
|
-
* `
|
|
2348
|
+
* On a construct it does not model, or on too many paths, the engine throws
|
|
2349
|
+
* `UnmodeledFlow` or `PathBudgetExceeded`, and the caller falls back to
|
|
2202
2350
|
* enclosure conditions plus an opaque conjunct instead of guessing.
|
|
2203
2351
|
*/
|
|
2204
2352
|
|
|
2205
2353
|
/** The cap on how many paths to enumerate. Past it the caller falls back to degraded conditions. */
|
|
2206
2354
|
declare const MAX_PATHS = 256;
|
|
2207
|
-
/** A construct the
|
|
2355
|
+
/** A construct the engine does not model, such as a stray break in a switch clause or a finally that exits. Callers catch this and degrade. */
|
|
2208
2356
|
declare class UnmodeledFlow extends Error {
|
|
2209
2357
|
}
|
|
2210
2358
|
/** The path budget was exceeded. Callers catch this and degrade. */
|
|
@@ -2215,14 +2363,24 @@ interface StructuredPathConditionsInput<Cond, Terminal> {
|
|
|
2215
2363
|
statements: StatementBlock<Cond>;
|
|
2216
2364
|
/**
|
|
2217
2365
|
* Every StructuredStatement reachable from `statements`, mapped to the
|
|
2218
|
-
*
|
|
2219
|
-
*
|
|
2220
|
-
*
|
|
2221
|
-
*
|
|
2222
|
-
*
|
|
2366
|
+
* caller's terminals found directly at that node: at its own position
|
|
2367
|
+
* (a return, throw, or opaque leaf) or, for a branching construct, in
|
|
2368
|
+
* its header or test expression. A lowering builds this at the same
|
|
2369
|
+
* time as the tree, so the engine never walks a raw source AST to find
|
|
2370
|
+
* where a terminal is.
|
|
2223
2371
|
*/
|
|
2224
2372
|
terminalsByStmt: ReadonlyMap<StructuredStatement<Cond>, readonly Terminal[]>;
|
|
2373
|
+
/**
|
|
2374
|
+
* The tests whose arms go on as separate paths after they rejoin, so
|
|
2375
|
+
* a terminal later in the body is reached once under each arm. A
|
|
2376
|
+
* client's caller keeps the arms of a test on the response status,
|
|
2377
|
+
* since which statuses it handles is the point of reading it, even
|
|
2378
|
+
* when neither arm returns. Every other test is merged away as usual.
|
|
2379
|
+
*/
|
|
2380
|
+
keepsArms?: KeepsArms<Cond>;
|
|
2225
2381
|
}
|
|
2382
|
+
/** Whether the arms of the test written as this condition go on as separate paths. */
|
|
2383
|
+
type KeepsArms<Cond> = (condition: Cond) => boolean;
|
|
2226
2384
|
interface StructuredPathConditionsResult<Cond, Terminal> {
|
|
2227
2385
|
/** The paths to each terminal, keyed by the caller's own terminal handle. */
|
|
2228
2386
|
byTerminal: Map<Terminal, ConditionInfo<Cond>[][]>;
|
|
@@ -2239,11 +2397,10 @@ interface StructuredPathConditionsResult<Cond, Terminal> {
|
|
|
2239
2397
|
*/
|
|
2240
2398
|
declare function enumerateStructuredPaths<Cond, Terminal>(input: StructuredPathConditionsInput<Cond, Terminal>): StructuredPathConditionsResult<Cond, Terminal>;
|
|
2241
2399
|
/**
|
|
2242
|
-
* Enumerate, and when the engine gives up
|
|
2243
|
-
* terminal comes back reachable under one
|
|
2244
|
-
*
|
|
2245
|
-
*
|
|
2246
|
-
* enclose it, should.
|
|
2400
|
+
* Enumerate, and when the engine gives up, report why instead of throwing.
|
|
2401
|
+
* Each terminal comes back reachable under one opaque marker condition, so
|
|
2402
|
+
* no terminal is lost. A caller that can walk a terminal's own ancestors
|
|
2403
|
+
* for the conditions that enclose it should use those instead.
|
|
2247
2404
|
*/
|
|
2248
2405
|
declare function enumerateOrDegrade<Cond, Terminal>(input: StructuredPathConditionsInput<Cond, Terminal>, terminals: Iterable<Terminal>): StructuredPathConditionsResult<Cond, Terminal> & {
|
|
2249
2406
|
/** Why the engine gave up, or null when it read the whole body. */
|
|
@@ -2256,12 +2413,10 @@ declare function enumerateOrDegrade<Cond, Terminal>(input: StructuredPathConditi
|
|
|
2256
2413
|
* for a path without it.
|
|
2257
2414
|
*
|
|
2258
2415
|
* `readPredicate` turns the language's own expression handle into a
|
|
2259
|
-
* predicate. Without
|
|
2260
|
-
* caller that has no reader gets.
|
|
2416
|
+
* predicate. Without it every condition comes back with `structured: null`.
|
|
2261
2417
|
*/
|
|
2262
2418
|
declare function sharedGatingConditions<Cond>(paths: readonly (readonly ConditionInfo<Cond>[])[] | undefined, readPredicate?: (expression: Cond) => Predicate): RawCondition[];
|
|
2263
2419
|
|
|
2264
|
-
/** Anything with a stable id, which is what these key on. */
|
|
2265
2420
|
interface Identified {
|
|
2266
2421
|
readonly id: number;
|
|
2267
2422
|
}
|
|
@@ -2271,7 +2426,7 @@ declare class IdSet<T extends Identified> implements Iterable<T> {
|
|
|
2271
2426
|
constructor(nodes?: Iterable<T>);
|
|
2272
2427
|
add(node: T): this;
|
|
2273
2428
|
has(node: T): boolean;
|
|
2274
|
-
/** The
|
|
2429
|
+
/** The wrapper that was added, which may be a different object from `node`. */
|
|
2275
2430
|
get(node: T): T | undefined;
|
|
2276
2431
|
get size(): number;
|
|
2277
2432
|
[Symbol.iterator](): Iterator<T>;
|
|
@@ -2287,23 +2442,58 @@ declare class IdMap<T extends Identified, V> implements Iterable<[T, V]> {
|
|
|
2287
2442
|
}
|
|
2288
2443
|
|
|
2289
2444
|
/**
|
|
2290
|
-
*
|
|
2291
|
-
*
|
|
2445
|
+
* The enclosing definition of a tree-sitter node, kept for as long as
|
|
2446
|
+
* its parse is.
|
|
2447
|
+
*
|
|
2448
|
+
* A fact key includes the function a node is written in, so an adapter
|
|
2449
|
+
* looks it up for every read it keys, and each step up the tree is a call
|
|
2450
|
+
* into tree-sitter's wasm module that builds a fresh wrapper. A parse tree
|
|
2451
|
+
* does not change once it is built, so each result is kept in a WeakMap
|
|
2452
|
+
* keyed on the tree. The results go when the tree does, and a parse made
|
|
2453
|
+
* in a later run starts with nothing kept.
|
|
2292
2454
|
*
|
|
2293
|
-
*
|
|
2294
|
-
*
|
|
2295
|
-
* does not list the containers it descends into. It walks every named
|
|
2296
|
-
* child and says only which nodes keep their own body, because that set
|
|
2297
|
-
* is short and a grammar's own vocabulary already names it.
|
|
2455
|
+
* Only this read is kept. Keeping each node's children and fields too
|
|
2456
|
+
* cost more memory than it saved time.
|
|
2298
2457
|
*/
|
|
2299
|
-
/**
|
|
2300
|
-
interface
|
|
2301
|
-
readonly
|
|
2458
|
+
/** What the reader needs from a parse tree node. */
|
|
2459
|
+
interface ParsedNode<T> {
|
|
2460
|
+
readonly id: number;
|
|
2461
|
+
readonly type: string;
|
|
2462
|
+
readonly tree: object;
|
|
2463
|
+
readonly parent: T | null;
|
|
2464
|
+
}
|
|
2465
|
+
/** The nearest ancestor of each node whose type is one of `types`, read once per parse. */
|
|
2466
|
+
declare class EnclosingNodes<T extends ParsedNode<T>> {
|
|
2467
|
+
private readonly types;
|
|
2468
|
+
private readonly byTree;
|
|
2469
|
+
constructor(types: ReadonlySet<string>);
|
|
2470
|
+
/**
|
|
2471
|
+
* The nearest ancestor of one of the types, or null when there is none.
|
|
2472
|
+
* Every node passed on the way up has the same result, so each one is
|
|
2473
|
+
* kept, and a later read from a sibling stops one step up.
|
|
2474
|
+
*/
|
|
2475
|
+
of(node: T): T | null;
|
|
2476
|
+
private keptFor;
|
|
2302
2477
|
}
|
|
2478
|
+
|
|
2479
|
+
/**
|
|
2480
|
+
* The recursion the adapters use to find a declaration wherever the
|
|
2481
|
+
* language allows one to be written.
|
|
2482
|
+
*
|
|
2483
|
+
* A declaration can go anywhere a statement can, and every language has
|
|
2484
|
+
* more places for a statement than anyone remembers to list. So an adapter
|
|
2485
|
+
* does not list the containers to descend into. The walk visits every
|
|
2486
|
+
* named child, and the adapter only lists the nodes whose body belongs to
|
|
2487
|
+
* what they declare, because that list is short.
|
|
2488
|
+
*
|
|
2489
|
+
* The adapter also says how to read a node's children. Its parser's own
|
|
2490
|
+
* getters keep the array they build on the node, so each adapter reads
|
|
2491
|
+
* children through one accessor of its own that leaves nothing behind.
|
|
2492
|
+
*/
|
|
2303
2493
|
/**
|
|
2304
2494
|
* Returned by `into` for a node whose children the walk should leave
|
|
2305
|
-
* unread, such as one whose body belongs to what it declares.
|
|
2306
|
-
* so it cannot collide with
|
|
2495
|
+
* unread, such as one whose body belongs to what it declares. It is a
|
|
2496
|
+
* symbol so it cannot collide with any value a caller passes down.
|
|
2307
2497
|
*/
|
|
2308
2498
|
declare const SKIP_CHILDREN: unique symbol;
|
|
2309
2499
|
/** What a walk does at each node it reaches. */
|
|
@@ -2313,12 +2503,14 @@ interface NodeVisitor<T, C> {
|
|
|
2313
2503
|
/** What to carry into this node's children, or `SKIP_CHILDREN` to leave them unread. */
|
|
2314
2504
|
into(node: T, carried: C): C | typeof SKIP_CHILDREN;
|
|
2315
2505
|
}
|
|
2506
|
+
/** A node's named children in source order, read by the adapter's own accessor. */
|
|
2507
|
+
type ChildrenOf<T> = (node: T) => readonly T[];
|
|
2316
2508
|
/**
|
|
2317
2509
|
* Every named node under `root`, depth first and in source order, with a
|
|
2318
2510
|
* value the visitor updates as the walk descends. `root` itself is not
|
|
2319
2511
|
* visited, because a caller starts from the body it is reading.
|
|
2320
2512
|
*/
|
|
2321
|
-
declare function walkDescendants<T
|
|
2513
|
+
declare function walkDescendants<T, C>(root: T, carried: C, childrenOf: ChildrenOf<T>, visitor: NodeVisitor<T, C>): void;
|
|
2322
2514
|
|
|
2323
2515
|
/**
|
|
2324
2516
|
* The project root when nothing declares one.
|
|
@@ -2330,6 +2522,69 @@ declare function walkDescendants<T extends WalkableNode<T>, C>(root: T, carried:
|
|
|
2330
2522
|
/** The deepest directory containing every file, or undefined when they share no absolute root. */
|
|
2331
2523
|
declare function commonDirectoryOf(files: ReadonlyArray<string>): string | undefined;
|
|
2332
2524
|
|
|
2525
|
+
/**
|
|
2526
|
+
* What a client call does with a redirect once the adapter has read the
|
|
2527
|
+
* value the call gives the pack's redirect option. Each adapter reads
|
|
2528
|
+
* the value in its own language, and all of them decide the same way.
|
|
2529
|
+
*/
|
|
2530
|
+
|
|
2531
|
+
/** `"response"` when the value is one that hands the 3xx back, and `"followed"` otherwise. */
|
|
2532
|
+
declare function redirectDeliveryWhenSet(option: RedirectOption, value: string | number | boolean): RedirectDelivery;
|
|
2533
|
+
|
|
2534
|
+
/**
|
|
2535
|
+
* Which files a test pack reads. `suss extract --intent` hands a test
|
|
2536
|
+
* pack the files the PRDs list under `coveredBy`, written the way the
|
|
2537
|
+
* author wrote them, usually from the repository root. An adapter walks
|
|
2538
|
+
* absolute paths, so an entry matches a file on whole path segments from
|
|
2539
|
+
* the end: `tests/test_orders.py` matches `/repo/api/tests/test_orders.py`
|
|
2540
|
+
* and not `/repo/api/tests/other_test_orders.py`. Every adapter's test
|
|
2541
|
+
* discovery goes through this, so the three languages agree on it.
|
|
2542
|
+
*/
|
|
2543
|
+
/** Whether the file is on the list. Every file is when there is no list. */
|
|
2544
|
+
declare function isListedTestFile(file: string, listed: readonly string[] | undefined): boolean;
|
|
2545
|
+
/**
|
|
2546
|
+
* Whether a file's base name matches one of the runner's patterns, where
|
|
2547
|
+
* `*` matches any run of characters: `test_*.py` or `*_spec.rb`.
|
|
2548
|
+
*/
|
|
2549
|
+
declare function matchesTestFileName(file: string, patterns: readonly string[]): boolean;
|
|
2550
|
+
|
|
2551
|
+
/**
|
|
2552
|
+
* Turns the places a value's walk ended into the value references a
|
|
2553
|
+
* transition records, the same way for every adapter.
|
|
2554
|
+
*
|
|
2555
|
+
* The walk itself is in `@suss/resolution`. What an input is depends on
|
|
2556
|
+
* the language and the framework, and so does reading a literal or
|
|
2557
|
+
* quoting the source, so the adapter says those three things. The order
|
|
2558
|
+
* they are tried in, and what a place that is none of them becomes, is
|
|
2559
|
+
* decided here.
|
|
2560
|
+
*/
|
|
2561
|
+
|
|
2562
|
+
/** One place a walk ended, as much of it as this needs. */
|
|
2563
|
+
interface WalkEnd {
|
|
2564
|
+
/** The key of the member the walk ended at. */
|
|
2565
|
+
readonly key: string;
|
|
2566
|
+
/** The properties read off it on the way to the value, outermost first. */
|
|
2567
|
+
readonly path: readonly string[];
|
|
2568
|
+
/** A read at a key the source computes on the way, or null for none. */
|
|
2569
|
+
readonly computedAt: string | null;
|
|
2570
|
+
/** The language's own conversions on the way to the value, outermost first. */
|
|
2571
|
+
readonly conversions: readonly string[];
|
|
2572
|
+
readonly end: {
|
|
2573
|
+
readonly is: string;
|
|
2574
|
+
};
|
|
2575
|
+
}
|
|
2576
|
+
/** What only the adapter can say about a place a walk ended. */
|
|
2577
|
+
interface SourceSpelling<L extends WalkEnd> {
|
|
2578
|
+
/** The input the place is, or null when it is not one. */
|
|
2579
|
+
inputOf(leaf: L): ValueRef | null;
|
|
2580
|
+
/** The literal the written value at a key is, or undefined for anything else. */
|
|
2581
|
+
literalAt(key: string): string | number | boolean | null | undefined;
|
|
2582
|
+
/** The source written at a key, or null when the key is not a node. */
|
|
2583
|
+
textAt(key: string): string | null;
|
|
2584
|
+
}
|
|
2585
|
+
/** Every place a value's walk ended, as distinct value references. */
|
|
2586
|
+
declare function sourceRefsOf<L extends WalkEnd>(leaves: readonly L[], spelling: SourceSpelling<L>): ValueRef[];
|
|
2587
|
+
|
|
2333
2588
|
/**
|
|
2334
2589
|
* The small surface every language adapter implements, whatever that
|
|
2335
2590
|
* language's own tooling looks like underneath.
|
|
@@ -2342,9 +2597,8 @@ declare function commonDirectoryOf(files: ReadonlyArray<string>): string | undef
|
|
|
2342
2597
|
|
|
2343
2598
|
interface LanguageAdapter {
|
|
2344
2599
|
/**
|
|
2345
|
-
*
|
|
2346
|
-
*
|
|
2347
|
-
* discovery without bottlenecking on synchronous reads.
|
|
2600
|
+
* Summaries for the listed files. It is async so an implementation can
|
|
2601
|
+
* read files concurrently during discovery.
|
|
2348
2602
|
*/
|
|
2349
2603
|
extractFromFiles(filePaths: string[]): Promise<BehavioralSummary[]>;
|
|
2350
2604
|
/** Extract summaries from every source file the adapter's project knows about. */
|
|
@@ -2352,23 +2606,22 @@ interface LanguageAdapter {
|
|
|
2352
2606
|
}
|
|
2353
2607
|
|
|
2354
2608
|
/**
|
|
2355
|
-
*
|
|
2609
|
+
* The language-neutral half of an adapter's cache key.
|
|
2356
2610
|
*
|
|
2357
|
-
*
|
|
2611
|
+
* Each adapter calls `createAdapterStamp` once, with its own
|
|
2358
2612
|
* `import.meta.url` and its hand-bumped version, and keeps the result for
|
|
2359
|
-
* the life of the process. The stamp hashes the adapter's
|
|
2360
|
-
*
|
|
2361
|
-
* `@suss/
|
|
2362
|
-
*
|
|
2363
|
-
*
|
|
2364
|
-
*
|
|
2365
|
-
* to cache. The extraction cache's design is in this package's README.
|
|
2613
|
+
* the life of the process. The stamp hashes the adapter's dist file and
|
|
2614
|
+
* every analysis package shipped with it (this package, `@suss/resolution`,
|
|
2615
|
+
* `@suss/datalog`, `@suss/behavioral-ir`). A release that changes any of
|
|
2616
|
+
* them invalidates an older cache, and so does a local rebuild, with no
|
|
2617
|
+
* version bump. Running from source leaves no dist file to hash, so that
|
|
2618
|
+
* mode turns the cache off. This package's DESIGN.md describes the cache.
|
|
2366
2619
|
*/
|
|
2620
|
+
|
|
2367
2621
|
/**
|
|
2368
2622
|
* Whether this process can see the adapter's own code. `bundle` includes
|
|
2369
|
-
* a hash that changes whenever the code does. `source` means
|
|
2370
|
-
*
|
|
2371
|
-
* about the code that will produce the results.
|
|
2623
|
+
* a hash that changes whenever the code does. `source` means no bundle was
|
|
2624
|
+
* found, so a cache key built from this stamp cannot tell two builds apart.
|
|
2372
2625
|
*/
|
|
2373
2626
|
type AdapterCodeStamp = {
|
|
2374
2627
|
kind: "bundle";
|
|
@@ -2376,24 +2629,22 @@ type AdapterCodeStamp = {
|
|
|
2376
2629
|
} | {
|
|
2377
2630
|
kind: "source";
|
|
2378
2631
|
};
|
|
2379
|
-
/** What `createAdapterStamp` hands back to an adapter's own version.ts. */
|
|
2380
2632
|
interface AdapterStamp {
|
|
2381
2633
|
/** The stamp for the running adapter, computed once per process. */
|
|
2382
2634
|
codeStamp(): AdapterCodeStamp;
|
|
2383
2635
|
/**
|
|
2384
|
-
*
|
|
2385
|
-
*
|
|
2386
|
-
*
|
|
2387
|
-
* loaded adapter dist file changes (dev-mode rebuild auto-invalidation).
|
|
2636
|
+
* A cache key for this adapter and its packs. It is the same across
|
|
2637
|
+
* processes for the same inputs, and changes when a pack's version, the
|
|
2638
|
+
* adapter's version, or the adapter's dist file changes.
|
|
2388
2639
|
*/
|
|
2389
2640
|
packsDigest(packVersions: ReadonlyArray<{
|
|
2390
2641
|
name: string;
|
|
2391
2642
|
version?: string;
|
|
2392
2643
|
}>): string;
|
|
2393
2644
|
/**
|
|
2394
|
-
* `cacheDir
|
|
2395
|
-
*
|
|
2396
|
-
* null
|
|
2645
|
+
* Returns `cacheDir`, or null when this process loaded the adapter from
|
|
2646
|
+
* source, since then one build cannot be told from another. The first
|
|
2647
|
+
* null in a process also prints the reason to stderr.
|
|
2397
2648
|
*/
|
|
2398
2649
|
declineWhenRunFromSource(cacheDir: string | null): string | null;
|
|
2399
2650
|
}
|
|
@@ -2410,7 +2661,7 @@ declare function createAdapterStamp(config: {
|
|
|
2410
2661
|
/**
|
|
2411
2662
|
* The hash for a bundle directory: the bundle itself plus every analysis
|
|
2412
2663
|
* package that can be located. Empty when the directory has no bundle in
|
|
2413
|
-
* it,
|
|
2664
|
+
* it, as happens when running from source.
|
|
2414
2665
|
*/
|
|
2415
2666
|
declare function computeDistHashFrom(dir: string): string;
|
|
2416
2667
|
/**
|
|
@@ -2429,19 +2680,42 @@ declare function computeContentHash(paths: readonly string[]): string;
|
|
|
2429
2680
|
* content go in, so a file that moves counts as a change even when
|
|
2430
2681
|
* every byte in it stayed the same.
|
|
2431
2682
|
*
|
|
2432
|
-
* A file that cannot be read
|
|
2433
|
-
*
|
|
2434
|
-
*
|
|
2435
|
-
* being gone is a fact about the project the next run should notice,
|
|
2436
|
-
* not a reason to stop telling runs apart.
|
|
2683
|
+
* A file that cannot be read is hashed as absent, where
|
|
2684
|
+
* `computeContentHash` would return an empty stamp. These files belong
|
|
2685
|
+
* to the project, so a missing one is a change the next run should see.
|
|
2437
2686
|
*/
|
|
2438
2687
|
declare function projectFileStamp(paths: readonly string[]): string;
|
|
2688
|
+
/**
|
|
2689
|
+
* The run options that change what an extraction writes. An adapter passes
|
|
2690
|
+
* every one it takes, and leaves out the ones it does not have.
|
|
2691
|
+
*/
|
|
2692
|
+
interface ExtractionConfig {
|
|
2693
|
+
gapHandling?: "strict" | "permissive" | "silent" | undefined;
|
|
2694
|
+
/** Whether a summary is written for each function a unit reaches. */
|
|
2695
|
+
includeReachable?: boolean | undefined;
|
|
2696
|
+
/** The directory a stored summary's `location.file` is relative to. */
|
|
2697
|
+
workspaceRoot?: string | undefined;
|
|
2698
|
+
/** The directory a stored summary's id measures its file from. */
|
|
2699
|
+
projectRoot?: string | undefined;
|
|
2700
|
+
/** The directories an absolute import was resolved against. */
|
|
2701
|
+
importRoots?: readonly string[] | undefined;
|
|
2702
|
+
/** The modules the project lists, which decide which units discovery finds. */
|
|
2703
|
+
modules?: readonly SettledModule[] | undefined;
|
|
2704
|
+
/** The directory the run walks when it walks only part of its project. */
|
|
2705
|
+
walkedDirectory?: string | undefined;
|
|
2706
|
+
}
|
|
2707
|
+
/**
|
|
2708
|
+
* The run options as one part of the cache key, so a run never reads an
|
|
2709
|
+
* entry that a run with other options wrote. Every adapter builds this part
|
|
2710
|
+
* here, which keeps the three keys from drifting apart.
|
|
2711
|
+
*/
|
|
2712
|
+
declare function extractionConfigStamp(config: ExtractionConfig): string;
|
|
2439
2713
|
/**
|
|
2440
2714
|
* The digest a run looks its cache entry up under. A pack may read
|
|
2441
2715
|
* project files that are not among the ones a run walks, a SAM template
|
|
2442
2716
|
* that decides which handlers exist for instance, so those belong in
|
|
2443
2717
|
* the key next to the pack's own config. Which files they are depends
|
|
2444
|
-
* on the files this run walks, so the digest is
|
|
2718
|
+
* on the files this run walks, so the digest is computed per run rather
|
|
2445
2719
|
* than once per adapter.
|
|
2446
2720
|
*/
|
|
2447
2721
|
declare function runDigest(packsDigest: string, packs: ReadonlyArray<{
|
|
@@ -2451,36 +2725,33 @@ declare function runDigest(packsDigest: string, packs: ReadonlyArray<{
|
|
|
2451
2725
|
/**
|
|
2452
2726
|
* The on-disk extraction cache, shared by every language adapter.
|
|
2453
2727
|
*
|
|
2454
|
-
* A run reuses the previous
|
|
2455
|
-
*
|
|
2456
|
-
*
|
|
2457
|
-
*
|
|
2458
|
-
*
|
|
2459
|
-
*
|
|
2460
|
-
*
|
|
2461
|
-
*
|
|
2462
|
-
*
|
|
2463
|
-
* full design is in this package's README.
|
|
2728
|
+
* A run reuses the previous run's summaries whole when nothing changed,
|
|
2729
|
+
* and per file when some files did. The entry directory's name is a hash
|
|
2730
|
+
* of the schema version, the adapter and packs digest, and the config
|
|
2731
|
+
* path, so two builds that disagree on any of them never read each
|
|
2732
|
+
* other's entry. The manifest inside records a stamp and content hash per
|
|
2733
|
+
* file, the files each summary belongs to, and for each of those files the
|
|
2734
|
+
* other files its walk read. An adapter can store its own data on a file's
|
|
2735
|
+
* record through `meta`, which the cache never reads. The package's
|
|
2736
|
+
* design notes describe the cache in full.
|
|
2464
2737
|
*/
|
|
2465
2738
|
|
|
2466
2739
|
/**
|
|
2467
|
-
* How many
|
|
2468
|
-
*
|
|
2469
|
-
*
|
|
2470
|
-
* twice one manifest.
|
|
2740
|
+
* How many entries a cache directory keeps. Two lets a pair of builds
|
|
2741
|
+
* alternate, as on a branch switch or an adapter rebuild and revert,
|
|
2742
|
+
* without either losing its entry, and keeps a directory to two manifests.
|
|
2471
2743
|
*/
|
|
2472
2744
|
declare const MAX_ENTRIES = 2;
|
|
2473
2745
|
/**
|
|
2474
2746
|
* What one walked file contributed to the run, and what its walk read.
|
|
2475
2747
|
* `deps` are the other files whose content went into this file's
|
|
2476
|
-
* summaries
|
|
2477
|
-
* are the units this file's walk claimed
|
|
2478
|
-
*
|
|
2479
|
-
* whatever else the adapter needs to
|
|
2480
|
-
* partial run
|
|
2481
|
-
*
|
|
2482
|
-
*
|
|
2483
|
-
* every partial run.
|
|
2748
|
+
* summaries, and a change to any of them re-extracts this file. `claims`
|
|
2749
|
+
* are the units this file's walk claimed. A partial run replays them
|
|
2750
|
+
* before walking anything, so the same pack wins each unit as before.
|
|
2751
|
+
* `meta` is whatever else the adapter needs to check this file again on
|
|
2752
|
+
* a partial run, such as a route's mount prefixes. A file marked
|
|
2753
|
+
* `cacheable: false` depends on something the cache cannot tie to files,
|
|
2754
|
+
* and is re-extracted on every partial run.
|
|
2484
2755
|
*/
|
|
2485
2756
|
interface RootRecord<Meta = unknown> {
|
|
2486
2757
|
path: string;
|
|
@@ -2493,15 +2764,31 @@ interface RootRecord<Meta = unknown> {
|
|
|
2493
2764
|
meta: Meta;
|
|
2494
2765
|
/** Packs that applied to the file, re-checked on a partial run. */
|
|
2495
2766
|
packs: string[];
|
|
2767
|
+
/** The files this file imports, in the order the adapter's loader found them. */
|
|
2768
|
+
imports?: string[];
|
|
2769
|
+
}
|
|
2770
|
+
/**
|
|
2771
|
+
* What an adapter worked out about one unit of its own, such as the calls
|
|
2772
|
+
* one function body makes. `file` is the file the unit is in and `deps`
|
|
2773
|
+
* the other files that went into `data`. A partial run hands the record
|
|
2774
|
+
* back while `file` and every one of `deps` hash the same, so the adapter
|
|
2775
|
+
* can skip the work that produced it. The cache never reads `data`.
|
|
2776
|
+
*/
|
|
2777
|
+
interface UnitRecord<Data = unknown> {
|
|
2778
|
+
key: string;
|
|
2779
|
+
file: string;
|
|
2780
|
+
deps: string[];
|
|
2781
|
+
data: Data;
|
|
2496
2782
|
}
|
|
2497
2783
|
/**
|
|
2498
|
-
* Which files each summary belongs to. `
|
|
2499
|
-
*
|
|
2500
|
-
* run
|
|
2784
|
+
* Which files each summary belongs to. `summaries[i]` is reused while at
|
|
2785
|
+
* least one file in `owners[i]` is. An empty list marks a summary built
|
|
2786
|
+
* over the whole run, which a partial run always recomputes.
|
|
2501
2787
|
*/
|
|
2502
|
-
interface CacheAttribution<Meta = unknown> {
|
|
2788
|
+
interface CacheAttribution<Meta = unknown, UnitData = unknown> {
|
|
2503
2789
|
roots: RootRecord<Meta>[];
|
|
2504
2790
|
owners: string[][];
|
|
2791
|
+
units?: UnitRecord<UnitData>[];
|
|
2505
2792
|
}
|
|
2506
2793
|
/** Reported by `lookup`: what the cache decided, and why. */
|
|
2507
2794
|
interface CacheDiagnostic {
|
|
@@ -2537,34 +2824,42 @@ type CacheLookup = {
|
|
|
2537
2824
|
diagnostic: CacheDiagnostic;
|
|
2538
2825
|
};
|
|
2539
2826
|
/**
|
|
2540
|
-
* What a `files-changed` miss can still reuse. `validRoots`
|
|
2541
|
-
*
|
|
2542
|
-
*
|
|
2543
|
-
* before calling `reuse`. `reuse` returns the summaries
|
|
2544
|
-
* least one
|
|
2545
|
-
*
|
|
2827
|
+
* What a `files-changed` miss can still reuse. `validRoots` are the files
|
|
2828
|
+
* whose hashes and recorded dependencies are unchanged. The caller can
|
|
2829
|
+
* drop more of them, such as a file whose mount prefix no longer matches,
|
|
2830
|
+
* before calling `reuse`. `reuse` returns the summaries that belong to at
|
|
2831
|
+
* least one remaining file, in stored order, with their owners, so the
|
|
2832
|
+
* caller can merge them and write the result back.
|
|
2546
2833
|
*/
|
|
2547
|
-
interface PartialPlan<Meta = unknown> {
|
|
2834
|
+
interface PartialPlan<Meta = unknown, UnitData = unknown> {
|
|
2548
2835
|
/** Paths whose content hash differs, plus paths new to the set. */
|
|
2549
2836
|
changed: Set<string>;
|
|
2550
2837
|
removed: Set<string>;
|
|
2838
|
+
/**
|
|
2839
|
+
* The stored import list of every file whose content is unchanged, when
|
|
2840
|
+
* no file joined or left the set, since either can move where an import
|
|
2841
|
+
* resolves. Empty otherwise.
|
|
2842
|
+
*/
|
|
2843
|
+
resolvedImports: Map<string, string[]>;
|
|
2551
2844
|
roots: Map<string, RootRecord<Meta>>;
|
|
2552
2845
|
validRoots: Set<string>;
|
|
2553
2846
|
rootsDeclined: number;
|
|
2847
|
+
/** Unit records whose file and deps are all unchanged, by key. */
|
|
2848
|
+
validUnits: Map<string, UnitRecord<UnitData>>;
|
|
2554
2849
|
reuse(valid: ReadonlySet<string>): {
|
|
2555
2850
|
summaries: BehavioralSummary[];
|
|
2556
2851
|
owners: string[][];
|
|
2557
2852
|
};
|
|
2558
2853
|
allSummaries(): BehavioralSummary[];
|
|
2559
2854
|
/** The stored attribution decoded, for a write that changes nothing. */
|
|
2560
|
-
attribution(): CacheAttribution<Meta>;
|
|
2855
|
+
attribution(): CacheAttribution<Meta, UnitData>;
|
|
2561
2856
|
}
|
|
2562
|
-
interface CacheLayer<Meta = unknown> {
|
|
2857
|
+
interface CacheLayer<Meta = unknown, UnitData = unknown> {
|
|
2563
2858
|
/** The summary list on a hit, null on a miss. */
|
|
2564
2859
|
tryHit(input: CacheInput): Promise<BehavioralSummary[] | null>;
|
|
2565
2860
|
/**
|
|
2566
|
-
* The lookup behind `tryHit`, with the reason a miss
|
|
2567
|
-
*
|
|
2861
|
+
* The lookup behind `tryHit`, with the reason for a miss. It stats the
|
|
2862
|
+
* files, and reads only those changed shortly before, to hash them.
|
|
2568
2863
|
*/
|
|
2569
2864
|
lookup(input: CacheInput): Promise<CacheLookup>;
|
|
2570
2865
|
/**
|
|
@@ -2572,33 +2867,39 @@ interface CacheLayer<Meta = unknown> {
|
|
|
2572
2867
|
* work out which files' summaries survive. Null when the entry has
|
|
2573
2868
|
* no per-file layer to reuse, or no entry matches the key at all.
|
|
2574
2869
|
*/
|
|
2575
|
-
plan(input: CacheInput): Promise<PartialPlan<Meta> | null>;
|
|
2870
|
+
plan(input: CacheInput): Promise<PartialPlan<Meta, UnitData> | null>;
|
|
2576
2871
|
/**
|
|
2577
|
-
*
|
|
2578
|
-
*
|
|
2579
|
-
*
|
|
2580
|
-
* ever be reused whole.
|
|
2872
|
+
* Save a fresh extraction's summaries against this file list, so a later
|
|
2873
|
+
* `lookup` with the same files returns them. Without `attribution` the
|
|
2874
|
+
* entry can only be reused whole.
|
|
2581
2875
|
*/
|
|
2582
|
-
write(input: CacheInput, summaries: BehavioralSummary[], attribution?: CacheAttribution<Meta>): Promise<void>;
|
|
2876
|
+
write(input: CacheInput, summaries: BehavioralSummary[], attribution?: CacheAttribution<Meta, UnitData>): Promise<void>;
|
|
2583
2877
|
}
|
|
2584
2878
|
interface CacheInput {
|
|
2585
2879
|
/** Absolute paths of every file the run walks. */
|
|
2586
2880
|
files: ReadonlyArray<string>;
|
|
2587
2881
|
adapterPacksDigest: string;
|
|
2588
2882
|
/**
|
|
2589
|
-
*
|
|
2590
|
-
*
|
|
2591
|
-
* not every adapter has one.
|
|
2883
|
+
* A file whose change invalidates the whole entry, such as a tsconfig or
|
|
2884
|
+
* a project manifest. Not every adapter has one.
|
|
2592
2885
|
*/
|
|
2593
2886
|
configPath?: string;
|
|
2594
2887
|
}
|
|
2595
2888
|
/**
|
|
2596
|
-
*
|
|
2597
|
-
*
|
|
2598
|
-
*
|
|
2599
|
-
|
|
2889
|
+
* A cache layer rooted at `cacheDir`. With `null`, every lookup misses and
|
|
2890
|
+
* `write` does nothing, for a one-shot extract where the cache would only
|
|
2891
|
+
* add time.
|
|
2892
|
+
*/
|
|
2893
|
+
declare function createCacheLayer<Meta = unknown, UnitData = unknown>(cacheDir: string | null): CacheLayer<Meta, UnitData>;
|
|
2894
|
+
|
|
2895
|
+
/**
|
|
2896
|
+
* Whether a write after `statAt` could leave this file's mtime and size
|
|
2897
|
+
* where the stat saw them, because its last change was that recent.
|
|
2600
2898
|
*/
|
|
2601
|
-
declare function
|
|
2899
|
+
declare function stampMayMissAWrite(stat: {
|
|
2900
|
+
mtimeMs: number;
|
|
2901
|
+
ctimeMs: number;
|
|
2902
|
+
}, statAt: number): boolean;
|
|
2602
2903
|
|
|
2603
2904
|
/**
|
|
2604
2905
|
* The extraction funnel, shared across languages.
|
|
@@ -2606,10 +2907,9 @@ declare function createCacheLayer<Meta = unknown>(cacheDir: string | null): Cach
|
|
|
2606
2907
|
* "Why did this run produce nothing" is always "at which stage did the
|
|
2607
2908
|
* count reach zero", so the report is a funnel: files in the tsconfig,
|
|
2608
2909
|
* files the import gates selected, units discovered, summaries built.
|
|
2609
|
-
* Each
|
|
2610
|
-
*
|
|
2611
|
-
*
|
|
2612
|
-
* is what made an entire pack family extract nothing in silence.
|
|
2910
|
+
* Each stage records its own row, so the CLI never works the counts out
|
|
2911
|
+
* from a second copy of the pre-filter's logic that could drift from the
|
|
2912
|
+
* first.
|
|
2613
2913
|
*
|
|
2614
2914
|
* TypeScript, Python and Ruby all build one of these, though only
|
|
2615
2915
|
* TypeScript gates files by import specifier today. A pack with no gate
|
|
@@ -2620,9 +2920,9 @@ declare function createCacheLayer<Meta = unknown>(cacheDir: string | null): Cach
|
|
|
2620
2920
|
interface PackFunnel {
|
|
2621
2921
|
pack: string;
|
|
2622
2922
|
/**
|
|
2623
|
-
*
|
|
2624
|
-
*
|
|
2625
|
-
*
|
|
2923
|
+
* The version stamp the pack declares, or null when it declares none.
|
|
2924
|
+
* The cache keys on it, so a pack that never changes its stamp can
|
|
2925
|
+
* serve a later run with an earlier build's results.
|
|
2626
2926
|
*/
|
|
2627
2927
|
version: string | null;
|
|
2628
2928
|
/**
|
|
@@ -2644,11 +2944,10 @@ interface PackFunnel {
|
|
|
2644
2944
|
*/
|
|
2645
2945
|
gates: string[];
|
|
2646
2946
|
/**
|
|
2647
|
-
* Gate specifiers that do not resolve from the project.
|
|
2648
|
-
*
|
|
2649
|
-
* installed
|
|
2650
|
-
* textual
|
|
2651
|
-
* nothing else surfaces.
|
|
2947
|
+
* Gate specifiers that do not resolve from the project. A non-empty
|
|
2948
|
+
* list usually means the target project's dependencies are not
|
|
2949
|
+
* installed. Packs that resolve symbols then stop working while packs
|
|
2950
|
+
* with a textual gate still run, and nothing else in the report shows it.
|
|
2652
2951
|
*/
|
|
2653
2952
|
unresolvedGates: string[];
|
|
2654
2953
|
/** Files the pre-filter selected for this pack. */
|
|
@@ -2707,9 +3006,9 @@ interface PackFunnel {
|
|
|
2707
3006
|
/**
|
|
2708
3007
|
* What the pack wrote as data rather than as code, or null for a pack
|
|
2709
3008
|
* written as a hand-rolled walk, or for a language whose packs have
|
|
2710
|
-
* no declared-pattern system at all.
|
|
2711
|
-
*
|
|
2712
|
-
*
|
|
3009
|
+
* no declared-pattern system at all. Unlike the counts, this comes from
|
|
3010
|
+
* the pack's definition and not from the run. It is reported so the
|
|
3011
|
+
* move of packs onto declared patterns can be measured.
|
|
2713
3012
|
*/
|
|
2714
3013
|
declarations: PackDeclarations | null;
|
|
2715
3014
|
}
|
|
@@ -2724,11 +3023,10 @@ interface ExtractionReport {
|
|
|
2724
3023
|
* Files whose exports the checker could not follow, so the run read
|
|
2725
3024
|
* them as exporting nothing.
|
|
2726
3025
|
*
|
|
2727
|
-
* Without this
|
|
2728
|
-
*
|
|
2729
|
-
*
|
|
2730
|
-
*
|
|
2731
|
-
* count below is a floor while this is non-empty.
|
|
3026
|
+
* Without this list, a module whose barrel chain overflowed the call
|
|
3027
|
+
* stack looks the same as a module that exports nothing: both produce
|
|
3028
|
+
* no summaries and exit 0. Anything reachable only through these files
|
|
3029
|
+
* is missing, and every count below is a floor while this is non-empty.
|
|
2732
3030
|
*/
|
|
2733
3031
|
filesWithUnreadableExports: string[];
|
|
2734
3032
|
/**
|
|
@@ -2737,10 +3035,9 @@ interface ExtractionReport {
|
|
|
2737
3035
|
*/
|
|
2738
3036
|
emptyStage: EmptyStage | null;
|
|
2739
3037
|
/**
|
|
2740
|
-
* Reassigned names the run stated
|
|
2741
|
-
* decides which write a reader sees.
|
|
2742
|
-
*
|
|
2743
|
-
* reaching definitions is worth writing.
|
|
3038
|
+
* Reassigned names the run stated no value for, because control flow
|
|
3039
|
+
* decides which write a reader sees. Across a large corpus, the count
|
|
3040
|
+
* shows how much a scoped reaching-definitions analysis would recover.
|
|
2744
3041
|
*/
|
|
2745
3042
|
reassignedNamesUnstated: number;
|
|
2746
3043
|
}
|
|
@@ -2754,7 +3051,7 @@ type EmptyStage = "tsconfig" | "gateResolution" | "candidateFiles" | "discovery"
|
|
|
2754
3051
|
* that looked and found nothing.
|
|
2755
3052
|
*/
|
|
2756
3053
|
interface PackFailure {
|
|
2757
|
-
/** The hook that threw,
|
|
3054
|
+
/** The hook that threw, by the name a pack author uses for it. */
|
|
2758
3055
|
hook: string;
|
|
2759
3056
|
/** The file the pack was reading. */
|
|
2760
3057
|
file: string;
|
|
@@ -2774,9 +3071,9 @@ interface PackTally {
|
|
|
2774
3071
|
}
|
|
2775
3072
|
declare const emptyTally: () => PackTally;
|
|
2776
3073
|
/**
|
|
2777
|
-
* Record that a pack's hook threw, and
|
|
2778
|
-
*
|
|
2779
|
-
*
|
|
3074
|
+
* Record that a pack's hook threw, and return one line a caller can print.
|
|
3075
|
+
* The failure also goes on the tally, so the pack's counts do not look
|
|
3076
|
+
* like those of a pack that found nothing.
|
|
2780
3077
|
*/
|
|
2781
3078
|
declare function recordPackFailure(tally: PackTally | undefined, failure: {
|
|
2782
3079
|
pack: string;
|
|
@@ -2796,8 +3093,8 @@ declare function tallyUnit(tallies: Map<string, PackTally>, recognition: string
|
|
|
2796
3093
|
* it, because the summaries a pack is responsible for are not all built
|
|
2797
3094
|
* where the pack is in scope: wrapper expansion and sub-unit synthesis
|
|
2798
3095
|
* both add summaries after discovery has moved on. Every summary
|
|
2799
|
-
* records
|
|
2800
|
-
*
|
|
3096
|
+
* records the pack that recognised it, so grouping on that credits each
|
|
3097
|
+
* summary to its pack however late it was built.
|
|
2801
3098
|
*/
|
|
2802
3099
|
interface SummaryCounts {
|
|
2803
3100
|
bound: number;
|
|
@@ -2822,6 +3119,34 @@ declare function buildUngatedExtractionReport(args: {
|
|
|
2822
3119
|
summaries: ReadonlyArray<BehavioralSummary>;
|
|
2823
3120
|
}): ExtractionReport;
|
|
2824
3121
|
|
|
3122
|
+
/**
|
|
3123
|
+
* A directory suss writes for itself, such as the extraction cache, can
|
|
3124
|
+
* land in any package of a repository, where a root `.gitignore` entry
|
|
3125
|
+
* for `/.suss` does not reach. A `.gitignore` of `*` inside it keeps it
|
|
3126
|
+
* out of version control wherever it is, the way pytest's cache does.
|
|
3127
|
+
*/
|
|
3128
|
+
/** Creates `dir` and a `.gitignore` of `*` in it. A `.gitignore` already there is kept. */
|
|
3129
|
+
declare function makeIgnoredDirectory(dir: string): void;
|
|
3130
|
+
|
|
3131
|
+
/**
|
|
3132
|
+
* Parses a process keeps between runs of one project, by file.
|
|
3133
|
+
*
|
|
3134
|
+
* The Python and Ruby adapters parse every file on every run, because
|
|
3135
|
+
* facts are emitted over the whole project. A process that reads the same
|
|
3136
|
+
* project after every edit hands a run one of these, and a file whose text
|
|
3137
|
+
* is the same as last time gets last time's tree back. The trees are
|
|
3138
|
+
* WASM memory the garbage collector cannot see, so a tree that is replaced
|
|
3139
|
+
* or whose file went away is handed to `release`.
|
|
3140
|
+
*/
|
|
3141
|
+
declare class KeptParses<T> {
|
|
3142
|
+
private readonly release;
|
|
3143
|
+
private readonly byFile;
|
|
3144
|
+
constructor(release?: (value: T) => void);
|
|
3145
|
+
parse(file: string, source: string, make: (source: string) => Promise<T>): Promise<T>;
|
|
3146
|
+
/** Lets go of every file not in this run. */
|
|
3147
|
+
keepOnly(files: Iterable<string>): void;
|
|
3148
|
+
}
|
|
3149
|
+
|
|
2825
3150
|
/**
|
|
2826
3151
|
* Checks that tell you a pack is probably not working.
|
|
2827
3152
|
*
|
|
@@ -2834,8 +3159,8 @@ declare function buildUngatedExtractionReport(args: {
|
|
|
2834
3159
|
* signal. What makes zero a signal is the count before it. A pack whose
|
|
2835
3160
|
* import gate picked forty files and whose discovery then found no unit
|
|
2836
3161
|
* in any of them said "look here" and failed to look. Every later stage
|
|
2837
|
-
* works the same way,
|
|
2838
|
-
*
|
|
3162
|
+
* works the same way, so the check is one comparison run over a list of
|
|
3163
|
+
* stage pairs instead of one check written per stage.
|
|
2839
3164
|
*/
|
|
2840
3165
|
|
|
2841
3166
|
/** One thing that looks wrong, reported the way the dogfood invariants are. */
|
|
@@ -2869,13 +3194,13 @@ interface HealthCheck {
|
|
|
2869
3194
|
violations: HealthViolation[];
|
|
2870
3195
|
}
|
|
2871
3196
|
/**
|
|
2872
|
-
*
|
|
3197
|
+
* How much of one pack is data and how much is code (#542).
|
|
2873
3198
|
*
|
|
2874
|
-
*
|
|
2875
|
-
*
|
|
2876
|
-
*
|
|
2877
|
-
*
|
|
2878
|
-
*
|
|
3199
|
+
* A pack with every link written as data runs on any adapter with the
|
|
3200
|
+
* executor ops. A link written as a function runs only where its own
|
|
3201
|
+
* language does, and one that reads the syntax tree runs only on the
|
|
3202
|
+
* adapter whose tree it reads. All three are allowed, and this counts
|
|
3203
|
+
* each kind.
|
|
2879
3204
|
*/
|
|
2880
3205
|
interface PackGradient {
|
|
2881
3206
|
pack: string;
|
|
@@ -2906,16 +3231,13 @@ declare function evaluatePackHealth(report: ExtractionReport): HealthCheck[];
|
|
|
2906
3231
|
declare function formatPackHealth(checks: ReadonlyArray<HealthCheck>, audiences: ReadonlyArray<HealthCheck["audience"]>): string;
|
|
2907
3232
|
|
|
2908
3233
|
/**
|
|
2909
|
-
*
|
|
2910
|
-
*
|
|
2911
|
-
*
|
|
2912
|
-
*
|
|
2913
|
-
* reachable closure" without engaging a profiler. Cheap enough to
|
|
2914
|
-
* always be on; a phase that isn't entered contributes zero.
|
|
3234
|
+
* Wall time per named phase of an adapter run, so the CLI can print
|
|
3235
|
+
* "extract took 17s, of which 11s was in the reachable closure" without
|
|
3236
|
+
* a profiler. It is cheap enough to leave on, and a phase that never
|
|
3237
|
+
* runs adds nothing.
|
|
2915
3238
|
*
|
|
2916
|
-
*
|
|
2917
|
-
*
|
|
2918
|
-
* long-running daemon (LSP / file-watcher), revisit then.
|
|
3239
|
+
* Everything stays in one process and goes to stdout, so there is no
|
|
3240
|
+
* OpenTelemetry dependency for consumers to inherit.
|
|
2919
3241
|
*/
|
|
2920
3242
|
interface TimingReport {
|
|
2921
3243
|
totalMs: number;
|
|
@@ -2928,48 +3250,34 @@ interface TimingReport {
|
|
|
2928
3250
|
interface Timer {
|
|
2929
3251
|
/** Run `fn`, accumulate wall time under `label`, return its result. */
|
|
2930
3252
|
time<T>(label: string, fn: () => T): T;
|
|
2931
|
-
/**
|
|
3253
|
+
/** The same as `time`, for an async `fn`. */
|
|
2932
3254
|
timeAsync<T>(label: string, fn: () => Promise<T>): Promise<T>;
|
|
2933
3255
|
/** Snapshot of all accumulated phases, ordered by total time descending. */
|
|
2934
3256
|
report(): TimingReport;
|
|
2935
3257
|
}
|
|
2936
|
-
/**
|
|
2937
|
-
* Build a fresh timer. Each adapter run gets its own, keeps
|
|
2938
|
-
* concurrent extracts independent (irrelevant today, will matter if
|
|
2939
|
-
* we add a server mode).
|
|
2940
|
-
*/
|
|
3258
|
+
/** Each adapter run gets its own timer, so two runs at once never mix their phases. */
|
|
2941
3259
|
declare function createTimer(): Timer;
|
|
2942
|
-
/**
|
|
3260
|
+
/** A timer that runs `fn` and records nothing, for callers that do not want timing. */
|
|
2943
3261
|
declare function noopTimer(): Timer;
|
|
2944
3262
|
|
|
2945
3263
|
/**
|
|
2946
|
-
* The vocabulary a language adapter implements so that any declared
|
|
2947
|
-
*
|
|
3264
|
+
* The vocabulary a language adapter implements so that any declared pack
|
|
3265
|
+
* runs on it. A pack is data, so the adapter has to turn "did this module
|
|
3266
|
+
* declare the method" into a yes or no about a particular program, and
|
|
3267
|
+
* these interfaces are everything a pack can ask of it.
|
|
2948
3268
|
*
|
|
2949
|
-
*
|
|
2950
|
-
*
|
|
2951
|
-
*
|
|
2952
|
-
* ask for. An adapter implements them once and every pack runs there,
|
|
2953
|
-
* which is what lets one pack drive several languages.
|
|
2954
|
-
*
|
|
2955
|
-
* They live here rather than beside the builders that produce them,
|
|
2956
|
-
* because an adapter needs this and none of the rest: the TypeScript
|
|
2957
|
-
* adapter imports these types and no runtime code from
|
|
2958
|
-
* `@suss/recognize`. Python and Ruby will want the same.
|
|
3269
|
+
* They are in this package rather than beside the builders in
|
|
3270
|
+
* `@suss/recognize`, so an adapter imports the types without that
|
|
3271
|
+
* package's runtime code. Only the TypeScript adapter implements them.
|
|
2959
3272
|
*
|
|
2960
3273
|
* Nothing here mentions a syntax tree. A pack that needs the tree goes
|
|
2961
3274
|
* through `@suss/recognize/ast`, a separate import so that reaching for
|
|
2962
3275
|
* it shows up in a diff and in the pack health report.
|
|
2963
3276
|
*/
|
|
2964
3277
|
/**
|
|
2965
|
-
* How a pack pins down the receiver a call is on.
|
|
2966
|
-
*
|
|
2967
|
-
*
|
|
2968
|
-
* express()`), `imported`, `anchored` (a chain read from its anchor
|
|
2969
|
-
* call), `inherits` (a Ruby or Python receiver matched by ancestry) and
|
|
2970
|
-
* `global` (`process.env`, bare `fetch`). Each arrives as a member here
|
|
2971
|
-
* with an entry in every adapter's dispatch table. The README beside
|
|
2972
|
-
* this file says which starts are not receiver-shaped at all.
|
|
3278
|
+
* How a pack pins down the receiver a call is on. The recognize package's
|
|
3279
|
+
* DESIGN.md lists the origins not built yet (#542) and the places a match
|
|
3280
|
+
* can start that are not receivers.
|
|
2973
3281
|
*/
|
|
2974
3282
|
type ReceiverOrigin = DeclaredBy | ConstructedFrom;
|
|
2975
3283
|
/**
|
|
@@ -3003,29 +3311,41 @@ interface ConstructedFrom {
|
|
|
3003
3311
|
readonly named?: readonly string[];
|
|
3004
3312
|
}
|
|
3005
3313
|
|
|
3314
|
+
/**
|
|
3315
|
+
* What a reader returns for a name nothing in the source settles.
|
|
3316
|
+
* `"nothing"` returns null, and `"reference"` returns the name of the
|
|
3317
|
+
* value to look up instead.
|
|
3318
|
+
*/
|
|
3006
3319
|
type UnsettledName = "nothing" | "reference";
|
|
3007
3320
|
/**
|
|
3008
3321
|
* One value a call states, as the questions a pack can ask about it.
|
|
3009
3322
|
*
|
|
3010
|
-
* `CallOps` reaches
|
|
3011
|
-
* values that are not calls. A library that takes one request object
|
|
3012
|
-
*
|
|
3013
|
-
*
|
|
3014
|
-
*
|
|
3015
|
-
* node. So the rule it writes runs wherever the ops do.
|
|
3323
|
+
* `CallOps` reaches the calls around the one in hand, and this reaches the
|
|
3324
|
+
* values that are not calls. A library that takes one request object puts
|
|
3325
|
+
* everything the call does inside it, as a list or as a string in the
|
|
3326
|
+
* library's own query language. A pack that reads those gets this instead
|
|
3327
|
+
* of the adapter's node, so its rule runs on any adapter with the ops.
|
|
3016
3328
|
*/
|
|
3017
3329
|
interface ValueOps {
|
|
3018
3330
|
/** The text of the string the source wrote, or null for anything else. */
|
|
3019
3331
|
text(): string | null;
|
|
3020
3332
|
/**
|
|
3021
|
-
*
|
|
3022
|
-
* writing it out. A queue URL is nearly always
|
|
3333
|
+
* The name of this value, when the source refers to it by name instead
|
|
3334
|
+
* of writing it out. A queue URL is nearly always
|
|
3023
3335
|
* `process.env.ORDERS_QUEUE_URL`, so the value only exists at deploy
|
|
3024
|
-
* time and the env var's name
|
|
3025
|
-
*
|
|
3026
|
-
*
|
|
3336
|
+
* time and both sides of the boundary use the env var's name.
|
|
3337
|
+
* `"reference"` returns that name, and `"nothing"` returns null for
|
|
3338
|
+
* anything the source does not settle.
|
|
3027
3339
|
*/
|
|
3028
3340
|
name(unsettled: UnsettledName): string | null;
|
|
3341
|
+
/**
|
|
3342
|
+
* Every string this value can be, when the source limits it to a
|
|
3343
|
+
* few. `` `record.${op}` `` with `op` typed `"a" | "b"` is
|
|
3344
|
+
* `record.a` and `record.b`. Null when part of it could be anything,
|
|
3345
|
+
* or when there are more than `cap`. An adapter that has not
|
|
3346
|
+
* implemented this leaves it out, and a reader has only `name`.
|
|
3347
|
+
*/
|
|
3348
|
+
names?(cap: number): readonly string[] | null;
|
|
3029
3349
|
/**
|
|
3030
3350
|
* The yes or no the source wrote here, or null for anything else. A
|
|
3031
3351
|
* library that asks which fields a call wants states them as a map of
|
|
@@ -3061,16 +3381,17 @@ interface ValueOps {
|
|
|
3061
3381
|
* a call is null rather than being dropped, so the two lists stay in
|
|
3062
3382
|
* step.
|
|
3063
3383
|
*
|
|
3064
|
-
* What a hole
|
|
3065
|
-
* there, so a query that
|
|
3384
|
+
* What a hole means is up to the pack. This only reports what was
|
|
3385
|
+
* written there, so a query that interpolates a table object can still
|
|
3386
|
+
* be read.
|
|
3066
3387
|
*/
|
|
3067
3388
|
holes(): readonly (CallOps | null)[];
|
|
3068
3389
|
/**
|
|
3069
3390
|
* The same holes as values, in the same order, for a reader that
|
|
3070
3391
|
* wants what the source settled a hole to rather than what call was
|
|
3071
|
-
* written there. A table kept in a module constant
|
|
3072
|
-
* hole is a name,
|
|
3073
|
-
*
|
|
3392
|
+
* written there. A table name kept in a module constant needs this:
|
|
3393
|
+
* the hole is a name, so `holes` gives null for it and this gives the
|
|
3394
|
+
* constant.
|
|
3074
3395
|
*
|
|
3075
3396
|
* An adapter that has not implemented this leaves it out, and a
|
|
3076
3397
|
* reader then has only the calls.
|
|
@@ -3097,7 +3418,7 @@ interface ValueEntry {
|
|
|
3097
3418
|
*
|
|
3098
3419
|
* Two members give back another `CallOps`, which is how these questions
|
|
3099
3420
|
* reach a call next to this one. A chain of calls and a command object
|
|
3100
|
-
* are both these same questions asked one step along, so neither
|
|
3421
|
+
* are both these same questions asked one step along, so neither needs
|
|
3101
3422
|
* a question of its own.
|
|
3102
3423
|
*/
|
|
3103
3424
|
interface CallOps {
|
|
@@ -3106,11 +3427,9 @@ interface CallOps {
|
|
|
3106
3427
|
/** Whether the receiver came from where the origin says. */
|
|
3107
3428
|
receiverIsFrom(origin: ReceiverOrigin): boolean;
|
|
3108
3429
|
/**
|
|
3109
|
-
* Whether the
|
|
3110
|
-
*
|
|
3111
|
-
*
|
|
3112
|
-
* an argument asks this of it before reading anything, so it never
|
|
3113
|
-
* reads an argument that was never the one.
|
|
3430
|
+
* Whether the callee itself came from where the origin says. A pack
|
|
3431
|
+
* that steps to an argument such as `new GetCommand(...)` asks this
|
|
3432
|
+
* first, so it never reads a command from some other library.
|
|
3114
3433
|
*/
|
|
3115
3434
|
isFrom(origin: ReceiverOrigin): boolean;
|
|
3116
3435
|
/** How many arguments the call passes. */
|
|
@@ -3132,6 +3451,23 @@ interface CallOps {
|
|
|
3132
3451
|
* class, the same as any other call.
|
|
3133
3452
|
*/
|
|
3134
3453
|
argument(index: number): CallOps | null;
|
|
3454
|
+
/**
|
|
3455
|
+
* Said by a chain that steps to the arguments of every call it sees,
|
|
3456
|
+
* before it reads the first one: at every call the walk visits, it
|
|
3457
|
+
* will read the arguments from `first` through `last`, or to the end
|
|
3458
|
+
* when `last` is left out. An adapter that asks a separate question
|
|
3459
|
+
* for each read can ask about all of them at once. Leaving it out
|
|
3460
|
+
* changes how fast a run is and nothing else.
|
|
3461
|
+
*/
|
|
3462
|
+
readingArguments?(first: number, last?: number): void;
|
|
3463
|
+
/**
|
|
3464
|
+
* Said by a chain before it asks what made a receiver: at every call
|
|
3465
|
+
* the walk visits whose method is one of `methods`, spelled as the
|
|
3466
|
+
* source spells it, it will ask about the receiver. An adapter can
|
|
3467
|
+
* then ask about all of them at once, and leaving it out changes only
|
|
3468
|
+
* how fast a run is.
|
|
3469
|
+
*/
|
|
3470
|
+
readingReceivers?(methods: ReadonlySet<string>): void;
|
|
3135
3471
|
/**
|
|
3136
3472
|
* The call the callee itself was written as, or null when nothing
|
|
3137
3473
|
* wrote it as one. A class a factory made is the case: `new
|
|
@@ -3154,7 +3490,7 @@ interface CallOps {
|
|
|
3154
3490
|
*/
|
|
3155
3491
|
parameterReadsAt?(index: number): readonly string[] | null;
|
|
3156
3492
|
/**
|
|
3157
|
-
*
|
|
3493
|
+
* One property of the object literal passed at this position. A
|
|
3158
3494
|
* property bag is not a call, so nothing else here reaches into one.
|
|
3159
3495
|
*/
|
|
3160
3496
|
propertyAt(index: number, property: string, unsettled: UnsettledName): string | null;
|
|
@@ -3167,13 +3503,42 @@ interface CallOps {
|
|
|
3167
3503
|
valueAt(index: number): ValueOps | null;
|
|
3168
3504
|
/**
|
|
3169
3505
|
* The one call behind the receiver the origin accepts, however many
|
|
3170
|
-
* name, construction, or query hops separate them
|
|
3171
|
-
* `model(...)` behind a document
|
|
3506
|
+
* name, construction, or query hops separate them, such as Mongoose's
|
|
3507
|
+
* `model(...)` behind a document. Null when nothing
|
|
3172
3508
|
* behind the receiver matches, when two distinct calls do (picking
|
|
3173
3509
|
* one would depend on the order facts arrived), and for an origin
|
|
3174
3510
|
* kind with no construction to hand back.
|
|
3175
3511
|
*/
|
|
3176
3512
|
anchorCall?(origin: ReceiverOrigin): CallOps | null;
|
|
3513
|
+
/**
|
|
3514
|
+
* The class the argument in this position refers to, or null when it
|
|
3515
|
+
* refers to none the run declares. An ORM that takes an entity class,
|
|
3516
|
+
* `InjectRepository(Order)`, keeps the table on the class itself.
|
|
3517
|
+
*/
|
|
3518
|
+
classAt?(index: number): ClassOps | null;
|
|
3519
|
+
/**
|
|
3520
|
+
* Said by a recognizer about an effect it built from this call: the
|
|
3521
|
+
* value the call states for each column the effect writes or picks
|
|
3522
|
+
* rows by. The adapter asks where each value came from and records it
|
|
3523
|
+
* on the transition. Leaving it out changes only that record.
|
|
3524
|
+
*/
|
|
3525
|
+
statesSlots?(effect: Effect, slots: readonly StatedSlot[]): void;
|
|
3526
|
+
}
|
|
3527
|
+
/** A column an effect writes or picks rows by, and the value stated for it. */
|
|
3528
|
+
interface StatedSlot {
|
|
3529
|
+
readonly slot: "field" | "selector";
|
|
3530
|
+
readonly name: string;
|
|
3531
|
+
readonly value: ValueOps;
|
|
3532
|
+
}
|
|
3533
|
+
/** One class a call refers to, as the questions a pack can ask about it. */
|
|
3534
|
+
interface ClassOps {
|
|
3535
|
+
/** The name the class is declared under, or null when it has none. */
|
|
3536
|
+
name(): string | null;
|
|
3537
|
+
/**
|
|
3538
|
+
* The one decorator call on the class that the origin accepts, such
|
|
3539
|
+
* as `@Entity("orders")`. Null when none does, or when two do.
|
|
3540
|
+
*/
|
|
3541
|
+
decorator(origin: ReceiverOrigin): CallOps | null;
|
|
3177
3542
|
}
|
|
3178
3543
|
/**
|
|
3179
3544
|
* The property an adapter puts its ops on, in the context it hands a
|
|
@@ -3194,26 +3559,27 @@ interface AstCapableOps extends CallOps {
|
|
|
3194
3559
|
}
|
|
3195
3560
|
|
|
3196
3561
|
/**
|
|
3197
|
-
* The assembly engine
|
|
3198
|
-
*
|
|
3199
|
-
* fits in the pipeline.
|
|
3562
|
+
* The assembly engine. A language adapter hands over a `RawCodeStructure`,
|
|
3563
|
+
* and `assembleSummary` turns it into a `BehavioralSummary`. The package
|
|
3564
|
+
* README explains where that step fits in the pipeline.
|
|
3200
3565
|
*
|
|
3201
|
-
*
|
|
3202
|
-
*
|
|
3203
|
-
*
|
|
3204
|
-
*
|
|
3205
|
-
*
|
|
3566
|
+
* `RawCodeStructure` and the raw types around it are the contract every
|
|
3567
|
+
* adapter and pack implements, so adding a field here changes that
|
|
3568
|
+
* contract. This is also the only module that turns a `Reading` into a
|
|
3569
|
+
* claim on a summary. Adapters pass readings over uncollapsed, and the rule
|
|
3570
|
+
* for collapsing them is below.
|
|
3206
3571
|
*/
|
|
3207
3572
|
|
|
3208
3573
|
interface RawParameter {
|
|
3209
3574
|
name: string;
|
|
3210
3575
|
position: number;
|
|
3211
3576
|
/**
|
|
3212
|
-
* What the parameter is for, in the library's own vocabulary.
|
|
3213
|
-
* adapter could not tell,
|
|
3214
|
-
* goes in `readings`.
|
|
3577
|
+
* What the parameter is for, in the library's own vocabulary. Null when
|
|
3578
|
+
* the adapter could not tell, with the reason in `readings`.
|
|
3215
3579
|
*/
|
|
3216
3580
|
role: string | null;
|
|
3581
|
+
/** Which field of the role's value the parameter is, when the library hands over one field. */
|
|
3582
|
+
field?: string;
|
|
3217
3583
|
typeText: string | null;
|
|
3218
3584
|
}
|
|
3219
3585
|
interface RawCondition {
|
|
@@ -3223,7 +3589,7 @@ interface RawCondition {
|
|
|
3223
3589
|
source: ConditionSource;
|
|
3224
3590
|
}
|
|
3225
3591
|
interface RawTerminal {
|
|
3226
|
-
kind: "response" | "throw" | "return" | "render" | "delegate" | "emit" | "void";
|
|
3592
|
+
kind: "response" | "throw" | "return" | "render" | "delegate" | "emit" | "void" | "exit";
|
|
3227
3593
|
statusCode: {
|
|
3228
3594
|
type: "literal";
|
|
3229
3595
|
value: number;
|
|
@@ -3236,6 +3602,13 @@ interface RawTerminal {
|
|
|
3236
3602
|
shape: TypeShape | null;
|
|
3237
3603
|
} | null;
|
|
3238
3604
|
exceptionType: string | null;
|
|
3605
|
+
/** On a throw, what the exception inherits from, where the adapter read it. */
|
|
3606
|
+
exceptionAncestry?: {
|
|
3607
|
+
ancestors: string[];
|
|
3608
|
+
incomplete: boolean;
|
|
3609
|
+
};
|
|
3610
|
+
/** On a throw, the status the framework sends when no handler catches it. */
|
|
3611
|
+
statusWhenUncaught?: number;
|
|
3239
3612
|
message: string | null;
|
|
3240
3613
|
/** Set on a throw whose pack declared the thrown status is the wire response. */
|
|
3241
3614
|
producesResponse?: boolean;
|
|
@@ -3302,7 +3675,7 @@ type RawEffect = {
|
|
|
3302
3675
|
callee: string;
|
|
3303
3676
|
args: EffectArg[];
|
|
3304
3677
|
async: boolean;
|
|
3305
|
-
/**
|
|
3678
|
+
/** An empty list means the call is not under any guard, so it always fires. */
|
|
3306
3679
|
preconditions?: RawCondition[];
|
|
3307
3680
|
} | {
|
|
3308
3681
|
type: "emission";
|
|
@@ -3320,6 +3693,8 @@ interface RawBranch {
|
|
|
3320
3693
|
* `RawEffect` conversion that `effects` goes through.
|
|
3321
3694
|
*/
|
|
3322
3695
|
extraEffects?: Effect[];
|
|
3696
|
+
/** Where the values in the slots of `extraEffects` came from. */
|
|
3697
|
+
provenance?: RawProvenance[];
|
|
3323
3698
|
location: {
|
|
3324
3699
|
start: number;
|
|
3325
3700
|
end: number;
|
|
@@ -3340,6 +3715,17 @@ interface RawBranch {
|
|
|
3340
3715
|
*/
|
|
3341
3716
|
bodyShapeReading?: DefaultedReading<TypeShape>;
|
|
3342
3717
|
}
|
|
3718
|
+
/**
|
|
3719
|
+
* Where the value in one slot came from, keyed by the effect object an
|
|
3720
|
+
* adapter put in `extraEffects`. Assembly folds repeated effects, so it
|
|
3721
|
+
* works out each effect's position only once the list is final.
|
|
3722
|
+
*/
|
|
3723
|
+
interface RawProvenance {
|
|
3724
|
+
effect: Effect;
|
|
3725
|
+
slot: ProvenanceSlot["slot"];
|
|
3726
|
+
name: string;
|
|
3727
|
+
from: ValueRef[];
|
|
3728
|
+
}
|
|
3343
3729
|
interface RawDependencyCall {
|
|
3344
3730
|
name: string;
|
|
3345
3731
|
assignedTo: string | null;
|
|
@@ -3420,14 +3806,14 @@ interface RawCodeStructure {
|
|
|
3420
3806
|
bodyContent?: BodyContent;
|
|
3421
3807
|
dependencyCalls: RawDependencyCall[];
|
|
3422
3808
|
/**
|
|
3423
|
-
* Reads the adapter saw in the body that never flow into a condition
|
|
3424
|
-
*
|
|
3425
|
-
* `inputReads`
|
|
3809
|
+
* Reads the adapter saw in the body that never flow into a condition or
|
|
3810
|
+
* an output value, such as a render tree's `props.title`. They are merged
|
|
3811
|
+
* into `inputReads` with the ones derived from conditions and outputs.
|
|
3426
3812
|
*/
|
|
3427
3813
|
extraInputReads?: InputRead[];
|
|
3428
3814
|
declaredContract: RawDeclaredContract | null;
|
|
3429
|
-
/** The property a consumer
|
|
3430
|
-
* axios
|
|
3815
|
+
/** The property a consumer reads the body through, such as `data` for
|
|
3816
|
+
* axios, so the checker can unwrap it without a rule per pack. */
|
|
3431
3817
|
bodyAccessors?: string[];
|
|
3432
3818
|
/** The same, for the status: `status` for fetch and for axios. */
|
|
3433
3819
|
statusAccessors?: string[];
|
|
@@ -3435,6 +3821,10 @@ interface RawCodeStructure {
|
|
|
3435
3821
|
successAccessors?: string[];
|
|
3436
3822
|
/** Whether this client's non-2xx arrives as a response or a rejection. */
|
|
3437
3823
|
failureDelivery?: FailureDelivery;
|
|
3824
|
+
/** Whether this client follows a redirect or hands the 3xx back. */
|
|
3825
|
+
redirectDelivery?: RedirectDelivery;
|
|
3826
|
+
/** Statuses the handler's own code lists as possible responses, such as FastAPI's `responses=`. */
|
|
3827
|
+
declaredStatuses?: number[];
|
|
3438
3828
|
/** Left exactly as written, because the extractor does not depend on
|
|
3439
3829
|
* graphql-js. The parsing happens at check time. */
|
|
3440
3830
|
graphqlDocument?: string;
|
|
@@ -3451,6 +3841,8 @@ interface RawCodeStructure {
|
|
|
3451
3841
|
wrappers?: WrapperReference[];
|
|
3452
3842
|
/** Where a REST pack's handlers read each part of the request, from the pack. */
|
|
3453
3843
|
requestSpelling?: RequestSpellingMetadata;
|
|
3844
|
+
/** What a test pack found about a `test` unit: whether it is skipped, and what it replaces with a mock. */
|
|
3845
|
+
test?: TestMetadata;
|
|
3454
3846
|
/** The extractor cannot derive this. An adapter that has the SDL and knows
|
|
3455
3847
|
* which field the resolver serves fills it in. */
|
|
3456
3848
|
graphqlDeclaredContract?: GraphqlDeclaredContract;
|
|
@@ -3473,6 +3865,13 @@ interface RawCodeStructure {
|
|
|
3473
3865
|
* `unreadOutcome` gap, so no checker counts it against the unit.
|
|
3474
3866
|
*/
|
|
3475
3867
|
unreadBinding?: string;
|
|
3868
|
+
/**
|
|
3869
|
+
* Why the adapter could not read this unit's body, when reading it threw.
|
|
3870
|
+
* The summary keeps the unit's identity and binding, and the reason comes
|
|
3871
|
+
* out as an `unreadOutcome` gap, so an empty body is not taken for one
|
|
3872
|
+
* that does nothing.
|
|
3873
|
+
*/
|
|
3874
|
+
readFailure?: string;
|
|
3476
3875
|
/**
|
|
3477
3876
|
* Readings the adapter passed along without collapsing. This module writes
|
|
3478
3877
|
* the reason for any that came back unreadable or ambiguous. Written and
|
|
@@ -3508,4 +3907,4 @@ declare function rawConditionToPredicate(c: RawCondition): Predicate;
|
|
|
3508
3907
|
declare function effectToIR(effect: RawEffect): Effect;
|
|
3509
3908
|
declare function paramToInput(param: RawParameter): Input;
|
|
3510
3909
|
|
|
3511
|
-
export { type AccessRecognizer, type AdapterCodeStamp, type AdapterStamp, type AstCapableOps, type BindingExtraction, type BodyContent, type CacheAttribution, type CacheDiagnostic, type CacheInput, type CacheLayer, type CacheLookup, type CallOps, type CaseGroup, type ChannelSource, type ChosenReading, type ConditionHandle, type ConditionInfo, type ConditionSource, type ConstructedFrom, type ContractPattern, type DeclaredBinding, type DeclaredBy, type DeclaredMatch, type DefaultedReading, type DiscoveredCustomUnit, type DiscoveredSubUnit, type DiscoveredSubUnitParent, type DiscoveryMatch, type DiscoveryPattern, type EffectArg, type EmptyStage, type ExitKind, type ExtractionReport, type ExtractorOptions, type FailureDelivery, type HealthCheck, type HealthViolation, type HelperDeclarations, type HelperSearch, type HelperSink, type HelperValue, IdMap, IdSet, type Identified, type InputMappingPattern, type InputRead, type InvocationRecognizer, type LanguageAdapter, type LoweredStatementParts, MAX_ENTRIES, MAX_PATHS, type ModuleInitOptions, type NodeVisitor, type OpsCarrier, type PackDeclarations, type PackFailure, type PackFunnel, type PackGradient, type PackTally, type PartialPlan, PathBudgetExceeded, type PatternPack, type ProjectHelper, type ProjectHelpers, type RawBranch, type RawCodeStructure, type RawCondition, type RawDeclaredContract, type RawDependencyCall, type RawEffect, type RawParameter, type RawTerminal, type Reading, type ReceiverOrigin, type RegistrationHelper, type ResponsePropertyMapping, type ResponsePropertyMeaning, type RootRecord, SKIP_CHILDREN, type SourceRange, type StatementBlock, type StructuredPathConditionsInput, type StructuredPathConditionsResult, type StructuredStatement, type TerminalExtraction, type TerminalMatch, type TerminalPattern, type Timer, type TimingReport, type TransparentWrapper, UnmodeledFlow, type UnsettledName, type ValueEntry, type ValueOps, type
|
|
3910
|
+
export { type AccessRecognizer, type AdapterCodeStamp, type AdapterStamp, type ArgumentParser, type AstCapableOps, type BindingExtraction, type BodyContent, type CacheAttribution, type CacheDiagnostic, type CacheInput, type CacheLayer, type CacheLookup, type CallOps, type CaseGroup, type ChannelSource, type ChildrenOf, type ChosenReading, type ClassOps, type ConditionHandle, type ConditionInfo, type ConditionSource, type ConstructedFrom, type ContractPattern, type DeclaredBinding, type DeclaredBy, type DeclaredMatch, type DeclaredModule, type DeclaredStatusDecorators, type DefaultedReading, type DiscoveredCustomUnit, type DiscoveredSubUnit, type DiscoveredSubUnitParent, type DiscoveryMatch, type DiscoveryPattern, type EffectArg, type EmptyStage, EnclosingNodes, type ExitKind, type ExtractionConfig, type ExtractionReport, type ExtractorOptions, type FailureDelivery, type GlobalPrefixCall, type HandOffSite, type HealthCheck, type HealthViolation, type HelperDeclarations, type HelperSearch, type HelperSink, type HelperValue, IdMap, IdSet, type Identified, type InputMappingPattern, type InputRead, type InvocationRecognizer, type KeepsArms, KeptParses, type LanguageAdapter, type LoweredStatementParts, MAX_ENTRIES, MAX_HELPER_PATHS, MAX_PATHS, MODULE_SURFACE_RECOGNITION, type ModuleInitOptions, type NodeVisitor, type OpsCarrier, type PackDeclarations, type PackFailure, type PackFunnel, type PackGradient, type PackTally, type ParameterSupplier, type ParsedNode, type PartialPlan, PathBudgetExceeded, type PatternPack, type ProjectHelper, type ProjectHelpers, type RawBranch, type RawCodeStructure, type RawCondition, type RawDeclaredContract, type RawDependencyCall, type RawEffect, type RawParameter, type RawProvenance, type RawTerminal, type Reading, type ReceiverOrigin, type RedirectDelivery, type RedirectOption, type RegistrationHelper, type ResponsePropertyMapping, type ResponsePropertyMeaning, type RootRecord, type RouteVersioning, SKIP_CHILDREN, type SettledModule, type SourceRange, type SourceSpelling, type StatedSlot, type StatementBlock, type StructuredPathConditionsInput, type StructuredPathConditionsResult, type StructuredStatement, type TerminalExtraction, type TerminalMatch, type TerminalPattern, type TestCaseMatch, type Timer, type TimingReport, type TransparentWrapper, type UnitRecord, UnmodeledFlow, type UnsettledName, type ValueEntry, type ValueOps, type VersionPlacement, type WalkEnd, type WrapperMethodRegistration, type WrapperOptionRegistration, type WrapperRegistration, absentReading, ambiguousReading, andThenReading, assembleSummary, assessConfidence, buildUngatedExtractionReport, commonDirectoryOf, composeWrappers, computeContentHash, computeDistHashFrom, configuredCallOption, createAdapterStamp, createCacheLayer, createPackTallies, createTimer, detectGaps, effectToIR, emptyTally, enumerateOrDegrade, enumerateStructuredPaths, evaluatePackHealth, extractionConfigStamp, firstWrittenReading, formatPackHealth, guardsHoldOn, helperPathsOnVariables, httpRouteDiscovery, isListedTestFile, makeIgnoredDirectory, makeTransitionId, mapReading, markReturnsAsExitCode, matchesTestFileName, mergeReadShapes, moduleInitStructure, moduleOfFile, noopTimer, packGradients, paramToInput, projectFileStamp, rawConditionToPredicate, recordPackFailure, redirectDeliveryWhenSet, registrationHelperDiscovery, routeHelperIndex, runDigest, runsBefore, scopeOption, settleModules, sharedGatingConditions, sourceRefsOf, splitAtHandOffs, stampMayMissAWrite, stampModuleImports, stampModules, storageSystemOption, summaryCountsByPack, tallyUnit, terminalToOutput, throughHelper, unreadableReading, unwrapJsonStringify, valueToReadFurtherFrom, walkDescendants, wrapperDiscovery, writtenReading };
|