@orkestrel/probe 0.0.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/LICENSE +21 -0
- package/README.md +81 -0
- package/dist/bin/main.js +14 -0
- package/dist/bin/main.js.map +1 -0
- package/dist/src/core/index.cjs +735 -0
- package/dist/src/core/index.cjs.map +1 -0
- package/dist/src/core/index.d.cts +1134 -0
- package/dist/src/core/index.d.ts +1134 -0
- package/dist/src/core/index.js +706 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/server/index.cjs +2346 -0
- package/dist/src/server/index.cjs.map +1 -0
- package/dist/src/server/index.d.cts +941 -0
- package/dist/src/server/index.d.ts +941 -0
- package/dist/src/server/index.js +2321 -0
- package/dist/src/server/index.js.map +1 -0
- package/package.json +131 -0
|
@@ -0,0 +1,941 @@
|
|
|
1
|
+
import { Case } from '@orkestrel/probe';
|
|
2
|
+
import { Case as Case_2 } from '@orkestrel/probe';
|
|
3
|
+
import { Check } from '@orkestrel/probe';
|
|
4
|
+
import { Check as Check_2 } from '@orkestrel/probe';
|
|
5
|
+
import { Claim } from '@orkestrel/probe';
|
|
6
|
+
import { EmitterInterface } from '@orkestrel/emitter';
|
|
7
|
+
import { EventEmitter } from 'node:events';
|
|
8
|
+
import { ProbeEventMap } from '@orkestrel/probe';
|
|
9
|
+
import { ProbeInterface } from '@orkestrel/probe';
|
|
10
|
+
import { ProbeOptions } from '@orkestrel/probe';
|
|
11
|
+
import { Project } from '@orkestrel/probe';
|
|
12
|
+
import { Project as Project_2 } from '@orkestrel/probe';
|
|
13
|
+
import { Stage } from '@orkestrel/probe';
|
|
14
|
+
import { Stage as Stage_2 } from '@orkestrel/probe';
|
|
15
|
+
import { Toolchain } from '@orkestrel/probe';
|
|
16
|
+
import type * as TypeScript from 'typescript';
|
|
17
|
+
import { Verdict } from '@orkestrel/probe';
|
|
18
|
+
import type * as VitestNode from 'vitest/node';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Records the listeners one emitter carries for a set of events.
|
|
22
|
+
*
|
|
23
|
+
* @param emitter - The emitter to read
|
|
24
|
+
* @param events - The event names to record
|
|
25
|
+
* @returns The listeners each named event carries at the moment of the call
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const capture = captureListeners(process, ['SIGTERM'])
|
|
30
|
+
* capture.get('SIGTERM')?.length === process.listenerCount('SIGTERM') // true
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function captureListeners(emitter: EventEmitter, events: readonly string[]): ListenerCapture;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Computes the canonical digest of one value as it stands in a target workspace.
|
|
37
|
+
*
|
|
38
|
+
* @remarks
|
|
39
|
+
* Digests the normalized value rather than the value itself, so one commit read at two absolute
|
|
40
|
+
* roots produces one digest and a digest carries no host path. The result is the leading 32 hex
|
|
41
|
+
* characters of a SHA-256 over the normalized JSON.
|
|
42
|
+
*
|
|
43
|
+
* @param workspace - The target workspace root the value's paths are read against
|
|
44
|
+
* @param value - The value to digest
|
|
45
|
+
* @returns 32 lowercase hex characters
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* computeDigest('/srv/checkout', { strict: true }).length // 32
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function computeDigest(workspace: string, value: unknown): string;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Creates a fresh sibling identity while preserving a test's resolution directory.
|
|
56
|
+
*
|
|
57
|
+
* @param workspace - The target workspace root
|
|
58
|
+
* @param path - The workspace-relative test path
|
|
59
|
+
* @param revision - The fresh revision identity
|
|
60
|
+
* @returns An absolute sibling file path
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```ts
|
|
64
|
+
* relativeWorkspaceFile(
|
|
65
|
+
* '/srv/checkout',
|
|
66
|
+
* createRevisionFile('/srv/checkout', 'tmp/probe/greeting.test.ts', '4821-9f0c'),
|
|
67
|
+
* )
|
|
68
|
+
* // 'tmp/probe/greeting.test.probe-4821-9f0c.ts'
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare function createRevisionFile(workspace: string, path: string, revision: string): string;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Normalizes a caught or foreign error into readable text.
|
|
75
|
+
*
|
|
76
|
+
* @param value - The value to describe
|
|
77
|
+
* @returns Its message when present, or its string representation
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* describeUnknown(new Error('The lint stage has been destroyed'))
|
|
82
|
+
* // 'The lint stage has been destroyed'
|
|
83
|
+
* describeUnknown(17) // '17'
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export declare function describeUnknown(value: unknown): string;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Names every draft member of a claim-shaped value whose `path` this package's guard refuses.
|
|
90
|
+
*
|
|
91
|
+
* @remarks
|
|
92
|
+
* The published claim schema constrains `Draft.path` to a non-empty string and nothing else, while
|
|
93
|
+
* `isDraft` also refuses an absolute path and one that escapes the workspace. That one member is
|
|
94
|
+
* the whole of the difference between the advertised contract and the enforced one, so a caller
|
|
95
|
+
* refused after satisfying the schema is refused here and nowhere else. The whole input must first
|
|
96
|
+
* satisfy that schema. Each draft is then tested with `isDraft` itself rather than with a second
|
|
97
|
+
* copy of its rule. Reports nothing for a value carrying no draft member, including one refused for
|
|
98
|
+
* a member this contract does not declare.
|
|
99
|
+
*
|
|
100
|
+
* This function lives in the server helpers rather than in core: core's leaf pair, `helpers.ts` and
|
|
101
|
+
* `validators.ts`, may not consume the shapes module this function reads `CLAIM_SHAPE` from, and
|
|
102
|
+
* `ProbeServer` is the sole consumer of the result it returns.
|
|
103
|
+
*
|
|
104
|
+
* @param value - The rejected tool input
|
|
105
|
+
* @returns The dotted member names, in `case` then `control` order, or an empty list
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* const test = { path: 'tmp/probe/greeting.test.ts', text: '' }
|
|
110
|
+
* findRefusedPaths({
|
|
111
|
+
* project: 'tsconfig.json',
|
|
112
|
+
* case: { files: [{ path: '../../etc/hosts', text: '' }], test },
|
|
113
|
+
* control: { files: [], test, stage: 'type', reason: 'must not compile' },
|
|
114
|
+
* })
|
|
115
|
+
* // ['case.files.0.path']
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export declare function findRefusedPaths(value: unknown): readonly string[];
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Selects the Language Server Protocol language identifier for a source path.
|
|
122
|
+
*
|
|
123
|
+
* @param path - The source path whose extension selects the language
|
|
124
|
+
* @returns The matching JavaScript or TypeScript language identifier
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* inferDocumentLanguage('src/core/greeting.ts') // 'typescript'
|
|
129
|
+
* inferDocumentLanguage('src/browser/Panel.tsx') // 'typescriptreact'
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export declare function inferDocumentLanguage(path: string): string;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Selects the Vitest project whose environment matches one test path.
|
|
136
|
+
*
|
|
137
|
+
* @remarks
|
|
138
|
+
* There is no root-project fallback. A path no configured project collects returns `undefined`,
|
|
139
|
+
* and the runtime stage refuses that claimant test with `code: 'missing'` rather than running it
|
|
140
|
+
* somewhere the workspace never configured.
|
|
141
|
+
*
|
|
142
|
+
* @param path - The workspace-relative test path
|
|
143
|
+
* @returns The matching project's name, or `undefined` when no configured project collects the path
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```ts
|
|
147
|
+
* inferTestProject('tmp/probe/greeting.test.ts') // 'probe'
|
|
148
|
+
* inferTestProject('tests/src/server/helpers.test.ts') // 'src:server'
|
|
149
|
+
* inferTestProject('tests/config.test.ts') // undefined
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
export declare function inferTestProject(path: string): string | undefined;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Selects the scoped TypeScript project for one candidate draft path.
|
|
156
|
+
*
|
|
157
|
+
* @param path - The workspace-relative candidate draft path
|
|
158
|
+
* @returns The workspace-relative scoped project path
|
|
159
|
+
* @throws When the path does not name a configured source or application environment
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* inferTypeProject('src/core/greeting.ts') // 'configs/src/tsconfig.core.json'
|
|
164
|
+
* inferTypeProject('tests/src/core/greeting.test.ts')
|
|
165
|
+
* // throws: Cannot infer a scoped TypeScript project for tests/src/core/greeting.test.ts
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
export declare function inferTypeProject(path: string): string;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Carries one queued inspection: the case a stage reads and the claim it belongs to.
|
|
172
|
+
*
|
|
173
|
+
* @remarks
|
|
174
|
+
* The coordinator admits one of these per stage at a time. Every stage reads `subject`; the type
|
|
175
|
+
* stage also reads `claim.project`, and the runtime stage reports `claim` when its deadline fires.
|
|
176
|
+
* A coordinator such as `Probe` mints an inspection when it admits a claim to a stage.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```ts
|
|
180
|
+
* const inspection: Inspection = { subject: claim.case, claim }
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export declare interface Inspection {
|
|
184
|
+
/** The candidate drafts and test one stage inspects. */
|
|
185
|
+
readonly subject: Case;
|
|
186
|
+
/** The claim the subject belongs to. */
|
|
187
|
+
readonly claim: Claim;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Inspects virtual documents through one resident Oxlint language server.
|
|
192
|
+
*
|
|
193
|
+
* @remarks
|
|
194
|
+
* Construction starts the target workspace's Oxlint binary with its Language Server Protocol
|
|
195
|
+
* mode. Each inspection opens the supplied text by URI, waits for published diagnostics, and
|
|
196
|
+
* closes the document without writing it to disk.
|
|
197
|
+
*
|
|
198
|
+
* Teardown is bounded at both ends. Warming waits for the server's `initialize` response and the
|
|
199
|
+
* ending waits for its `shutdown` reply, and the protocol leaves both answers to the server, so
|
|
200
|
+
* `destroy` bounds each exchange and takes the ending back with a signal when the bound passes.
|
|
201
|
+
*
|
|
202
|
+
* The URI is the path the candidate declared, so the candidate receives exactly the rule set the
|
|
203
|
+
* workspace's own lint gate applies to that path, including an override anchored to one directory,
|
|
204
|
+
* one file name, or one exact file. A path the workspace's version-control ignore files exclude is
|
|
205
|
+
* a path that gate never lints, and this stage reports the same nothing for it. Reuse of one
|
|
206
|
+
* declared path across inspections is what the caller's own serialization protects: the stage
|
|
207
|
+
* refuses a second inspection of a path it already has open rather than answering either one with
|
|
208
|
+
* the other's diagnostics.
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* ```ts
|
|
212
|
+
* const stage = new LintStage('/srv/checkout')
|
|
213
|
+
* const check = await stage.inspect(subject)
|
|
214
|
+
* await stage.destroy()
|
|
215
|
+
* ```
|
|
216
|
+
*/
|
|
217
|
+
export declare class LintStage implements StageInterface {
|
|
218
|
+
#private;
|
|
219
|
+
/**
|
|
220
|
+
* Starts warming the target workspace's Oxlint language server.
|
|
221
|
+
*
|
|
222
|
+
* @param workspace - The target workspace root. Default: the current working directory
|
|
223
|
+
*/
|
|
224
|
+
constructor(workspace?: string);
|
|
225
|
+
get stage(): Stage_2;
|
|
226
|
+
get progress(): number;
|
|
227
|
+
inspect(subject: Case_2): Promise<Check_2>;
|
|
228
|
+
destroy(): Promise<void>;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Holds the listeners one emitter carried for a set of events at the moment it was captured.
|
|
233
|
+
*
|
|
234
|
+
* @remarks
|
|
235
|
+
* A capture is the before half of a listener diff. `captureListeners` takes one, and
|
|
236
|
+
* `releaseListeners` removes whatever the emitter has gained since. Identity is what the pair
|
|
237
|
+
* compares, so a listener a capture holds survives the release whatever it is named.
|
|
238
|
+
*
|
|
239
|
+
* The pair reads a gain as the callee's own, so it binds its caller to a window nothing else can
|
|
240
|
+
* attach in. Where a caller cannot promise that window, hold each handler as a field and remove it
|
|
241
|
+
* by reference instead.
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```ts
|
|
245
|
+
* const capture: ListenerCapture = new Map([['SIGTERM', process.listeners('SIGTERM')]])
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
export declare type ListenerCapture = ReadonlyMap<string, readonly Function[]>;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Loads one installed tool module from a target workspace.
|
|
252
|
+
*
|
|
253
|
+
* @param workspace - The target workspace root
|
|
254
|
+
* @param specifier - The module specifier to load
|
|
255
|
+
* @returns The installed module
|
|
256
|
+
* @throws When the workspace cannot load the module
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```ts
|
|
260
|
+
* const typescript = loadWorkspaceModule(process.cwd(), 'typescript')
|
|
261
|
+
* console.log(typescript.version)
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
export declare function loadWorkspaceModule(workspace: string, specifier: 'typescript'): typeof TypeScript;
|
|
265
|
+
|
|
266
|
+
export declare function loadWorkspaceModule(workspace: string, specifier: 'vitest/node'): typeof VitestNode;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Reports whether a path is a workspace module Vitest can cache.
|
|
270
|
+
*
|
|
271
|
+
* @param path - The candidate file path
|
|
272
|
+
* @returns True for script, TypeScript, Vue, and JSON modules; false otherwise
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```ts
|
|
276
|
+
* matchesWorkspaceModule('src/core/greeting.ts') // true
|
|
277
|
+
* matchesWorkspaceModule('src/styles/tokens.css') // false
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
280
|
+
export declare function matchesWorkspaceModule(path: string): boolean;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Rewrites one path into the forward-slash spelling this package compares and reports paths in.
|
|
284
|
+
*
|
|
285
|
+
* @remarks
|
|
286
|
+
* Windows reports a path with backslashes and accepts either separator, so two spellings of one
|
|
287
|
+
* file compare unequal until they are rewritten. Every path this package keys a map on, matches a
|
|
288
|
+
* prefix against, or hands a caller passes through here first.
|
|
289
|
+
*
|
|
290
|
+
* @param path - The path to rewrite
|
|
291
|
+
* @returns The same path with every backslash replaced by a forward slash
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```ts
|
|
295
|
+
* normalizePath('src\\core\\greeting.ts') // 'src/core/greeting.ts'
|
|
296
|
+
* normalizePath('src/core/greeting.ts') // 'src/core/greeting.ts'
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
export declare function normalizePath(path: string): string;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Rewrites every workspace-contained absolute path in a value to its workspace-relative form and
|
|
303
|
+
* sorts every record's keys.
|
|
304
|
+
*
|
|
305
|
+
* @remarks
|
|
306
|
+
* A parsed TypeScript project carries the absolute root it was parsed at, so the same commit
|
|
307
|
+
* checked out at two paths produces two values that describe one configuration. Rewriting those
|
|
308
|
+
* members makes the value portable and stops a host path leaking into anything derived from it. A
|
|
309
|
+
* path that escapes the workspace is left as it stands, because rewriting it would name a file
|
|
310
|
+
* outside the tree by a relative spelling. Key order is the parser's, not the configuration's, so
|
|
311
|
+
* sorting removes a difference that means nothing.
|
|
312
|
+
*
|
|
313
|
+
* @param workspace - The target workspace root
|
|
314
|
+
* @param value - The value to rewrite
|
|
315
|
+
* @returns The value with contained absolute paths made relative and every record key sorted
|
|
316
|
+
*
|
|
317
|
+
* @example
|
|
318
|
+
* ```ts
|
|
319
|
+
* normalizeValue('/srv/checkout', { rootDir: '/srv/checkout/src/core', strict: true })
|
|
320
|
+
* // { rootDir: 'src/core', strict: true }
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
export declare function normalizeValue(workspace: string, value: unknown): unknown;
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Holds the candidate drafts one inspection substitutes for the files a tool would read from disk.
|
|
327
|
+
*
|
|
328
|
+
* @remarks
|
|
329
|
+
* One overlay belongs to one inspection: the inspection creates it, records every candidate it
|
|
330
|
+
* carries, and clears it when the inspection ends. Each stage adapts the same set to the host its
|
|
331
|
+
* own tool expects rather than sharing one filesystem across tools. A fresh identity per instance
|
|
332
|
+
* is what makes a resident tool re-read a path this overlay holds, so two inspections that supply
|
|
333
|
+
* different text for one path never share a cached answer.
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```ts
|
|
337
|
+
* const overlay = new Overlay()
|
|
338
|
+
* overlay.set('/srv/checkout/src/core/greeting.ts', "export const GREETING = 'hi'\n")
|
|
339
|
+
* console.log(overlay.text('/srv/checkout/src/core/greeting.ts'))
|
|
340
|
+
* overlay.clear()
|
|
341
|
+
* ```
|
|
342
|
+
*/
|
|
343
|
+
export declare class Overlay implements OverlayInterface {
|
|
344
|
+
#private;
|
|
345
|
+
get revision(): string;
|
|
346
|
+
get paths(): readonly string[];
|
|
347
|
+
/**
|
|
348
|
+
* Records one candidate's text against the absolute path it stands in for.
|
|
349
|
+
*
|
|
350
|
+
* @param path - The absolute path the candidate replaces
|
|
351
|
+
* @param text - The candidate's full contents
|
|
352
|
+
* @returns Nothing
|
|
353
|
+
*/
|
|
354
|
+
set(path: string, text: string): void;
|
|
355
|
+
/**
|
|
356
|
+
* Reads the candidate text recorded for one absolute path.
|
|
357
|
+
*
|
|
358
|
+
* @param path - The absolute path to read
|
|
359
|
+
* @returns The recorded text, or `undefined` when this overlay holds no candidate there
|
|
360
|
+
*/
|
|
361
|
+
text(path: string): string | undefined;
|
|
362
|
+
/**
|
|
363
|
+
* Checks whether a candidate sits beneath one directory.
|
|
364
|
+
*
|
|
365
|
+
* @remarks
|
|
366
|
+
* The answer is derived from the paths the overlay holds rather than stored, so it stops being
|
|
367
|
+
* true exactly when the inspection that declared those candidates clears them. Both sides pass
|
|
368
|
+
* through `normalizePath` first, because a tool that normalizes its own paths asks about a
|
|
369
|
+
* directory in a spelling the recorded path may not share.
|
|
370
|
+
*
|
|
371
|
+
* @param directory - The absolute directory path to check
|
|
372
|
+
* @returns True if a candidate path sits beneath the directory; false otherwise
|
|
373
|
+
*/
|
|
374
|
+
covers(directory: string): boolean;
|
|
375
|
+
/**
|
|
376
|
+
* Releases every candidate.
|
|
377
|
+
*
|
|
378
|
+
* @returns Nothing
|
|
379
|
+
*/
|
|
380
|
+
clear(): void;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Holds the candidate drafts one inspection substitutes for the files a tool would read from disk.
|
|
385
|
+
*
|
|
386
|
+
* @remarks
|
|
387
|
+
* A stage records every candidate the inspection carries before it reads any of them, and clears
|
|
388
|
+
* the set when the inspection ends, whatever ended it. The entity names no tool: each stage adapts
|
|
389
|
+
* one overlay to the host its own tool expects, so a language service, a document protocol, and a
|
|
390
|
+
* module resolver read one candidate set through their own adapters rather than through one shared
|
|
391
|
+
* filesystem. Paths are absolute and the stage resolves them, because only the stage knows the
|
|
392
|
+
* workspace a candidate's declared path is relative to. `revision` identifies the set, so a
|
|
393
|
+
* resident tool that caches by version reads fresh text for a path this overlay holds and reads
|
|
394
|
+
* disk again after `clear`.
|
|
395
|
+
*
|
|
396
|
+
* Mint one overlay per inspection and release it when that inspection ends. An instance shared
|
|
397
|
+
* across inspections keeps the identity a resident tool caches against, so the second inspection
|
|
398
|
+
* reads the first one's answer as a fresh one. `Overlay` implements this contract.
|
|
399
|
+
*
|
|
400
|
+
* @example
|
|
401
|
+
* ```ts
|
|
402
|
+
* const overlay: OverlayInterface = new Overlay()
|
|
403
|
+
* overlay.set('/srv/checkout/src/core/greeting.ts', "export const GREETING = 'hi'\n")
|
|
404
|
+
* overlay.covers('/srv/checkout/src/core') // true
|
|
405
|
+
* overlay.clear()
|
|
406
|
+
* ```
|
|
407
|
+
*/
|
|
408
|
+
export declare interface OverlayInterface {
|
|
409
|
+
/** Identity of the candidate set this overlay holds. */
|
|
410
|
+
readonly revision: string;
|
|
411
|
+
/** Absolute path of every candidate this overlay holds. */
|
|
412
|
+
readonly paths: readonly string[];
|
|
413
|
+
/**
|
|
414
|
+
* Records one candidate's text against the absolute path it stands in for.
|
|
415
|
+
*
|
|
416
|
+
* @param path - The absolute path the candidate replaces
|
|
417
|
+
* @param text - The candidate's full contents
|
|
418
|
+
* @returns Nothing
|
|
419
|
+
*/
|
|
420
|
+
set(path: string, text: string): void;
|
|
421
|
+
/**
|
|
422
|
+
* Reads the candidate text recorded for one absolute path.
|
|
423
|
+
*
|
|
424
|
+
* @param path - The absolute path to read
|
|
425
|
+
* @returns The recorded text, or `undefined` when this overlay holds no candidate there
|
|
426
|
+
*/
|
|
427
|
+
text(path: string): string | undefined;
|
|
428
|
+
/**
|
|
429
|
+
* Checks whether a candidate sits beneath one directory.
|
|
430
|
+
*
|
|
431
|
+
* @remarks
|
|
432
|
+
* A tool asking whether a directory exists is answered from disk first, so this reports only
|
|
433
|
+
* the directories the candidate set adds. A directory listing is a separate question and stays
|
|
434
|
+
* on disk: a candidate that entered one would outlive the inspection that declared it.
|
|
435
|
+
*
|
|
436
|
+
* @param directory - The absolute directory path to check
|
|
437
|
+
* @returns True if a candidate path sits beneath the directory; false otherwise
|
|
438
|
+
*/
|
|
439
|
+
covers(directory: string): boolean;
|
|
440
|
+
/**
|
|
441
|
+
* Releases every candidate.
|
|
442
|
+
*
|
|
443
|
+
* @returns Nothing
|
|
444
|
+
*/
|
|
445
|
+
clear(): void;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Reads a JSON-RPC frame's declared byte length.
|
|
450
|
+
*
|
|
451
|
+
* @param header - The frame header text without its terminating empty line
|
|
452
|
+
* @returns The non-negative content length, or `undefined` for an invalid header
|
|
453
|
+
*
|
|
454
|
+
* @example
|
|
455
|
+
* ```ts
|
|
456
|
+
* parseContentLength('Content-Length: 128') // 128
|
|
457
|
+
* parseContentLength('Content-Type: application/json') // undefined
|
|
458
|
+
* ```
|
|
459
|
+
*/
|
|
460
|
+
export declare function parseContentLength(header: string): number | undefined;
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Answers claims through resident TypeScript, Oxlint, and Vitest stages.
|
|
464
|
+
*
|
|
465
|
+
* @remarks
|
|
466
|
+
* Construction resolves the target workspace's toolchain and begins warming every stage. The boot
|
|
467
|
+
* controls mutate imported dependencies and refuse service unless the type and runtime stages
|
|
468
|
+
* report their respective changes. One queue per stage admits inspections in arrival order, one at
|
|
469
|
+
* a time, so a stage never serves two claims at once and the deadline covers active work rather
|
|
470
|
+
* than queue wait. Each active stage inspection has a coordinator-owned deadline. An expiry at any
|
|
471
|
+
* stage abandons that stage and replaces it before the next queued inspection begins, so one slow
|
|
472
|
+
* claim costs that claim rather than the process. A failed boot is replaced the same way: the next
|
|
473
|
+
* claim runs the controls again rather than inheriting a refusal.
|
|
474
|
+
*
|
|
475
|
+
* @example
|
|
476
|
+
* ```ts
|
|
477
|
+
* const probe = new Probe({ workspace: '/srv/checkout' })
|
|
478
|
+
* const verdict = await probe.prove(claim)
|
|
479
|
+
* await probe.destroy()
|
|
480
|
+
* ```
|
|
481
|
+
*/
|
|
482
|
+
export declare class Probe implements ProbeInterface {
|
|
483
|
+
#private;
|
|
484
|
+
/**
|
|
485
|
+
* Resolves the target toolchain and starts warming the resident stages.
|
|
486
|
+
*
|
|
487
|
+
* @param options - Workspace, deadline, and initial observation hooks
|
|
488
|
+
*/
|
|
489
|
+
constructor(options?: ProbeOptions);
|
|
490
|
+
get emitter(): EmitterInterface<ProbeEventMap>;
|
|
491
|
+
get toolchain(): Toolchain;
|
|
492
|
+
prove(claim: Claim): Promise<Verdict>;
|
|
493
|
+
destroy(): Promise<void>;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Serves one probe over this process's Model Context Protocol stdio transport.
|
|
498
|
+
*
|
|
499
|
+
* @remarks
|
|
500
|
+
* Construction creates the probe, publishes the `prove` tool, and binds the dual-era dispatcher to
|
|
501
|
+
* the stdio transport. The probe begins warming there, so a harness that spawns the entry pays
|
|
502
|
+
* arming while its client is still handshaking.
|
|
503
|
+
*
|
|
504
|
+
* `start` seizes standard input and registers the signals a harness ends a child with, and records
|
|
505
|
+
* whether standard input was already flowing. Every listener it attaches is held as a field, and
|
|
506
|
+
* `destroy` removes exactly those by reference, so a listener a host registers while this server is
|
|
507
|
+
* serving is still attached and still fires afterwards. The transport reads a stream this server
|
|
508
|
+
* owns rather than this process's standard input, which is what makes that possible: the
|
|
509
|
+
* transport's own listeners land on that stream, and the only listeners this server ever puts on
|
|
510
|
+
* `process.stdin` are the `data`, `close`, and `error` forwarders into it. `destroy` pauses the
|
|
511
|
+
* stream only when this server is what set it flowing and nothing else is reading it, so a process
|
|
512
|
+
* that outlives this server reads its own standard input again and receives its own signals.
|
|
513
|
+
* Teardown removes the signal handlers first: it takes seconds when a boot is in flight, and a
|
|
514
|
+
* harness that signals again means to kill rather than to queue.
|
|
515
|
+
*
|
|
516
|
+
* @example
|
|
517
|
+
* ```ts
|
|
518
|
+
* const server = new ProbeServer({ workspace: process.cwd() })
|
|
519
|
+
* server.start()
|
|
520
|
+
* await server.destroy()
|
|
521
|
+
* ```
|
|
522
|
+
*/
|
|
523
|
+
export declare class ProbeServer implements ProbeServerInterface {
|
|
524
|
+
#private;
|
|
525
|
+
/**
|
|
526
|
+
* Creates the probe this server publishes and binds it to this process's stdio transport.
|
|
527
|
+
*
|
|
528
|
+
* @param options - Workspace, deadline, and initial observation hooks for the probe it creates
|
|
529
|
+
*/
|
|
530
|
+
constructor(options?: ProbeOptions);
|
|
531
|
+
start(): void;
|
|
532
|
+
destroy(): Promise<void>;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Serves one probe over this process's Model Context Protocol stdio transport.
|
|
537
|
+
*
|
|
538
|
+
* @remarks
|
|
539
|
+
* The server owns the process it runs in. `start` seizes standard input and standard output for
|
|
540
|
+
* the transport and registers the termination handlers a harness signals, so a host that starts one
|
|
541
|
+
* has already given the process to it. `destroy` reverses all of that and tears the probe down with
|
|
542
|
+
* it, which is why there is no verb that stops serving and leaves the resident engines running: a
|
|
543
|
+
* probe nothing is reading from holds its resident tools for nobody.
|
|
544
|
+
*
|
|
545
|
+
* @example
|
|
546
|
+
* ```ts
|
|
547
|
+
* const server = new ProbeServer({ workspace: process.cwd() })
|
|
548
|
+
* server.start()
|
|
549
|
+
* await server.destroy()
|
|
550
|
+
* ```
|
|
551
|
+
*/
|
|
552
|
+
export declare interface ProbeServerInterface {
|
|
553
|
+
/**
|
|
554
|
+
* Serves the probe over this process's standard input and output.
|
|
555
|
+
*
|
|
556
|
+
* @remarks
|
|
557
|
+
* Reads newline-delimited JSON requests from standard input, and answers a `SIGINT` or a
|
|
558
|
+
* `SIGTERM` by destroying the server. Calling this on a server already serving does nothing.
|
|
559
|
+
* Calling it after teardown begins throws a claimant-owned `destroyed` failure.
|
|
560
|
+
*
|
|
561
|
+
* @returns Nothing
|
|
562
|
+
* @throws When this call comes after teardown begins
|
|
563
|
+
*/
|
|
564
|
+
start(): void;
|
|
565
|
+
/**
|
|
566
|
+
* Releases the transport, the process listeners, and the probe behind them.
|
|
567
|
+
*
|
|
568
|
+
* @remarks
|
|
569
|
+
* Settling is idempotent: a call made while teardown is running joins it and returns the same
|
|
570
|
+
* promise, and a call made afterwards returns that settled promise. The server removes exactly the
|
|
571
|
+
* listeners it attached, holding each one as a field rather than choosing by absence from a
|
|
572
|
+
* capture, so a host that keeps running after this call reads its own standard input again and
|
|
573
|
+
* receives its own signals, and a listener the host registered while
|
|
574
|
+
* the server was serving is still attached and still fires. That covers the stream's flow as
|
|
575
|
+
* well as its listeners: standard input is left flowing when it was already flowing before
|
|
576
|
+
* `start` and when something else is reading it at release, and a stream nothing had read yet
|
|
577
|
+
* and nothing else reads is paused.
|
|
578
|
+
*
|
|
579
|
+
* @returns A promise that settles after the probe releases its resident engines
|
|
580
|
+
*/
|
|
581
|
+
destroy(): Promise<void>;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Reads one installed package manifest from the target workspace.
|
|
586
|
+
*
|
|
587
|
+
* @param workspace - The target workspace root
|
|
588
|
+
* @param name - The installed package name
|
|
589
|
+
* @returns The manifest's absolute path and parsed record
|
|
590
|
+
* @throws When the package cannot be resolved, read, parsed, or does not publish a record manifest
|
|
591
|
+
*
|
|
592
|
+
* @example
|
|
593
|
+
* ```ts
|
|
594
|
+
* const manifest = readWorkspaceManifest(process.cwd(), 'typescript')
|
|
595
|
+
* console.log(manifest.contents.version)
|
|
596
|
+
* ```
|
|
597
|
+
*/
|
|
598
|
+
export declare function readWorkspaceManifest(workspace: string, name: string): WorkspaceManifest;
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Projects an absolute tool path into the workspace-relative form issues expose.
|
|
602
|
+
*
|
|
603
|
+
* @param workspace - The target workspace root
|
|
604
|
+
* @param file - The path a tool reported
|
|
605
|
+
* @returns A forward-slash workspace-relative path
|
|
606
|
+
*
|
|
607
|
+
* @example
|
|
608
|
+
* ```ts
|
|
609
|
+
* relativeWorkspaceFile('/srv/checkout', '/srv/checkout/src/core/greeting.ts')
|
|
610
|
+
* // 'src/core/greeting.ts'
|
|
611
|
+
* ```
|
|
612
|
+
*/
|
|
613
|
+
export declare function relativeWorkspaceFile(workspace: string, file: string): string;
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Removes every listener one emitter gained for the captured events since its capture.
|
|
617
|
+
*
|
|
618
|
+
* @remarks
|
|
619
|
+
* Compares identity rather than name, so a listener whose name a dependency changes between
|
|
620
|
+
* releases is still recognized and a listener that merely shares a name is still left alone. A
|
|
621
|
+
* listener the capture already held survives, and a listener the capture held that has since been
|
|
622
|
+
* removed is not restored.
|
|
623
|
+
*
|
|
624
|
+
* A gain is not evidence of who caused it, so this reads every gain as the callee's. Call it only
|
|
625
|
+
* across a window nothing else can attach in — a synchronous call, or a call whose handlers land
|
|
626
|
+
* before its first await and that is released as it returns — because a listener anyone else
|
|
627
|
+
* attaches inside that window is removed with the rest. Where a caller cannot promise that window,
|
|
628
|
+
* hold each handler as a field and remove it by reference instead of capturing at all.
|
|
629
|
+
*
|
|
630
|
+
* @param emitter - The emitter to release
|
|
631
|
+
* @param capture - The listeners the emitter carried at capture time
|
|
632
|
+
* @returns Nothing
|
|
633
|
+
*
|
|
634
|
+
* @example
|
|
635
|
+
* ```ts
|
|
636
|
+
* const capture = captureListeners(process, ['SIGTERM'])
|
|
637
|
+
* process.on('SIGTERM', () => {})
|
|
638
|
+
* releaseListeners(process, capture)
|
|
639
|
+
* process.listenerCount('SIGTERM') === capture.get('SIGTERM')?.length // true
|
|
640
|
+
* ```
|
|
641
|
+
*/
|
|
642
|
+
export declare function releaseListeners(emitter: EventEmitter, capture: ListenerCapture): void;
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Resolves a package's portable JavaScript binary from the target workspace.
|
|
646
|
+
*
|
|
647
|
+
* @param workspace - The target workspace root
|
|
648
|
+
* @param name - The installed package name and binary key
|
|
649
|
+
* @returns The absolute JavaScript entry named by the package's `bin` field
|
|
650
|
+
* @throws When the package does not publish a binary under the requested name
|
|
651
|
+
*
|
|
652
|
+
* @example
|
|
653
|
+
* ```ts
|
|
654
|
+
* relativeWorkspaceFile(process.cwd(), resolveWorkspaceBinary(process.cwd(), 'oxlint'))
|
|
655
|
+
* // 'node_modules/oxlint/bin/oxlint'
|
|
656
|
+
* resolveWorkspaceBinary(process.cwd(), 'typescript')
|
|
657
|
+
* // throws: typescript does not publish the typescript binary
|
|
658
|
+
* ```
|
|
659
|
+
*/
|
|
660
|
+
export declare function resolveWorkspaceBinary(workspace: string, name: string): string;
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Resolves a path inside a target workspace and rejects traversal outside it.
|
|
664
|
+
*
|
|
665
|
+
* @remarks
|
|
666
|
+
* A native `ENAMETOOLONG` or NUL-byte `ERR_INVALID_ARG_VALUE` fault is a claimant refusal. This
|
|
667
|
+
* classifies the fault, not the author: a workspace nested deeply enough that this package's short
|
|
668
|
+
* generated names overflow the host limit also reads as a claimant refusal.
|
|
669
|
+
*
|
|
670
|
+
* @param workspace - The target workspace root
|
|
671
|
+
* @param target - A workspace-relative path
|
|
672
|
+
* @param mutate - If `true`, refuses a symbolic link in an existing descendant; if `false`,
|
|
673
|
+
* resolves lexically. Default: `false`
|
|
674
|
+
* @returns The absolute contained path
|
|
675
|
+
* @throws When the path resolves outside the workspace, mutation would cross a symbolic link, or
|
|
676
|
+
* the target tree cannot be inspected
|
|
677
|
+
*
|
|
678
|
+
* @example
|
|
679
|
+
* ```ts
|
|
680
|
+
* resolveWorkspaceFile('/srv/checkout', 'src/core/greeting.ts')
|
|
681
|
+
* // '/srv/checkout/src/core/greeting.ts'
|
|
682
|
+
* resolveWorkspaceFile('/srv/checkout', '../secrets.env')
|
|
683
|
+
* // throws: Path escapes the workspace: ../secrets.env
|
|
684
|
+
* ```
|
|
685
|
+
*/
|
|
686
|
+
export declare function resolveWorkspaceFile(workspace: string, target: string, mutate?: boolean): string;
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Resolves one installed module from the target workspace.
|
|
690
|
+
*
|
|
691
|
+
* @param workspace - The target workspace root
|
|
692
|
+
* @param specifier - The module specifier to resolve
|
|
693
|
+
* @returns The installed module entry path
|
|
694
|
+
* @throws When the workspace does not install the module
|
|
695
|
+
*
|
|
696
|
+
* @example
|
|
697
|
+
* ```ts
|
|
698
|
+
* resolveWorkspaceModule(process.cwd(), 'typescript/package.json') ===
|
|
699
|
+
* readWorkspaceManifest(process.cwd(), 'typescript').path // true
|
|
700
|
+
* ```
|
|
701
|
+
*/
|
|
702
|
+
export declare function resolveWorkspaceModule(workspace: string, specifier: string): string;
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* Inspects tests through one resident Vitest service from the target workspace.
|
|
706
|
+
*
|
|
707
|
+
* @remarks
|
|
708
|
+
* Construction starts Vitest with the threads pool and instruments each inline or function-declared
|
|
709
|
+
* project with a Vite plugin that reads the active inspection's candidate overlay. A selected
|
|
710
|
+
* string-declared project reports a workspace issue because its configuration carries no runtime
|
|
711
|
+
* overlay plugin. Every inspection writes one fresh sibling specification, invalidates each
|
|
712
|
+
* workspace module whose disk content or candidate revision changed, runs that specification,
|
|
713
|
+
* evicts its result, and deletes the file. Clearing the overlay makes the next snapshot differ from
|
|
714
|
+
* the candidate revision, so the next inspection invalidates that module and reads disk again.
|
|
715
|
+
*
|
|
716
|
+
* Vite retains one unresolved URL for every specification path, so the stage replaces its whole
|
|
717
|
+
* Vitest service after 64 specifications rather than deleting from each map that service owns. Any
|
|
718
|
+
* bound holds the retention flat, because the replacement releases everything the instance held,
|
|
719
|
+
* and 64 is the value chosen. The inspection that crosses the bound pays the replacement
|
|
720
|
+
* synchronously: it closes the resident service and warms a new one before it runs. On 2026-08-20,
|
|
721
|
+
* over this package's own workspace on the host `guides/probe.md` § Cost names, two runs of 66
|
|
722
|
+
* inspections put that one at 480 ms and 269 ms against median inspections of 156 ms and 155 ms, so
|
|
723
|
+
* budget one call in 64 at 110 ms to 330 ms above the rest.
|
|
724
|
+
*
|
|
725
|
+
* Every issue this stage emits names its party, and the stage emits an issue for every party
|
|
726
|
+
* `Party` declares. An `origin: 'claimant'` issue is a failure Vitest reported about the candidate.
|
|
727
|
+
* An `origin: 'workspace'` issue names the target tree: a project the root configuration declares
|
|
728
|
+
* as a path string, into which the stage can install no overlay, and a specification path that
|
|
729
|
+
* crosses a symbolic link, whose existing components this host cannot inspect, or whose directory
|
|
730
|
+
* the target tree blocks probe from creating. An `origin: 'instrument'` issue names this package's
|
|
731
|
+
* own machinery: a specification it could not write after its directory exists, or one it could
|
|
732
|
+
* not run, evict, or delete, in each case for a reason the target tree does not own, and a run
|
|
733
|
+
* that reported no test. An unmapped caller test and a test whose named project is absent are claimant failures with
|
|
734
|
+
* `code: 'missing'`, thrown rather than reported, because a test that never ran is no evidence
|
|
735
|
+
* about the candidate.
|
|
736
|
+
*
|
|
737
|
+
* The write path's physical-containment guarantee covers the claim inputs and the target tree as
|
|
738
|
+
* inspected. A concurrent process that mutates a path component between the final inspection and
|
|
739
|
+
* the write is outside that guarantee.
|
|
740
|
+
*
|
|
741
|
+
* @example
|
|
742
|
+
* ```ts
|
|
743
|
+
* const stage = new RuntimeStage('/srv/checkout')
|
|
744
|
+
* const check = await stage.inspect(subject)
|
|
745
|
+
* await stage.destroy()
|
|
746
|
+
* ```
|
|
747
|
+
*/
|
|
748
|
+
export declare class RuntimeStage implements StageInterface {
|
|
749
|
+
#private;
|
|
750
|
+
/**
|
|
751
|
+
* Starts warming the target workspace's Vitest service.
|
|
752
|
+
*
|
|
753
|
+
* @param workspace - The target workspace root. Default: the current working directory
|
|
754
|
+
*/
|
|
755
|
+
constructor(workspace?: string);
|
|
756
|
+
get stage(): Stage_2;
|
|
757
|
+
get progress(): number;
|
|
758
|
+
inspect(subject: Case_2): Promise<Check_2>;
|
|
759
|
+
destroy(): Promise<void>;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* Inspects one case with a resident workspace tool.
|
|
764
|
+
*
|
|
765
|
+
* @remarks
|
|
766
|
+
* Warming begins at construction. The `inspect` method awaits that one warm operation and reuses
|
|
767
|
+
* the resulting tool across calls. A stage serves one inspection at a time and admits none itself.
|
|
768
|
+
* Await an inspection before starting the next one, or admit through one queue per stage the way
|
|
769
|
+
* `Probe` does: a second concurrent call reaches the same resident tool and the same overlay,
|
|
770
|
+
* document, and specification state the first is still using. A stage never holds a later
|
|
771
|
+
* inspection behind an earlier one, so a caller that abandons an inspection at its own deadline
|
|
772
|
+
* can still use the stage. The `destroy` method permanently tears the stage down and releases
|
|
773
|
+
* every resource it owns.
|
|
774
|
+
*
|
|
775
|
+
* @example
|
|
776
|
+
* ```ts
|
|
777
|
+
* const check = await stage.inspect(subject)
|
|
778
|
+
* console.log(check.stage)
|
|
779
|
+
* await stage.destroy()
|
|
780
|
+
* ```
|
|
781
|
+
*/
|
|
782
|
+
export declare interface StageInterface {
|
|
783
|
+
/** The inspection this resident stage performs. */
|
|
784
|
+
readonly stage: Stage;
|
|
785
|
+
/**
|
|
786
|
+
* Claimant-owned progress the coordinator compares with its inspection snapshot.
|
|
787
|
+
*
|
|
788
|
+
* @remarks
|
|
789
|
+
* When claimant-owned work is admitted, raise `progress` before awaiting its result. When this
|
|
790
|
+
* stage later performs stage-owned awaited work, return `progress` to its pre-inspection reading
|
|
791
|
+
* before that work starts. `RuntimeStage` does this before eviction and cleanup, so an expiry
|
|
792
|
+
* during that work reads level with the coordinator's snapshot and is attributed to the
|
|
793
|
+
* instrument rather than to the claimant.
|
|
794
|
+
*/
|
|
795
|
+
readonly progress: number;
|
|
796
|
+
/**
|
|
797
|
+
* Inspects one case.
|
|
798
|
+
*
|
|
799
|
+
* @param subject - The candidate drafts and test to inspect
|
|
800
|
+
* @returns One outcome for this stage
|
|
801
|
+
* @throws When the resident tool cannot start or has already been destroyed
|
|
802
|
+
*/
|
|
803
|
+
inspect(subject: Case): Promise<Check>;
|
|
804
|
+
/**
|
|
805
|
+
* Tears down the resident tool and releases its resources.
|
|
806
|
+
*
|
|
807
|
+
* @remarks
|
|
808
|
+
* A stage abandons every inspection it holds rather than waiting behind one, so teardown never
|
|
809
|
+
* waits for an inspection to return. An abandoned inspection rejects, either at the stage's own
|
|
810
|
+
* guard or as the owned tool closes. Teardown is bounded whatever the resident tool does: a tool
|
|
811
|
+
* that answers neither its warming exchange nor its ending is signalled and released at the
|
|
812
|
+
* stage's own deadline. A coordinator replaces a stage whose worker no longer returns because
|
|
813
|
+
* teardown neither waits for an inspection nor waits past that deadline.
|
|
814
|
+
*
|
|
815
|
+
* @returns A promise that settles after the resident tool releases its resources
|
|
816
|
+
*/
|
|
817
|
+
destroy(): Promise<void>;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Inspects TypeScript source through resident language services from the target workspace.
|
|
822
|
+
*
|
|
823
|
+
* @remarks
|
|
824
|
+
* Construction starts loading the workspace's compiler and warming one service per project the
|
|
825
|
+
* workspace declares. A candidate draft is checked against the project a call names, or
|
|
826
|
+
* against its own scoped environment project when a call names none, while the test uses the root
|
|
827
|
+
* project. Disk snapshots use their modification time as the service version so dependency edits
|
|
828
|
+
* cannot leave a warm answer stale. Candidate text lives in an overlay the inspection owns, and
|
|
829
|
+
* the language-service host answers existence, reads, and versions from it, so a candidate that
|
|
830
|
+
* exists only as text is importable and a candidate that shadows a disk file is checked as the
|
|
831
|
+
* text the case supplied. A project outside the declared set holds one recycled slot, so a caller
|
|
832
|
+
* varying the project cannot grow the resident set. A language service checks one candidate
|
|
833
|
+
* synchronously, so the stage hands the host's event loop back at each candidate boundary: a
|
|
834
|
+
* caller's deadline is answered within one candidate's check rather than after the whole
|
|
835
|
+
* inspection, and an inspection abandoned at that deadline stops at the next boundary.
|
|
836
|
+
*
|
|
837
|
+
* @example
|
|
838
|
+
* ```ts
|
|
839
|
+
* const stage = new TypeStage('/srv/checkout')
|
|
840
|
+
* const check = await stage.inspect(subject, 'configs/src/tsconfig.core.json')
|
|
841
|
+
* await stage.destroy()
|
|
842
|
+
* ```
|
|
843
|
+
*/
|
|
844
|
+
export declare class TypeStage implements TypeStageInterface {
|
|
845
|
+
#private;
|
|
846
|
+
/**
|
|
847
|
+
* Starts warming the target workspace's TypeScript service.
|
|
848
|
+
*
|
|
849
|
+
* @param workspace - The target workspace root. Default: the current working directory
|
|
850
|
+
*/
|
|
851
|
+
constructor(workspace?: string);
|
|
852
|
+
get stage(): Stage_2;
|
|
853
|
+
get progress(): number;
|
|
854
|
+
/**
|
|
855
|
+
* Inspects one case, against a caller-named project where the caller names one.
|
|
856
|
+
*
|
|
857
|
+
* @remarks
|
|
858
|
+
* The `project` parameter is this stage's own, not the stage contract's: the lint and runtime
|
|
859
|
+
* stages read no project, so `StageInterface` declares one parameter and every caller that
|
|
860
|
+
* needs this one holds a `TypeStage`.
|
|
861
|
+
*
|
|
862
|
+
* @param subject - The candidate drafts and test to inspect
|
|
863
|
+
* @param project - The workspace-relative TypeScript project the candidate drafts are checked
|
|
864
|
+
* against. Default: the scoped project each candidate path infers
|
|
865
|
+
* @returns One outcome for this stage
|
|
866
|
+
* @throws When the resident compiler cannot start or the stage has already been destroyed
|
|
867
|
+
*/
|
|
868
|
+
inspect(subject: Case_2, project?: string): Promise<Check_2>;
|
|
869
|
+
/**
|
|
870
|
+
* Resolves one project to the path and digest this stage applies for it.
|
|
871
|
+
*
|
|
872
|
+
* @remarks
|
|
873
|
+
* Reads the parse this stage itself applies, filling its cache when the project is not already
|
|
874
|
+
* resident, so the reported digest is the configuration the inspection is judged under rather
|
|
875
|
+
* than a second parse a caller ran. The returned record is a value copy, so a later eviction
|
|
876
|
+
* does not move it.
|
|
877
|
+
*
|
|
878
|
+
* @param project - The workspace-relative TypeScript project to resolve
|
|
879
|
+
* @returns The resolved workspace-relative path and the digest of its compiler options
|
|
880
|
+
* @throws When the project escapes the workspace, cannot be parsed, or the stage has already
|
|
881
|
+
* been destroyed
|
|
882
|
+
*/
|
|
883
|
+
resolve(project: string): Promise<Project_2>;
|
|
884
|
+
destroy(): Promise<void>;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Inspects TypeScript source against a caller-named project and reports what that project is.
|
|
889
|
+
*
|
|
890
|
+
* @remarks
|
|
891
|
+
* The type stage carries members the shared stage contract cannot: the lint and runtime stages
|
|
892
|
+
* read no project, so a project parameter and a project lookup belong here rather than on
|
|
893
|
+
* `StageInterface`.
|
|
894
|
+
*
|
|
895
|
+
* @example
|
|
896
|
+
* ```ts
|
|
897
|
+
* const project = await stage.resolve('configs/src/tsconfig.core.json')
|
|
898
|
+
* const check = await stage.inspect(subject, project.path)
|
|
899
|
+
* ```
|
|
900
|
+
*/
|
|
901
|
+
export declare interface TypeStageInterface extends StageInterface {
|
|
902
|
+
/**
|
|
903
|
+
* Inspects one case, against a caller-named project where the caller names one.
|
|
904
|
+
*
|
|
905
|
+
* @param subject - The candidate drafts and test to inspect
|
|
906
|
+
* @param project - The workspace-relative TypeScript project the candidate drafts are checked
|
|
907
|
+
* against. Default: the scoped project each candidate path infers
|
|
908
|
+
* @returns One outcome for this stage
|
|
909
|
+
* @throws When the resident compiler cannot start or the stage has already been destroyed
|
|
910
|
+
*/
|
|
911
|
+
inspect(subject: Case, project?: string): Promise<Check>;
|
|
912
|
+
/**
|
|
913
|
+
* Resolves one project to the path and digest the stage applies for it.
|
|
914
|
+
*
|
|
915
|
+
* @param project - The workspace-relative TypeScript project to resolve
|
|
916
|
+
* @returns The resolved workspace-relative path and the digest of its compiler options
|
|
917
|
+
* @throws When the project escapes the workspace, cannot be parsed, or the stage has already
|
|
918
|
+
* been destroyed
|
|
919
|
+
*/
|
|
920
|
+
resolve(project: string): Promise<Project>;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/**
|
|
924
|
+
* Carries one parsed package manifest and the path it came from.
|
|
925
|
+
*
|
|
926
|
+
* @example
|
|
927
|
+
* ```ts
|
|
928
|
+
* const manifest: WorkspaceManifest = {
|
|
929
|
+
* path: '/srv/checkout/node_modules/typescript/package.json',
|
|
930
|
+
* contents: { version: '6.0.3' },
|
|
931
|
+
* }
|
|
932
|
+
* ```
|
|
933
|
+
*/
|
|
934
|
+
export declare interface WorkspaceManifest {
|
|
935
|
+
/** Absolute path of the package manifest. */
|
|
936
|
+
readonly path: string;
|
|
937
|
+
/** Parsed manifest record. */
|
|
938
|
+
readonly contents: Readonly<Record<string, unknown>>;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
export { }
|