@orkestrel/probe 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/core/index.d.cts +18 -4
- package/dist/src/core/index.d.ts +18 -4
- package/dist/src/server/index.cjs +398 -96
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +105 -3
- package/dist/src/server/index.d.ts +105 -3
- package/dist/src/server/index.js +399 -100
- package/dist/src/server/index.js.map +1 -1
- package/package.json +13 -12
package/dist/src/server/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
-
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { closeSync, constants, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
6
|
import { attempt, compileGuard, compileSchema, isArray, isRecord, schemaToParameters } from "@orkestrel/contract";
|
|
6
|
-
import { CLAIM_SHAPE, ProbeError, computeReceipt, createDestroyedError, formatCheck, formatSpecification, formatVerdict, isClaim, isDraft, isVerdict, matchesSpecification } from "../core/index.js";
|
|
7
|
+
import { CLAIM_SHAPE, ProbeError, computeReceipt, createDestroyedError, formatCheck, formatSpecification, formatVerdict, isClaim, isDraft, isProbeError, isVerdict, matchesSpecification } from "../core/index.js";
|
|
7
8
|
import { Emitter } from "@orkestrel/emitter";
|
|
8
9
|
import { createQueue } from "@orkestrel/queue";
|
|
9
10
|
import { createTimeout } from "@orkestrel/timeout";
|
|
10
11
|
import { spawn } from "node:child_process";
|
|
11
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
12
12
|
import { PassThrough } from "node:stream";
|
|
13
|
-
import {
|
|
13
|
+
import { setTimeout } from "node:timers/promises";
|
|
14
14
|
import { createMCPLegacy, createMCPServer } from "@orkestrel/mcp";
|
|
15
15
|
import { createStdioServer } from "@orkestrel/mcp/server";
|
|
16
16
|
import { createTool, createToolManager } from "@orkestrel/tool";
|
|
@@ -106,6 +106,46 @@ function resolveWorkspaceFile(workspace, target, mutate = false) {
|
|
|
106
106
|
return file;
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
109
|
+
* Overwrites a file that already exists, through a descriptor that refuses a symbolic link at the
|
|
110
|
+
* final component.
|
|
111
|
+
*
|
|
112
|
+
* @remarks
|
|
113
|
+
* A containment walk and the write that follows it are separate calls, so a process that swaps the
|
|
114
|
+
* final component between them decides where the bytes land. `writeFileSync` opens with the default
|
|
115
|
+
* `w` flag, which follows a symbolic link at that component and creates the file when it is absent,
|
|
116
|
+
* so the walk's reading does not bind the write. Opening `O_WRONLY | O_TRUNC | O_NOFOLLOW` moves
|
|
117
|
+
* that decision into the call that writes: a link at the final component refuses the open, and the
|
|
118
|
+
* omitted `O_CREAT` fails `ENOENT` for a target that has gone since the walk saw it. This is the
|
|
119
|
+
* mutating counterpart of the `wx` flag every create in this package uses. Which code the refusal
|
|
120
|
+
* carries is the host's; Linux with Node v22.22.2 reported `ELOOP` on 2026-08-24.
|
|
121
|
+
*
|
|
122
|
+
* A directory component stays open, because Node exposes no descriptor-relative call to walk and
|
|
123
|
+
* write through one set of descriptors. Where a host's Node build defines no `O_NOFOLLOW`, that flag
|
|
124
|
+
* contributes nothing to the flag set and the final component is open on that host too.
|
|
125
|
+
*
|
|
126
|
+
* @param file - The absolute path to overwrite
|
|
127
|
+
* @param text - The text to write
|
|
128
|
+
* @returns Nothing
|
|
129
|
+
* @throws The host's own fault when the final component is a symbolic link, when the file is
|
|
130
|
+
* absent, or when the host refuses the descriptor
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* const file = resolveWorkspaceFile('/srv/checkout', 'tmp/probe/arm-type.ts', true)
|
|
135
|
+
* writeFileSync(file, 'export type Signal = string\n', { encoding: 'utf8', flag: 'wx' })
|
|
136
|
+
* overwriteFile(file, 'export type Signal = number\n')
|
|
137
|
+
* readFileSync(file, 'utf8') // 'export type Signal = number\n'
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
function overwriteFile(file, text) {
|
|
141
|
+
const descriptor = openSync(file, constants.O_WRONLY | constants.O_TRUNC | constants.O_NOFOLLOW);
|
|
142
|
+
try {
|
|
143
|
+
writeFileSync(descriptor, text, "utf8");
|
|
144
|
+
} finally {
|
|
145
|
+
closeSync(descriptor);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
109
149
|
* Reports whether a fault means the host refuses the name a caller supplied for a file to create.
|
|
110
150
|
*
|
|
111
151
|
* @remarks
|
|
@@ -169,6 +209,60 @@ function relativeWorkspaceFile(workspace, file) {
|
|
|
169
209
|
return normalizePath(relative(resolve(workspace), resolve(file)));
|
|
170
210
|
}
|
|
171
211
|
/**
|
|
212
|
+
* Projects the paths one tool named in a message into the forms this package's issues expose.
|
|
213
|
+
*
|
|
214
|
+
* @remarks
|
|
215
|
+
* An issue's `path` is workspace-relative, and its message is prose a tool wrote about the same
|
|
216
|
+
* tree. Left alone that prose names a file by the host's own layout, so one issue reports a path two
|
|
217
|
+
* ways and a reader on another checkout is sent to a directory that is not theirs. Each spelling of
|
|
218
|
+
* the root is removed: the absolute path, the backslash spelling a Windows tool writes, and the
|
|
219
|
+
* `file:` URL a runtime names a module by. A root the host itself names ends in a separator, and the
|
|
220
|
+
* paths beneath it continue straight from it rather than from one more separator. A path outside the
|
|
221
|
+
* workspace stands as it is, because a relative spelling of it would name a file the tree does not
|
|
222
|
+
* hold.
|
|
223
|
+
*
|
|
224
|
+
* A spelling of the root counts only where a path begins: at the start of the message, or after a
|
|
225
|
+
* character no path carries. A directory whose own name ends in this root's text holds a different
|
|
226
|
+
* tree, so the root inside a longer path names a file this workspace does not hold and that path
|
|
227
|
+
* survives whole.
|
|
228
|
+
*
|
|
229
|
+
* Only the root is removed. A name is otherwise the tool's, including a `.probe-` name that reads
|
|
230
|
+
* like a specification this package generates: the stage that wrote one knows the exact name it
|
|
231
|
+
* wrote and renames that name itself, which is the only reading that separates its own file from a
|
|
232
|
+
* file the target tree owns.
|
|
233
|
+
*
|
|
234
|
+
* Everything else the tool wrote survives verbatim, separators included. A message carries text
|
|
235
|
+
* that is not a path — a runtime escapes a newline as a backslash when it prints a string inline,
|
|
236
|
+
* and a compiler quotes a string literal with its escapes intact — so rewriting every separator
|
|
237
|
+
* would corrupt the evidence the message exists to carry. The cost is that the path left behind
|
|
238
|
+
* keeps the separator the tool chose, which on Windows is not the one `Issue.path` uses.
|
|
239
|
+
*
|
|
240
|
+
* @param workspace - The target workspace root
|
|
241
|
+
* @param message - The message a tool reported
|
|
242
|
+
* @returns The message with the host's own layout removed from every path that begins with it
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* relativeWorkspaceMessage('/srv/checkout', 'Cannot read /srv/checkout/tsconfig.json')
|
|
247
|
+
* // 'Cannot read tsconfig.json'
|
|
248
|
+
* relativeWorkspaceMessage('/srv/checkout', 'Cannot read /mirror/srv/checkout/tsconfig.json')
|
|
249
|
+
* // 'Cannot read /mirror/srv/checkout/tsconfig.json'
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
function relativeWorkspaceMessage(workspace, message) {
|
|
253
|
+
const root = resolve(workspace);
|
|
254
|
+
const forward = normalizePath(root);
|
|
255
|
+
const url = pathToFileURL(forward).href;
|
|
256
|
+
const spellings = /* @__PURE__ */ new Set([
|
|
257
|
+
url.endsWith("/") ? url : `${url}/`,
|
|
258
|
+
forward.endsWith("/") ? forward : `${forward}/`,
|
|
259
|
+
root.endsWith(sep) ? root : `${root}${sep}`
|
|
260
|
+
]);
|
|
261
|
+
let text = message;
|
|
262
|
+
for (const spelling of spellings) text = text.replaceAll(spelling, (match, offset, source) => /[^\s"'`()[\]{}<>,;:=|]/u.test(source.charAt(offset - 1)) ? match : "");
|
|
263
|
+
return text;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
172
266
|
* Resolves one installed module from the target workspace.
|
|
173
267
|
*
|
|
174
268
|
* @param workspace - The target workspace root
|
|
@@ -456,6 +550,32 @@ function describeUnknown(value) {
|
|
|
456
550
|
return String(value);
|
|
457
551
|
}
|
|
458
552
|
/**
|
|
553
|
+
* Guards one resident-stage operation with the stage failure contract.
|
|
554
|
+
*
|
|
555
|
+
* @param stage - The resident stage serving the operation
|
|
556
|
+
* @param operation - The operation to settle
|
|
557
|
+
* @returns The operation's fulfilled value
|
|
558
|
+
* @throws The original `ProbeError`, or an instrument-owned malformed failure retaining the cause
|
|
559
|
+
*
|
|
560
|
+
* @example
|
|
561
|
+
* ```ts
|
|
562
|
+
* await guardStage('type', stage.inspect(subject))
|
|
563
|
+
* ```
|
|
564
|
+
*/
|
|
565
|
+
async function guardStage(stage, operation) {
|
|
566
|
+
try {
|
|
567
|
+
return await operation;
|
|
568
|
+
} catch (error) {
|
|
569
|
+
if (error instanceof ProbeError) throw error;
|
|
570
|
+
throw new ProbeError(`The ${stage} stage could not serve (${describeUnknown(error)})`, {
|
|
571
|
+
origin: "instrument",
|
|
572
|
+
code: "malformed",
|
|
573
|
+
context: { stage },
|
|
574
|
+
cause: error
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
459
579
|
* Names every draft member of a claim-shaped value whose `path` this package's guard refuses.
|
|
460
580
|
*
|
|
461
581
|
* @remarks
|
|
@@ -685,11 +805,11 @@ var Overlay = class {
|
|
|
685
805
|
};
|
|
686
806
|
//#endregion
|
|
687
807
|
//#region package.json
|
|
688
|
-
var version = "0.0.
|
|
808
|
+
var version = "0.0.5";
|
|
689
809
|
var peerDependencies = {
|
|
690
|
-
"oxlint": "^1.
|
|
691
|
-
"typescript": "^6.0.
|
|
692
|
-
"vitest": "^4.1.
|
|
810
|
+
"oxlint": "^1.77.0",
|
|
811
|
+
"typescript": "^6.0.0",
|
|
812
|
+
"vitest": "^4.1.0"
|
|
693
813
|
};
|
|
694
814
|
//#endregion
|
|
695
815
|
//#region src/server/stages/LintStage.ts
|
|
@@ -751,7 +871,16 @@ var LintStage = class {
|
|
|
751
871
|
get progress() {
|
|
752
872
|
return this.#progress;
|
|
753
873
|
}
|
|
754
|
-
|
|
874
|
+
inspect(subject) {
|
|
875
|
+
return guardStage(this.stage, this.#inspect(subject));
|
|
876
|
+
}
|
|
877
|
+
destroy() {
|
|
878
|
+
if (this.#closing !== void 0) return this.#closing;
|
|
879
|
+
this.#destroyed = true;
|
|
880
|
+
this.#closing = guardStage(this.stage, this.#destroy());
|
|
881
|
+
return this.#closing;
|
|
882
|
+
}
|
|
883
|
+
async #inspect(subject) {
|
|
755
884
|
if (this.#destroyed) throw createDestroyedError("lint stage");
|
|
756
885
|
const started = performance.now();
|
|
757
886
|
await this.#warmth;
|
|
@@ -764,12 +893,6 @@ var LintStage = class {
|
|
|
764
893
|
issues
|
|
765
894
|
};
|
|
766
895
|
}
|
|
767
|
-
destroy() {
|
|
768
|
-
if (this.#closing !== void 0) return this.#closing;
|
|
769
|
-
this.#destroyed = true;
|
|
770
|
-
this.#closing = this.#destroy();
|
|
771
|
-
return this.#closing;
|
|
772
|
-
}
|
|
773
896
|
async #destroy() {
|
|
774
897
|
const child = await this.#warmed();
|
|
775
898
|
this.#fail(createDestroyedError("lint stage"));
|
|
@@ -1057,6 +1180,13 @@ var LintStage = class {
|
|
|
1057
1180
|
* workspace module whose disk content or candidate revision changed, runs that specification,
|
|
1058
1181
|
* evicts its result, and deletes the file. Clearing the overlay makes the next snapshot differ from
|
|
1059
1182
|
* the candidate revision, so the next inspection invalidates that module and reads disk again.
|
|
1183
|
+
* After the run, the stage checks each covered module reachable from the generated specification
|
|
1184
|
+
* against the overlay paths its loader served. A target-config loader that served first produces a
|
|
1185
|
+
* workspace issue; a module id probe's loader received but failed to match produces an instrument
|
|
1186
|
+
* issue.
|
|
1187
|
+
* The runtime overlay leaves bare specifier resolution to Vite: it replaces a bare import only
|
|
1188
|
+
* after Vite resolves that import to a covered file. The type stage overlays the declared test
|
|
1189
|
+
* path, while this stage executes a generated sibling and overlays only the candidate files.
|
|
1060
1190
|
*
|
|
1061
1191
|
* Vite retains one unresolved URL for every specification path, so the stage replaces its whole
|
|
1062
1192
|
* Vitest service after 64 specifications rather than deleting from each map that service owns. Any
|
|
@@ -1080,9 +1210,12 @@ var LintStage = class {
|
|
|
1080
1210
|
* test path the host refuses to create is a claimant failure with `code: 'refused'`. Each is thrown
|
|
1081
1211
|
* rather than reported, because a test that never ran is no evidence about the candidate.
|
|
1082
1212
|
*
|
|
1083
|
-
*
|
|
1084
|
-
*
|
|
1085
|
-
*
|
|
1213
|
+
* Physical containment covers the claim inputs, the target tree as the walk inspected it, and the
|
|
1214
|
+
* final component at the moment this stage writes or unlinks it: a specification is created with the
|
|
1215
|
+
* `wx` flag, which fails rather than following a symbolic link that appeared after the walk, and an
|
|
1216
|
+
* unlink names the final component itself rather than what it points at. A directory component
|
|
1217
|
+
* swapped for a symbolic link between the walk and the write stays open, because Node exposes no
|
|
1218
|
+
* descriptor-relative call to pin the walk and the write to one set of descriptors.
|
|
1086
1219
|
*
|
|
1087
1220
|
* @example
|
|
1088
1221
|
* ```ts
|
|
@@ -1095,6 +1228,8 @@ var RuntimeStage = class {
|
|
|
1095
1228
|
#workspace;
|
|
1096
1229
|
#vitest;
|
|
1097
1230
|
#overlay = new Overlay();
|
|
1231
|
+
#loads = /* @__PURE__ */ new Set();
|
|
1232
|
+
#reads = /* @__PURE__ */ new Set();
|
|
1098
1233
|
#modules = /* @__PURE__ */ new Map();
|
|
1099
1234
|
#revisions = /* @__PURE__ */ new Set();
|
|
1100
1235
|
#specifications = 0;
|
|
@@ -1109,8 +1244,7 @@ var RuntimeStage = class {
|
|
|
1109
1244
|
constructor(workspace = process.cwd()) {
|
|
1110
1245
|
this.#workspace = workspace;
|
|
1111
1246
|
const vitest = loadWorkspaceModule(this.#workspace, "vitest/node");
|
|
1112
|
-
this.#
|
|
1113
|
-
this.#vitest.catch(() => {});
|
|
1247
|
+
this.#store(this.#warm(vitest.createVitest));
|
|
1114
1248
|
}
|
|
1115
1249
|
get stage() {
|
|
1116
1250
|
return "runtime";
|
|
@@ -1118,7 +1252,16 @@ var RuntimeStage = class {
|
|
|
1118
1252
|
get progress() {
|
|
1119
1253
|
return this.#progress;
|
|
1120
1254
|
}
|
|
1121
|
-
|
|
1255
|
+
inspect(subject) {
|
|
1256
|
+
return guardStage(this.stage, this.#inspect(subject));
|
|
1257
|
+
}
|
|
1258
|
+
destroy() {
|
|
1259
|
+
if (this.#closing !== void 0) return this.#closing;
|
|
1260
|
+
this.#destroyed = true;
|
|
1261
|
+
this.#closing = guardStage(this.stage, this.#destroy());
|
|
1262
|
+
return this.#closing;
|
|
1263
|
+
}
|
|
1264
|
+
async #inspect(subject) {
|
|
1122
1265
|
if (this.#destroyed) throw createDestroyedError("runtime stage");
|
|
1123
1266
|
const started = performance.now();
|
|
1124
1267
|
const exitCode = process.exitCode;
|
|
@@ -1132,6 +1275,8 @@ var RuntimeStage = class {
|
|
|
1132
1275
|
};
|
|
1133
1276
|
const overlay = new Overlay();
|
|
1134
1277
|
this.#overlay = overlay;
|
|
1278
|
+
this.#loads.clear();
|
|
1279
|
+
this.#reads.clear();
|
|
1135
1280
|
try {
|
|
1136
1281
|
for (const draft of subject.files) overlay.set(resolveWorkspaceFile(this.#workspace, draft.path), draft.text);
|
|
1137
1282
|
this.#revalidate(vitest);
|
|
@@ -1151,7 +1296,7 @@ var RuntimeStage = class {
|
|
|
1151
1296
|
try {
|
|
1152
1297
|
try {
|
|
1153
1298
|
const result = await vitest.runTestSpecifications([task], false);
|
|
1154
|
-
issues = this.#issues(result, file, subject.test.path);
|
|
1299
|
+
issues = [...this.#issues(result, file, subject.test.path), ...this.#misses(project, file)];
|
|
1155
1300
|
} catch (error) {
|
|
1156
1301
|
if (error instanceof ProbeError) throw error;
|
|
1157
1302
|
throw new ProbeError(`The runtime stage could not run the generated specification (${describeUnknown(error)})`, {
|
|
@@ -1186,15 +1331,11 @@ var RuntimeStage = class {
|
|
|
1186
1331
|
issues: [...issues, ...cleanup]
|
|
1187
1332
|
};
|
|
1188
1333
|
} finally {
|
|
1334
|
+
this.#loads.clear();
|
|
1335
|
+
this.#reads.clear();
|
|
1189
1336
|
overlay.clear();
|
|
1190
1337
|
}
|
|
1191
1338
|
}
|
|
1192
|
-
destroy() {
|
|
1193
|
-
if (this.#closing !== void 0) return this.#closing;
|
|
1194
|
-
this.#destroyed = true;
|
|
1195
|
-
this.#closing = this.#destroy();
|
|
1196
|
-
return this.#closing;
|
|
1197
|
-
}
|
|
1198
1339
|
async #destroy() {
|
|
1199
1340
|
try {
|
|
1200
1341
|
for (const file of this.#revisions) try {
|
|
@@ -1202,13 +1343,15 @@ var RuntimeStage = class {
|
|
|
1202
1343
|
if (existsSync(contained)) unlinkSync(contained);
|
|
1203
1344
|
} catch {}
|
|
1204
1345
|
this.#revisions.clear();
|
|
1205
|
-
const vitest = await this.#vitest
|
|
1346
|
+
const vitest = await this.#vitest?.catch(() => void 0);
|
|
1206
1347
|
if (vitest !== void 0) {
|
|
1207
1348
|
vitest.cancelCurrentRun("keyboard-input").catch(() => {});
|
|
1208
1349
|
await vitest.close();
|
|
1209
1350
|
}
|
|
1210
1351
|
} finally {
|
|
1211
1352
|
this.#modules.clear();
|
|
1353
|
+
this.#loads.clear();
|
|
1354
|
+
this.#reads.clear();
|
|
1212
1355
|
this.#overlay.clear();
|
|
1213
1356
|
}
|
|
1214
1357
|
}
|
|
@@ -1217,8 +1360,9 @@ var RuntimeStage = class {
|
|
|
1217
1360
|
const output = new PassThrough();
|
|
1218
1361
|
output.resume();
|
|
1219
1362
|
const signals = captureListeners(process, ["SIGINT", "SIGTERM"]);
|
|
1363
|
+
let warming;
|
|
1220
1364
|
try {
|
|
1221
|
-
|
|
1365
|
+
warming = create("test", {
|
|
1222
1366
|
root: this.#workspace,
|
|
1223
1367
|
config: resolveWorkspaceFile(this.#workspace, "vite.config.ts"),
|
|
1224
1368
|
watch: false,
|
|
@@ -1236,9 +1380,16 @@ var RuntimeStage = class {
|
|
|
1236
1380
|
stdout: output,
|
|
1237
1381
|
stderr: process.stderr
|
|
1238
1382
|
});
|
|
1383
|
+
} catch (error) {
|
|
1384
|
+
throw this.#configuration(error);
|
|
1239
1385
|
} finally {
|
|
1240
1386
|
releaseListeners(process, signals);
|
|
1241
1387
|
}
|
|
1388
|
+
try {
|
|
1389
|
+
return await warming;
|
|
1390
|
+
} catch (error) {
|
|
1391
|
+
throw this.#configuration(error);
|
|
1392
|
+
}
|
|
1242
1393
|
}
|
|
1243
1394
|
#configure(config) {
|
|
1244
1395
|
const test = config.test;
|
|
@@ -1265,7 +1416,7 @@ var RuntimeStage = class {
|
|
|
1265
1416
|
};
|
|
1266
1417
|
}
|
|
1267
1418
|
#resolve(id, importer) {
|
|
1268
|
-
const separator = id.
|
|
1419
|
+
const separator = id.indexOf("?");
|
|
1269
1420
|
const specifier = separator === -1 ? id : id.slice(0, separator);
|
|
1270
1421
|
const suffix = separator === -1 ? "" : id.slice(separator);
|
|
1271
1422
|
if (!specifier.startsWith(".") && !isAbsolute(specifier)) return void 0;
|
|
@@ -1277,17 +1428,22 @@ var RuntimeStage = class {
|
|
|
1277
1428
|
if (extension === "") candidates.push(`${imported}.ts`);
|
|
1278
1429
|
for (const candidate of candidates) {
|
|
1279
1430
|
const resolved = `${candidate}${suffix}`;
|
|
1280
|
-
if (this.#
|
|
1431
|
+
if (this.#overlay.text(candidate) !== void 0) return resolved;
|
|
1281
1432
|
}
|
|
1282
1433
|
}
|
|
1283
1434
|
#load(id) {
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
const
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1435
|
+
this.#loads.add(normalizePath(id));
|
|
1436
|
+
const separator = id.indexOf("?");
|
|
1437
|
+
const path = separator === -1 ? id : id.slice(0, separator);
|
|
1438
|
+
const text = this.#overlay.text(path);
|
|
1439
|
+
if (text === void 0) return void 0;
|
|
1440
|
+
this.#reads.add(normalizePath(path));
|
|
1441
|
+
if (separator !== -1 && /(?:^|&)raw(?:&|$)/u.test(id.slice(separator + 1))) return {
|
|
1442
|
+
code: `export default ${JSON.stringify(text)}`,
|
|
1443
|
+
map: { mappings: "" },
|
|
1444
|
+
moduleType: "js"
|
|
1445
|
+
};
|
|
1446
|
+
return text;
|
|
1291
1447
|
}
|
|
1292
1448
|
#specification(test) {
|
|
1293
1449
|
let creating = false;
|
|
@@ -1359,6 +1515,47 @@ var RuntimeStage = class {
|
|
|
1359
1515
|
};
|
|
1360
1516
|
return project;
|
|
1361
1517
|
}
|
|
1518
|
+
#misses(project, specification) {
|
|
1519
|
+
const file = normalizePath(specification);
|
|
1520
|
+
const issues = [];
|
|
1521
|
+
for (const path of this.#overlay.paths) {
|
|
1522
|
+
if (this.#reads.has(path)) continue;
|
|
1523
|
+
let served = false;
|
|
1524
|
+
let loaded = false;
|
|
1525
|
+
for (const environment of Object.values(project.vite.environments)) {
|
|
1526
|
+
const modules = environment.moduleGraph.getModulesByFile(path);
|
|
1527
|
+
if (modules === void 0) continue;
|
|
1528
|
+
for (const module of modules) {
|
|
1529
|
+
const pending = [...module.importers];
|
|
1530
|
+
const seen = new Set(pending);
|
|
1531
|
+
let reaches = false;
|
|
1532
|
+
while (pending.length > 0) {
|
|
1533
|
+
const importer = pending.pop();
|
|
1534
|
+
if (importer === void 0) break;
|
|
1535
|
+
if (importer.file !== null && normalizePath(importer.file) === file) {
|
|
1536
|
+
reaches = true;
|
|
1537
|
+
break;
|
|
1538
|
+
}
|
|
1539
|
+
for (const parent of importer.importers) {
|
|
1540
|
+
if (seen.has(parent)) continue;
|
|
1541
|
+
seen.add(parent);
|
|
1542
|
+
pending.push(parent);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
if (!reaches) continue;
|
|
1546
|
+
served = true;
|
|
1547
|
+
if (module.id !== null && this.#loads.has(normalizePath(module.id))) loaded = true;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
if (!served) continue;
|
|
1551
|
+
issues.push({
|
|
1552
|
+
origin: loaded ? "instrument" : "workspace",
|
|
1553
|
+
path: relativeWorkspaceFile(this.#workspace, path),
|
|
1554
|
+
message: loaded ? "The runtime overlay did not resolve this module" : "The workspace configuration served this module before the runtime overlay"
|
|
1555
|
+
});
|
|
1556
|
+
}
|
|
1557
|
+
return issues;
|
|
1558
|
+
}
|
|
1362
1559
|
async #evict(vitest, file) {
|
|
1363
1560
|
try {
|
|
1364
1561
|
const ids = [];
|
|
@@ -1399,17 +1596,38 @@ var RuntimeStage = class {
|
|
|
1399
1596
|
}
|
|
1400
1597
|
}
|
|
1401
1598
|
#runner() {
|
|
1402
|
-
|
|
1403
|
-
this.#specifications
|
|
1404
|
-
|
|
1405
|
-
this.#vitest
|
|
1406
|
-
return this.#
|
|
1599
|
+
const current = this.#vitest;
|
|
1600
|
+
if (current !== void 0 && this.#specifications < 64) return current;
|
|
1601
|
+
if (current !== void 0) return this.#store(this.#replace(current));
|
|
1602
|
+
const runner = loadWorkspaceModule(this.#workspace, "vitest/node");
|
|
1603
|
+
return this.#store(this.#specifications < 64 ? this.#warm(runner.createVitest) : this.#replace(void 0, runner.createVitest));
|
|
1407
1604
|
}
|
|
1408
|
-
async #replace(current) {
|
|
1409
|
-
await (await current).close();
|
|
1605
|
+
async #replace(current, create) {
|
|
1606
|
+
if (current !== void 0) await (await current).close();
|
|
1410
1607
|
if (this.#destroyed) throw createDestroyedError("runtime stage");
|
|
1411
|
-
const runner = loadWorkspaceModule(this.#workspace, "vitest/node");
|
|
1412
|
-
|
|
1608
|
+
const runner = create ?? loadWorkspaceModule(this.#workspace, "vitest/node").createVitest;
|
|
1609
|
+
const replacement = await this.#warm(runner);
|
|
1610
|
+
this.#specifications = 0;
|
|
1611
|
+
return replacement;
|
|
1612
|
+
}
|
|
1613
|
+
#store(vitest) {
|
|
1614
|
+
this.#vitest = vitest;
|
|
1615
|
+
vitest.catch(() => {
|
|
1616
|
+
if (this.#vitest === vitest) this.#vitest = void 0;
|
|
1617
|
+
});
|
|
1618
|
+
return vitest;
|
|
1619
|
+
}
|
|
1620
|
+
#configuration(error) {
|
|
1621
|
+
if (isProbeError(error)) return error;
|
|
1622
|
+
return new ProbeError(`The runtime stage could not load vite.config.ts (${describeUnknown(error)})`, {
|
|
1623
|
+
origin: "workspace",
|
|
1624
|
+
code: "malformed",
|
|
1625
|
+
context: {
|
|
1626
|
+
stage: this.stage,
|
|
1627
|
+
path: "vite.config.ts"
|
|
1628
|
+
},
|
|
1629
|
+
cause: error
|
|
1630
|
+
});
|
|
1413
1631
|
}
|
|
1414
1632
|
#revalidate(vitest) {
|
|
1415
1633
|
const modules = this.#snapshot();
|
|
@@ -1554,7 +1772,7 @@ var RuntimeStage = class {
|
|
|
1554
1772
|
return outcome.success ? outcome.value : path;
|
|
1555
1773
|
}
|
|
1556
1774
|
#issue(error, specification, original) {
|
|
1557
|
-
const message = describeUnknown(error);
|
|
1775
|
+
const message = relativeWorkspaceMessage(this.#workspace, describeUnknown(error)).replaceAll(basename(specification), basename(original));
|
|
1558
1776
|
if (typeof error !== "object" || error === null || !("stacks" in error)) return {
|
|
1559
1777
|
origin: "claimant",
|
|
1560
1778
|
path: original,
|
|
@@ -1661,7 +1879,33 @@ var TypeStage = class {
|
|
|
1661
1879
|
* @returns One outcome for this stage
|
|
1662
1880
|
* @throws When the resident compiler cannot start or the stage has already been destroyed
|
|
1663
1881
|
*/
|
|
1664
|
-
|
|
1882
|
+
inspect(subject, project) {
|
|
1883
|
+
return guardStage(this.stage, this.#inspect(subject, project));
|
|
1884
|
+
}
|
|
1885
|
+
/**
|
|
1886
|
+
* Resolves one project to the path and digest this stage applies for it.
|
|
1887
|
+
*
|
|
1888
|
+
* @remarks
|
|
1889
|
+
* Reads the parse this stage itself applies, filling its cache when the project is not already
|
|
1890
|
+
* resident, so the reported digest is the configuration the inspection is judged under rather
|
|
1891
|
+
* than a second parse a caller ran. The returned record is a value copy, so a later eviction
|
|
1892
|
+
* does not move it.
|
|
1893
|
+
*
|
|
1894
|
+
* @param project - The workspace-relative TypeScript project to resolve
|
|
1895
|
+
* @returns The resolved workspace-relative path and the digest of its compiler options
|
|
1896
|
+
* @throws When the project escapes the workspace, cannot be parsed, or the stage has already
|
|
1897
|
+
* been destroyed
|
|
1898
|
+
*/
|
|
1899
|
+
resolve(project) {
|
|
1900
|
+
return guardStage(this.stage, this.#resolve(project));
|
|
1901
|
+
}
|
|
1902
|
+
destroy() {
|
|
1903
|
+
if (this.#closing !== void 0) return this.#closing;
|
|
1904
|
+
this.#destroyed = true;
|
|
1905
|
+
this.#closing = guardStage(this.stage, this.#destroy());
|
|
1906
|
+
return this.#closing;
|
|
1907
|
+
}
|
|
1908
|
+
async #inspect(subject, project) {
|
|
1665
1909
|
if (this.#destroyed) throw createDestroyedError("type stage");
|
|
1666
1910
|
const started = performance.now();
|
|
1667
1911
|
const typescript = await this.#typescript;
|
|
@@ -1673,8 +1917,13 @@ var TypeStage = class {
|
|
|
1673
1917
|
draft: candidate.draft,
|
|
1674
1918
|
project: project ?? inferTypeProject(relativeWorkspaceFile(this.#workspace, candidate.path))
|
|
1675
1919
|
}));
|
|
1676
|
-
this.#
|
|
1677
|
-
|
|
1920
|
+
const root = this.#service(typescript, "tsconfig.json");
|
|
1921
|
+
this.#configure(root, "tsconfig.json");
|
|
1922
|
+
await this.#unblock();
|
|
1923
|
+
for (const selection of selections) {
|
|
1924
|
+
this.#configure(this.#service(typescript, selection.project), selection.project);
|
|
1925
|
+
await this.#unblock();
|
|
1926
|
+
}
|
|
1678
1927
|
const overlay = new Overlay();
|
|
1679
1928
|
this.#overlay = overlay;
|
|
1680
1929
|
try {
|
|
@@ -1683,7 +1932,6 @@ var TypeStage = class {
|
|
|
1683
1932
|
this.#progress += 1;
|
|
1684
1933
|
const issues = [];
|
|
1685
1934
|
const projects = /* @__PURE__ */ new Set();
|
|
1686
|
-
const root = this.#service(typescript, "tsconfig.json");
|
|
1687
1935
|
issues.push(...this.#issues(typescript, root, subject.test, "tsconfig.json", false, true));
|
|
1688
1936
|
projects.add("tsconfig.json");
|
|
1689
1937
|
await this.#unblock();
|
|
@@ -1704,37 +1952,19 @@ var TypeStage = class {
|
|
|
1704
1952
|
overlay.clear();
|
|
1705
1953
|
}
|
|
1706
1954
|
}
|
|
1707
|
-
|
|
1708
|
-
* Resolves one project to the path and digest this stage applies for it.
|
|
1709
|
-
*
|
|
1710
|
-
* @remarks
|
|
1711
|
-
* Reads the parse this stage itself applies, filling its cache when the project is not already
|
|
1712
|
-
* resident, so the reported digest is the configuration the inspection is judged under rather
|
|
1713
|
-
* than a second parse a caller ran. The returned record is a value copy, so a later eviction
|
|
1714
|
-
* does not move it.
|
|
1715
|
-
*
|
|
1716
|
-
* @param project - The workspace-relative TypeScript project to resolve
|
|
1717
|
-
* @returns The resolved workspace-relative path and the digest of its compiler options
|
|
1718
|
-
* @throws When the project escapes the workspace, cannot be parsed, or the stage has already
|
|
1719
|
-
* been destroyed
|
|
1720
|
-
*/
|
|
1721
|
-
async resolve(project) {
|
|
1955
|
+
async #resolve(project) {
|
|
1722
1956
|
if (this.#destroyed) throw createDestroyedError("type stage");
|
|
1723
1957
|
const typescript = await this.#typescript;
|
|
1724
1958
|
if (this.#destroyed) throw createDestroyedError("type stage");
|
|
1725
1959
|
const resolved = resolveWorkspaceFile(this.#workspace, project);
|
|
1960
|
+
this.#progress += 1;
|
|
1726
1961
|
this.#service(typescript, project);
|
|
1962
|
+
await this.#unblock();
|
|
1727
1963
|
return {
|
|
1728
1964
|
path: relativeWorkspaceFile(this.#workspace, resolved),
|
|
1729
1965
|
digest: computeDigest(this.#workspace, this.#options.get(resolved) ?? {})
|
|
1730
1966
|
};
|
|
1731
1967
|
}
|
|
1732
|
-
destroy() {
|
|
1733
|
-
if (this.#closing !== void 0) return this.#closing;
|
|
1734
|
-
this.#destroyed = true;
|
|
1735
|
-
this.#closing = this.#destroy();
|
|
1736
|
-
return this.#closing;
|
|
1737
|
-
}
|
|
1738
1968
|
async #destroy() {
|
|
1739
1969
|
await this.#typescript.catch(() => void 0);
|
|
1740
1970
|
for (const service of this.#services.values()) service.dispose();
|
|
@@ -1767,7 +1997,7 @@ var TypeStage = class {
|
|
|
1767
1997
|
return projects;
|
|
1768
1998
|
}
|
|
1769
1999
|
async #unblock() {
|
|
1770
|
-
await
|
|
2000
|
+
await setTimeout(0);
|
|
1771
2001
|
if (this.#destroyed) throw createDestroyedError("type stage");
|
|
1772
2002
|
}
|
|
1773
2003
|
#record(draft, overlay) {
|
|
@@ -1779,7 +2009,7 @@ var TypeStage = class {
|
|
|
1779
2009
|
if (existing !== void 0) return existing;
|
|
1780
2010
|
const spelling = normalizePath(path);
|
|
1781
2011
|
const config = typescript.readConfigFile(spelling, typescript.sys.readFile);
|
|
1782
|
-
if (config.error !== void 0) throw new ProbeError(this.#translate(typescript, config.error.messageText
|
|
2012
|
+
if (config.error !== void 0) throw new ProbeError(this.#translate(typescript, config.error.messageText), {
|
|
1783
2013
|
origin: "workspace",
|
|
1784
2014
|
code: "malformed",
|
|
1785
2015
|
context: {
|
|
@@ -1788,7 +2018,7 @@ var TypeStage = class {
|
|
|
1788
2018
|
}
|
|
1789
2019
|
});
|
|
1790
2020
|
const parsed = typescript.parseJsonConfigFileContent(config.config, typescript.sys, dirname(spelling), void 0, spelling);
|
|
1791
|
-
if (parsed.errors.length > 0) throw new ProbeError(this.#translate(typescript, parsed.errors[0]?.messageText
|
|
2021
|
+
if (parsed.errors.length > 0) throw new ProbeError(this.#translate(typescript, parsed.errors[0]?.messageText), {
|
|
1792
2022
|
origin: "workspace",
|
|
1793
2023
|
code: "malformed",
|
|
1794
2024
|
context: {
|
|
@@ -1845,8 +2075,8 @@ var TypeStage = class {
|
|
|
1845
2075
|
#newline(typescript) {
|
|
1846
2076
|
return typescript.sys.newLine;
|
|
1847
2077
|
}
|
|
1848
|
-
#translate(typescript, message
|
|
1849
|
-
return
|
|
2078
|
+
#translate(typescript, message) {
|
|
2079
|
+
return relativeWorkspaceMessage(this.#workspace, typescript.flattenDiagnosticMessageText(message, "\n"));
|
|
1850
2080
|
}
|
|
1851
2081
|
#configure(service, project) {
|
|
1852
2082
|
const path = resolveWorkspaceFile(this.#workspace, project);
|
|
@@ -1885,7 +2115,7 @@ var TypeStage = class {
|
|
|
1885
2115
|
].map((diagnostic) => this.#issue(typescript, diagnostic, project, selected));
|
|
1886
2116
|
}
|
|
1887
2117
|
#issue(typescript, diagnostic, project, selected) {
|
|
1888
|
-
const message = typescript
|
|
2118
|
+
const message = this.#translate(typescript, diagnostic.messageText);
|
|
1889
2119
|
if (diagnostic.file === void 0) {
|
|
1890
2120
|
if (selected) throw new ProbeError(message, {
|
|
1891
2121
|
origin: "claimant",
|
|
@@ -1896,7 +2126,7 @@ var TypeStage = class {
|
|
|
1896
2126
|
}
|
|
1897
2127
|
});
|
|
1898
2128
|
return {
|
|
1899
|
-
origin: "
|
|
2129
|
+
origin: "workspace",
|
|
1900
2130
|
path: project,
|
|
1901
2131
|
message
|
|
1902
2132
|
};
|
|
@@ -1948,6 +2178,8 @@ var Probe = class {
|
|
|
1948
2178
|
#typeQueue;
|
|
1949
2179
|
#lintQueue;
|
|
1950
2180
|
#runtimeQueue;
|
|
2181
|
+
#deadlines = /* @__PURE__ */ new WeakSet();
|
|
2182
|
+
#typeTail = Promise.resolve();
|
|
1951
2183
|
#arming;
|
|
1952
2184
|
#closing;
|
|
1953
2185
|
#destroyed = false;
|
|
@@ -1998,11 +2230,12 @@ var Probe = class {
|
|
|
1998
2230
|
async prove(claim) {
|
|
1999
2231
|
try {
|
|
2000
2232
|
this.#support();
|
|
2233
|
+
this.#admit(claim);
|
|
2001
2234
|
await this.#ready();
|
|
2002
2235
|
if (this.#destroyed) throw createDestroyedError("probe");
|
|
2003
2236
|
const started = performance.now();
|
|
2004
2237
|
const id = randomUUID();
|
|
2005
|
-
const project = await this.#
|
|
2238
|
+
const project = await this.#resolve(claim);
|
|
2006
2239
|
const digest = computeDigest(this.#workspace, {
|
|
2007
2240
|
case: claim.case,
|
|
2008
2241
|
control: claim.control
|
|
@@ -2140,7 +2373,7 @@ var Probe = class {
|
|
|
2140
2373
|
code: "malformed"
|
|
2141
2374
|
});
|
|
2142
2375
|
resolveWorkspaceFile(this.#workspace, relative(this.#workspace, typeDependency), true);
|
|
2143
|
-
|
|
2376
|
+
overwriteFile(typeDependency, formatSpecification("export type Signal = number\n", revision));
|
|
2144
2377
|
const afterType = await this.#inspect(typeClaim.control, typeClaim);
|
|
2145
2378
|
const type = afterType.find((check) => check.stage === typeClaim.control.stage);
|
|
2146
2379
|
const tolerant = afterType.find((check) => check.stage === "runtime");
|
|
@@ -2155,7 +2388,7 @@ var Probe = class {
|
|
|
2155
2388
|
context: { stage: "runtime" }
|
|
2156
2389
|
});
|
|
2157
2390
|
resolveWorkspaceFile(this.#workspace, relative(this.#workspace, runtimeDependency), true);
|
|
2158
|
-
|
|
2391
|
+
overwriteFile(runtimeDependency, formatSpecification("export const SIGNAL = 'after'\n", revision));
|
|
2159
2392
|
const afterRuntime = await this.#inspect(runtimeClaim.control, runtimeClaim);
|
|
2160
2393
|
const runtime = afterRuntime.find((check) => check.stage === runtimeClaim.control.stage);
|
|
2161
2394
|
if (runtime === void 0 || runtime.issues.length === 0) throw new ProbeError(`The probe boot runtime control did not detect a mutated dependency\n${afterRuntime.map(formatCheck).join("\n")}`, {
|
|
@@ -2184,8 +2417,14 @@ var Probe = class {
|
|
|
2184
2417
|
for (const pending of admitted) pending.catch(() => {});
|
|
2185
2418
|
return Promise.all(admitted);
|
|
2186
2419
|
}
|
|
2187
|
-
#inspectType(inspection) {
|
|
2188
|
-
|
|
2420
|
+
async #inspectType(inspection) {
|
|
2421
|
+
const release = await this.#admitType();
|
|
2422
|
+
try {
|
|
2423
|
+
const stage = this.#type;
|
|
2424
|
+
return await this.#inspectStage(stage, stage.progress, stage.inspect(inspection.subject, inspection.claim.project), inspection.claim);
|
|
2425
|
+
} finally {
|
|
2426
|
+
release();
|
|
2427
|
+
}
|
|
2189
2428
|
}
|
|
2190
2429
|
#inspectLint(inspection) {
|
|
2191
2430
|
return this.#inspectStage(this.#lint, this.#lint.progress, this.#lint.inspect(inspection.subject), inspection.claim);
|
|
@@ -2194,19 +2433,28 @@ var Probe = class {
|
|
|
2194
2433
|
return this.#inspectStage(this.#runtime, this.#runtime.progress, this.#runtime.inspect(inspection.subject), inspection.claim);
|
|
2195
2434
|
}
|
|
2196
2435
|
async #inspectStage(stage, progress, operation, claim) {
|
|
2436
|
+
try {
|
|
2437
|
+
return await this.#bound(operation, `The ${stage.stage} stage exceeded ${this.#deadline} ms`, stage, progress);
|
|
2438
|
+
} catch (error) {
|
|
2439
|
+
this.#emitExpiry(stage, claim);
|
|
2440
|
+
throw error;
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
async #bound(operation, message, stage, progress) {
|
|
2197
2444
|
const timeout = createTimeout({ ms: this.#deadline });
|
|
2198
2445
|
timeout.start();
|
|
2199
2446
|
try {
|
|
2200
|
-
return await Promise.race([operation, this.#expiry(timeout,
|
|
2447
|
+
return await Promise.race([operation, this.#expiry(timeout, message, stage, progress)]);
|
|
2201
2448
|
} catch (error) {
|
|
2202
2449
|
if (!timeout.expired) throw error;
|
|
2203
|
-
|
|
2450
|
+
await this.#recycle(stage);
|
|
2204
2451
|
throw error;
|
|
2205
2452
|
} finally {
|
|
2206
2453
|
timeout.clear();
|
|
2207
2454
|
}
|
|
2208
2455
|
}
|
|
2209
2456
|
async #recycle(stage) {
|
|
2457
|
+
if (this.#destroyed) return false;
|
|
2210
2458
|
const timeout = createTimeout({ ms: this.#deadline });
|
|
2211
2459
|
timeout.start();
|
|
2212
2460
|
try {
|
|
@@ -2229,16 +2477,45 @@ var Probe = class {
|
|
|
2229
2477
|
}
|
|
2230
2478
|
return false;
|
|
2231
2479
|
}
|
|
2480
|
+
async #admitType() {
|
|
2481
|
+
const previous = this.#typeTail;
|
|
2482
|
+
const turn = Promise.withResolvers();
|
|
2483
|
+
this.#typeTail = turn.promise;
|
|
2484
|
+
await previous;
|
|
2485
|
+
return turn.resolve;
|
|
2486
|
+
}
|
|
2487
|
+
async #resolve(claim) {
|
|
2488
|
+
const release = await this.#admitType();
|
|
2489
|
+
try {
|
|
2490
|
+
const stage = this.#type;
|
|
2491
|
+
try {
|
|
2492
|
+
return await this.#bound(stage.resolve(claim.project), `The type stage project resolution exceeded ${this.#deadline} ms`, stage, stage.progress);
|
|
2493
|
+
} catch (error) {
|
|
2494
|
+
this.#emitExpiry(stage, claim);
|
|
2495
|
+
throw error;
|
|
2496
|
+
}
|
|
2497
|
+
} finally {
|
|
2498
|
+
release();
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
#emitExpiry(stage, claim) {
|
|
2502
|
+
if (stage === this.#type || stage === this.#lint || stage === this.#runtime) return;
|
|
2503
|
+
this.#emitter.emit("expire", claim);
|
|
2504
|
+
}
|
|
2232
2505
|
#expiry(timeout, message, stage, progress) {
|
|
2233
2506
|
return new Promise((_resolve, reject) => {
|
|
2234
|
-
timeout.signal.addEventListener("abort", () =>
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2507
|
+
timeout.signal.addEventListener("abort", () => {
|
|
2508
|
+
const error = new ProbeError(message, {
|
|
2509
|
+
origin: stage.progress > progress ? "claimant" : "instrument",
|
|
2510
|
+
code: "deadline",
|
|
2511
|
+
context: {
|
|
2512
|
+
stage: stage.stage,
|
|
2513
|
+
deadline: this.#deadline
|
|
2514
|
+
}
|
|
2515
|
+
});
|
|
2516
|
+
this.#deadlines.add(error);
|
|
2517
|
+
reject(error);
|
|
2518
|
+
}, { once: true });
|
|
2242
2519
|
});
|
|
2243
2520
|
}
|
|
2244
2521
|
async #destroy() {
|
|
@@ -2246,11 +2523,18 @@ var Probe = class {
|
|
|
2246
2523
|
await this.#arming;
|
|
2247
2524
|
} catch {}
|
|
2248
2525
|
await Promise.all([
|
|
2249
|
-
this.#type
|
|
2250
|
-
this.#lint
|
|
2251
|
-
this.#runtime
|
|
2526
|
+
this.#destroyStage(this.#type),
|
|
2527
|
+
this.#destroyStage(this.#lint),
|
|
2528
|
+
this.#destroyStage(this.#runtime)
|
|
2252
2529
|
]);
|
|
2253
2530
|
}
|
|
2531
|
+
async #destroyStage(stage) {
|
|
2532
|
+
try {
|
|
2533
|
+
await this.#bound(stage.destroy(), `The ${stage.stage} stage teardown exceeded ${this.#deadline} ms`, stage, stage.progress);
|
|
2534
|
+
} catch (error) {
|
|
2535
|
+
if (!(error instanceof ProbeError) || !this.#deadlines.has(error)) throw error;
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2254
2538
|
#version(name) {
|
|
2255
2539
|
const version = readWorkspaceManifest(this.#workspace, name).contents.version;
|
|
2256
2540
|
if (typeof version !== "string") throw new ProbeError(`${name} publishes no readable version`, {
|
|
@@ -2260,6 +2544,21 @@ var Probe = class {
|
|
|
2260
2544
|
});
|
|
2261
2545
|
return version;
|
|
2262
2546
|
}
|
|
2547
|
+
#admit(claim) {
|
|
2548
|
+
const subject = claim.case;
|
|
2549
|
+
const control = claim.control;
|
|
2550
|
+
if (subject.test.path !== control.test.path) return;
|
|
2551
|
+
if (subject.test.text !== control.test.text) return;
|
|
2552
|
+
if (subject.files.length !== control.files.length) return;
|
|
2553
|
+
if (!subject.files.every((draft, index) => {
|
|
2554
|
+
const other = control.files[index];
|
|
2555
|
+
return other !== void 0 && other.path === draft.path && other.text === draft.text;
|
|
2556
|
+
})) return;
|
|
2557
|
+
throw new ProbeError("The control must differ from the case; it carries the same candidate drafts and the same test", {
|
|
2558
|
+
origin: "claimant",
|
|
2559
|
+
code: "refused"
|
|
2560
|
+
});
|
|
2561
|
+
}
|
|
2263
2562
|
#support() {
|
|
2264
2563
|
const version = this.#toolchain.typescript;
|
|
2265
2564
|
const range = peerDependencies.typescript;
|
|
@@ -2419,6 +2718,6 @@ var ProbeServer = class {
|
|
|
2419
2718
|
}
|
|
2420
2719
|
};
|
|
2421
2720
|
//#endregion
|
|
2422
|
-
export { LintStage, Overlay, Probe, ProbeServer, RuntimeStage, TypeStage, captureListeners, computeDigest, createRevisionFile, describeUnknown, findRefusedPaths, inferDocumentLanguage, inferTestProject, inferTypeProject, isRefusedName, loadWorkspaceModule, matchesWorkspaceModule, normalizePath, normalizeValue, parseContentLength, readWorkspaceManifest, relativeWorkspaceFile, releaseListeners, resolveWorkspaceBinary, resolveWorkspaceFile, resolveWorkspaceModule };
|
|
2721
|
+
export { LintStage, Overlay, Probe, ProbeServer, RuntimeStage, TypeStage, captureListeners, computeDigest, createRevisionFile, describeUnknown, findRefusedPaths, guardStage, inferDocumentLanguage, inferTestProject, inferTypeProject, isRefusedName, loadWorkspaceModule, matchesWorkspaceModule, normalizePath, normalizeValue, overwriteFile, parseContentLength, readWorkspaceManifest, relativeWorkspaceFile, relativeWorkspaceMessage, releaseListeners, resolveWorkspaceBinary, resolveWorkspaceFile, resolveWorkspaceModule };
|
|
2423
2722
|
|
|
2424
2723
|
//# sourceMappingURL=index.js.map
|