@orkestrel/probe 0.0.14 → 0.0.16
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/server/index.cjs +37 -37
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.js +38 -38
- package/dist/src/server/index.js.map +1 -1
- package/package.json +10 -10
package/dist/src/server/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { closeSync, constants, existsSync, ftruncateSync, lstatSync, mkdirSync,
|
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
6
|
-
import { attempt, compileGuard, compileSchema, isArray, isRecord, schemaToParameters } from "@orkestrel/contract";
|
|
6
|
+
import { attempt, compileGuard, compileSchema, isArray, isError, isNumber, isObject, isRecord, isString, parseJSON, schemaToParameters } from "@orkestrel/contract";
|
|
7
7
|
import { CLAIM_SHAPE, LINT_DEADLINE, PROBE_DEADLINE, PROBE_KEYS, PROBE_SPECIFICATIONS, ProbeError, RUNTIME_PLUGIN, TYPE_MIRROR, computeReceipt, createDestroyedError, formatCheck, formatReceipt, formatSpecification, formatVerdict, isClaim, isDraft, isProbeError, isVerdict, matchesSpecification } from "../core/index.js";
|
|
8
8
|
import { Emitter } from "@orkestrel/emitter";
|
|
9
9
|
import { createQueue } from "@orkestrel/queue";
|
|
@@ -60,11 +60,11 @@ function normalizePath(path) {
|
|
|
60
60
|
* ```
|
|
61
61
|
*/
|
|
62
62
|
function readFaultCode(error) {
|
|
63
|
-
if (
|
|
63
|
+
if (!isObject(error)) return void 0;
|
|
64
64
|
const fault = error;
|
|
65
65
|
const reading = attempt(() => "code" in fault ? fault.code : void 0);
|
|
66
66
|
if (!reading.success) return void 0;
|
|
67
|
-
return
|
|
67
|
+
return isString(reading.value) ? reading.value : void 0;
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
70
70
|
* Reports whether one path resolves outside the root it is read against.
|
|
@@ -151,7 +151,7 @@ function resolveWorkspaceFile(workspace, target, mutate = false) {
|
|
|
151
151
|
});
|
|
152
152
|
}
|
|
153
153
|
} catch (error) {
|
|
154
|
-
if (error
|
|
154
|
+
if (isProbeError(error)) throw error;
|
|
155
155
|
const code = readFaultCode(error);
|
|
156
156
|
const claimant = code === "ENAMETOOLONG" || code === "ERR_INVALID_ARG_VALUE";
|
|
157
157
|
throw new ProbeError(`The workspace path cannot be inspected: ${target}`, {
|
|
@@ -459,7 +459,7 @@ function readWorkspaceManifest(workspace, name) {
|
|
|
459
459
|
try {
|
|
460
460
|
path = resolveWorkspaceModule(workspace, `${name}/package.json`);
|
|
461
461
|
} catch (error) {
|
|
462
|
-
if (!(error
|
|
462
|
+
if (!isProbeError(error)) throw error;
|
|
463
463
|
throw new ProbeError(`${name} does not publish a readable manifest`, {
|
|
464
464
|
origin: "workspace",
|
|
465
465
|
code: error.code,
|
|
@@ -536,14 +536,14 @@ function resolveWorkspaceBinary(workspace, name, command = name) {
|
|
|
536
536
|
code: "missing",
|
|
537
537
|
context: { name }
|
|
538
538
|
});
|
|
539
|
-
if (
|
|
539
|
+
if (isString(bin)) return resolve(manifest.path, "..", bin);
|
|
540
540
|
if (!isRecord(bin) || !(command in bin)) throw new ProbeError(`${name} does not publish the ${command} binary`, {
|
|
541
541
|
origin: "workspace",
|
|
542
542
|
code: "missing",
|
|
543
543
|
context: { name }
|
|
544
544
|
});
|
|
545
545
|
const entry = bin[command];
|
|
546
|
-
if (
|
|
546
|
+
if (!isString(entry)) throw new ProbeError(`${name} publishes an invalid ${command} binary`, {
|
|
547
547
|
origin: "workspace",
|
|
548
548
|
code: "malformed",
|
|
549
549
|
context: {
|
|
@@ -710,7 +710,7 @@ function matchesWorkspaceModule(path) {
|
|
|
710
710
|
* ```
|
|
711
711
|
*/
|
|
712
712
|
function matchesLiveProcess(id) {
|
|
713
|
-
if (!Number.isSafeInteger(id) || id <= 0) return true;
|
|
713
|
+
if (!isNumber(id) || !Number.isSafeInteger(id) || id <= 0) return true;
|
|
714
714
|
try {
|
|
715
715
|
process.kill(id, 0);
|
|
716
716
|
return true;
|
|
@@ -774,8 +774,8 @@ function collectWorkspaceFiles(workspace) {
|
|
|
774
774
|
* ```
|
|
775
775
|
*/
|
|
776
776
|
function describeUnknown(value) {
|
|
777
|
-
if (value
|
|
778
|
-
if (
|
|
777
|
+
if (isError(value)) return value.message;
|
|
778
|
+
if (isObject(value) && "message" in value && isString(value.message)) return value.message;
|
|
779
779
|
return String(value);
|
|
780
780
|
}
|
|
781
781
|
/**
|
|
@@ -795,7 +795,7 @@ async function guardStage(stage, operation) {
|
|
|
795
795
|
try {
|
|
796
796
|
return await operation;
|
|
797
797
|
} catch (error) {
|
|
798
|
-
if (error
|
|
798
|
+
if (isProbeError(error)) throw error;
|
|
799
799
|
throw new ProbeError(`The ${stage} stage could not serve (${describeUnknown(error)})`, {
|
|
800
800
|
origin: "instrument",
|
|
801
801
|
code: "malformed",
|
|
@@ -872,7 +872,7 @@ function findRefusedPaths(value) {
|
|
|
872
872
|
*/
|
|
873
873
|
function normalizeValue(workspace, value) {
|
|
874
874
|
const root = resolve(workspace);
|
|
875
|
-
if (
|
|
875
|
+
if (isString(value)) {
|
|
876
876
|
if (!isAbsolute(value)) return value;
|
|
877
877
|
const path = relative(root, resolve(value));
|
|
878
878
|
if (path === "") return ".";
|
|
@@ -982,14 +982,14 @@ function releaseListeners(emitter, capture) {
|
|
|
982
982
|
* ```
|
|
983
983
|
*/
|
|
984
984
|
function parseProjectConfig(text) {
|
|
985
|
-
const parsed =
|
|
986
|
-
if (!
|
|
987
|
-
const files = parsed.
|
|
988
|
-
const include = parsed.
|
|
985
|
+
const parsed = parseJSON(text);
|
|
986
|
+
if (!isRecord(parsed)) return void 0;
|
|
987
|
+
const files = parsed.files;
|
|
988
|
+
const include = parsed.include;
|
|
989
989
|
return {
|
|
990
|
-
compilerOptions: parsed.
|
|
991
|
-
...isArray(files) && files.every(
|
|
992
|
-
...isArray(include) && include.every(
|
|
990
|
+
compilerOptions: parsed.compilerOptions,
|
|
991
|
+
...isArray(files) && files.every(isString) ? { files } : {},
|
|
992
|
+
...isArray(include) && include.every(isString) ? { include } : {}
|
|
993
993
|
};
|
|
994
994
|
}
|
|
995
995
|
/**
|
|
@@ -1103,7 +1103,7 @@ var Overlay = class {
|
|
|
1103
1103
|
};
|
|
1104
1104
|
//#endregion
|
|
1105
1105
|
//#region package.json
|
|
1106
|
-
var version = "0.0.
|
|
1106
|
+
var version = "0.0.16";
|
|
1107
1107
|
var peerDependencies = {
|
|
1108
1108
|
"oxlint": "^1.82.0",
|
|
1109
1109
|
"typescript": "^6.0.3",
|
|
@@ -1278,7 +1278,7 @@ var LintStage = class {
|
|
|
1278
1278
|
if (this.#closing !== void 0) return createDestroyedError("lint stage");
|
|
1279
1279
|
const ending = this.#ending;
|
|
1280
1280
|
if (ending !== void 0) return this.#fault(`The Oxlint language server exited with ${ending}`, error, path);
|
|
1281
|
-
if (error
|
|
1281
|
+
if (isError(error)) return error;
|
|
1282
1282
|
return this.#fault(describeUnknown(error), error, path);
|
|
1283
1283
|
}
|
|
1284
1284
|
#fault(message, cause, path) {
|
|
@@ -1449,7 +1449,7 @@ var RuntimeStage = class {
|
|
|
1449
1449
|
for (const draft of subject.files) overlay.set(resolveWorkspaceFile(this.#workspace, draft.path), draft.text);
|
|
1450
1450
|
this.#revalidate(vitest);
|
|
1451
1451
|
const specification = this.#specification(subject.test);
|
|
1452
|
-
if (
|
|
1452
|
+
if (!isString(specification)) return {
|
|
1453
1453
|
stage: this.stage,
|
|
1454
1454
|
elapsed: Math.round(performance.now() - started),
|
|
1455
1455
|
issues: [specification]
|
|
@@ -1466,7 +1466,7 @@ var RuntimeStage = class {
|
|
|
1466
1466
|
const result = await vitest.runTestSpecifications([task], false);
|
|
1467
1467
|
issues = [...this.#issues(result, file, subject.test.path), ...this.#misses(project, file)];
|
|
1468
1468
|
} catch (error) {
|
|
1469
|
-
if (error
|
|
1469
|
+
if (isProbeError(error)) throw error;
|
|
1470
1470
|
throw new ProbeError(`The runtime stage could not run the generated specification (${describeUnknown(error)})`, {
|
|
1471
1471
|
origin: "instrument",
|
|
1472
1472
|
code: "malformed",
|
|
@@ -1487,7 +1487,7 @@ var RuntimeStage = class {
|
|
|
1487
1487
|
if (existsSync(contained)) unlinkSync(contained);
|
|
1488
1488
|
} catch (error) {
|
|
1489
1489
|
cleanup = [...cleanup, {
|
|
1490
|
-
origin: error
|
|
1490
|
+
origin: isProbeError(error) && error.origin === "workspace" ? "workspace" : "instrument",
|
|
1491
1491
|
path: relativeWorkspaceFile(this.#workspace, file),
|
|
1492
1492
|
message: `The runtime stage could not delete the generated specification (${describeUnknown(error)})`
|
|
1493
1493
|
}];
|
|
@@ -1566,7 +1566,7 @@ var RuntimeStage = class {
|
|
|
1566
1566
|
test.projects = test.projects.map((project) => this.#augment(project));
|
|
1567
1567
|
}
|
|
1568
1568
|
#augment(project) {
|
|
1569
|
-
if (
|
|
1569
|
+
if (isString(project)) return project;
|
|
1570
1570
|
if (typeof project === "function") return this.#wrap(project);
|
|
1571
1571
|
return Promise.resolve(project).then(this.#instrument.bind(this));
|
|
1572
1572
|
}
|
|
@@ -1634,7 +1634,7 @@ var RuntimeStage = class {
|
|
|
1634
1634
|
return file;
|
|
1635
1635
|
});
|
|
1636
1636
|
if (outcome.success) return outcome.value;
|
|
1637
|
-
if (outcome.error
|
|
1637
|
+
if (isProbeError(outcome.error) && outcome.error.origin === "claimant") throw new ProbeError(outcome.error.message, {
|
|
1638
1638
|
origin: outcome.error.origin,
|
|
1639
1639
|
code: outcome.error.code,
|
|
1640
1640
|
context: {
|
|
@@ -1653,7 +1653,7 @@ var RuntimeStage = class {
|
|
|
1653
1653
|
cause: outcome.error
|
|
1654
1654
|
});
|
|
1655
1655
|
return {
|
|
1656
|
-
origin: outcome.error
|
|
1656
|
+
origin: isProbeError(outcome.error) && outcome.error.origin === "workspace" || creating ? "workspace" : "instrument",
|
|
1657
1657
|
path: test.path,
|
|
1658
1658
|
message: `The runtime stage could not write the generated specification (${describeUnknown(outcome.error)})`
|
|
1659
1659
|
};
|
|
@@ -1913,29 +1913,29 @@ var RuntimeStage = class {
|
|
|
1913
1913
|
}
|
|
1914
1914
|
#issue(error, specification, original) {
|
|
1915
1915
|
const message = relativeWorkspaceMessage(this.#workspace, describeUnknown(error)).replaceAll(basename(specification), basename(original));
|
|
1916
|
-
if (
|
|
1916
|
+
if (!isObject(error) || !("stacks" in error)) return {
|
|
1917
1917
|
origin: "claimant",
|
|
1918
1918
|
path: original,
|
|
1919
1919
|
message
|
|
1920
1920
|
};
|
|
1921
1921
|
const stacks = error.stacks;
|
|
1922
|
-
if (!
|
|
1922
|
+
if (!isArray(stacks)) return {
|
|
1923
1923
|
origin: "claimant",
|
|
1924
1924
|
path: original,
|
|
1925
1925
|
message
|
|
1926
1926
|
};
|
|
1927
1927
|
for (const stack of stacks) {
|
|
1928
|
-
if (
|
|
1929
|
-
if (!("file" in stack) ||
|
|
1928
|
+
if (!isObject(stack)) continue;
|
|
1929
|
+
if (!("file" in stack) || !isString(stack.file)) continue;
|
|
1930
1930
|
const declared = stack.file.startsWith("file:") ? fileURLToPath(stack.file) : isAbsolute(stack.file) ? stack.file : resolve(this.#workspace, stack.file);
|
|
1931
1931
|
const reported = this.#real(declared);
|
|
1932
1932
|
const path = reported === specification ? original : relativeWorkspaceFile(this.#real(this.#workspace), reported);
|
|
1933
|
-
if (!("line" in stack) ||
|
|
1933
|
+
if (!("line" in stack) || !isNumber(stack.line)) return {
|
|
1934
1934
|
origin: "claimant",
|
|
1935
1935
|
path,
|
|
1936
1936
|
message
|
|
1937
1937
|
};
|
|
1938
|
-
const character = "column" in stack &&
|
|
1938
|
+
const character = "column" in stack && isNumber(stack.column) ? stack.column - 1 : 0;
|
|
1939
1939
|
const position = {
|
|
1940
1940
|
line: stack.line - 1,
|
|
1941
1941
|
character
|
|
@@ -2581,7 +2581,7 @@ var Probe = class {
|
|
|
2581
2581
|
this.#emitter.emit("prove", verdict);
|
|
2582
2582
|
return verdict;
|
|
2583
2583
|
} catch (error) {
|
|
2584
|
-
if (!(error
|
|
2584
|
+
if (!isProbeError(error) || !this.#surfaced.has(error)) this.#emitter.emit("error", error);
|
|
2585
2585
|
throw error;
|
|
2586
2586
|
}
|
|
2587
2587
|
}
|
|
@@ -2626,7 +2626,7 @@ var Probe = class {
|
|
|
2626
2626
|
this.#emitter.emit("arm", this.#toolchain);
|
|
2627
2627
|
}
|
|
2628
2628
|
#surface(error) {
|
|
2629
|
-
if (error
|
|
2629
|
+
if (isProbeError(error)) this.#surfaced.add(error);
|
|
2630
2630
|
this.#emitter.emit("error", error);
|
|
2631
2631
|
}
|
|
2632
2632
|
#workbench() {
|
|
@@ -2636,7 +2636,7 @@ var Probe = class {
|
|
|
2636
2636
|
try {
|
|
2637
2637
|
mkdirSync(resolveWorkspaceFile(this.#workspace, path, true), { recursive: true });
|
|
2638
2638
|
} catch (error) {
|
|
2639
|
-
const code = error
|
|
2639
|
+
const code = isProbeError(error) && error.origin === "workspace" ? error.code : "malformed";
|
|
2640
2640
|
throw new ProbeError(`The probe could not create the boot workbench (${describeUnknown(error)})`, {
|
|
2641
2641
|
origin: "workspace",
|
|
2642
2642
|
code,
|
|
@@ -2872,12 +2872,12 @@ var Probe = class {
|
|
|
2872
2872
|
try {
|
|
2873
2873
|
await this.#bound(() => stage.destroy(), `The ${stage.stage} stage teardown exceeded ${this.#deadline} ms`, stage, stage.progress);
|
|
2874
2874
|
} catch (error) {
|
|
2875
|
-
if (!(error
|
|
2875
|
+
if (!isProbeError(error) || !this.#deadlines.has(error)) throw error;
|
|
2876
2876
|
}
|
|
2877
2877
|
}
|
|
2878
2878
|
#version(name) {
|
|
2879
2879
|
const version = readWorkspaceManifest(this.#workspace, name).contents.version;
|
|
2880
|
-
if (
|
|
2880
|
+
if (!isString(version)) throw new ProbeError(`${name} publishes no readable version`, {
|
|
2881
2881
|
origin: "workspace",
|
|
2882
2882
|
code: "malformed",
|
|
2883
2883
|
context: { name }
|