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