@systemfsoftware/stryker-js-cli 7.0.0 → 8.0.0
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/CHANGELOG.md +23 -0
- package/dist/Reporter-Bx0LTTkQ.mjs +31690 -0
- package/dist/compiler-CyKSVP2x.mjs +27429 -0
- package/dist/dist-Bn6hT7sW.mjs +5056 -0
- package/dist/esm-shims-z34yX56b.mjs +12 -0
- package/dist/main.mjs +8188 -601
- package/dist/node-7-yHBdZ2.mjs +27485 -0
- package/dist/parser.wasm32-wasi.wasm +0 -0
- package/dist/reporters/html.mjs +77 -0
- package/dist/rolldown-runtime-Dr7-SnC6.mjs +45 -0
- package/dist/wasm-CmiFEbUB.mjs +12995 -0
- package/dist/worker-runtime-CU41J_c_.mjs +697 -0
- package/dist/workers/checker-worker.mjs +17 -28
- package/dist/workers/child-process-test-runner-worker.mjs +25 -38
- package/package.json +23 -22
- package/dist/node-B7U4hEuW.mjs +0 -107
- package/dist/worker-runtime-CT5LMMgY.mjs +0 -20
|
@@ -1,31 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import * as Layer from "effect/Layer";
|
|
5
|
-
import * as Option from "effect/Option";
|
|
6
|
-
import * as Path from "effect/Path";
|
|
7
|
-
import * as FileSystem from "effect/FileSystem";
|
|
8
|
-
import { NodeFileSystem, NodePath, NodeSocketServer } from "@effect/platform-node";
|
|
9
|
-
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
|
|
10
|
-
import { Checker, CheckerFailed } from "@systemfsoftware/stryker-js/Checker";
|
|
11
|
-
import { RunConfiguration, SandboxDirectory } from "@systemfsoftware/stryker-js/Plugin";
|
|
12
|
-
import * as HashMap from "effect/HashMap";
|
|
13
|
-
import * as RpcServer from "effect/unstable/rpc/RpcServer";
|
|
14
|
-
import { CheckerRpcs, create, decodeWorkerOptions, loadPlugins } from "@systemfsoftware/stryker-js-engine/worker";
|
|
1
|
+
import { Ar as fail, Cs as match, Dr as die, Mr as flatMap, Pr as forEach, Vr as gen, ei as map, fa as mergeAll, fi as provide, g as SandboxDirectory, h as RunConfiguration, ha as succeed, ki as succeed$1, nn as Path, on as FileSystem, pa as provide$1 } from "../Reporter-Bx0LTTkQ.mjs";
|
|
2
|
+
import { H as CheckerFailed, I as loadPlugins, N as create, P as decodeWorkerOptions, V as Checker, X as layerNdjson, i as layer, k as CheckerRpcs, r as layer$1, t as nodeModuleLayer, vt as fromIterable, yt as get } from "../node-7-yHBdZ2.mjs";
|
|
3
|
+
import { a as layerProtocolSocketServer, i as layer$2, n as workerSocketPath, r as layer$3, t as launchWorker } from "../worker-runtime-CU41J_c_.mjs";
|
|
15
4
|
//#region src/workers/Checker.worker.ts
|
|
16
|
-
const buildChecker = (contribution, options) => Checker.pipe(
|
|
5
|
+
const buildChecker = (contribution, options) => Checker.pipe(provide(contribution.layer.pipe(provide$1(mergeAll(succeed(RunConfiguration, options), succeed(SandboxDirectory, process.cwd()), layer, layer$1, nodeModuleLayer)))));
|
|
17
6
|
const mutantIdsOf = (mutants) => mutants.map((mutant) => mutant.id);
|
|
18
|
-
const readWorkerOptions =
|
|
19
|
-
const workerDir = process.env["STRYKER_WORKER_DIR"] ?? (yield*
|
|
20
|
-
const fs = yield* FileSystem
|
|
21
|
-
const path = yield* Path
|
|
7
|
+
const readWorkerOptions = gen(function* () {
|
|
8
|
+
const workerDir = process.env["STRYKER_WORKER_DIR"] ?? (yield* die(/* @__PURE__ */ new Error("STRYKER_WORKER_DIR is not set")));
|
|
9
|
+
const fs = yield* FileSystem;
|
|
10
|
+
const path = yield* Path;
|
|
22
11
|
const raw = yield* fs.readFileString(path.join(workerDir, "options.json"));
|
|
23
12
|
return yield* decodeWorkerOptions(raw);
|
|
24
13
|
});
|
|
25
|
-
const CheckerHandlers = CheckerRpcs.toLayer(
|
|
14
|
+
const CheckerHandlers = CheckerRpcs.toLayer(gen(function* () {
|
|
26
15
|
const options = yield* readWorkerOptions;
|
|
27
16
|
const loaded = yield* loadPlugins(options.plugins, process.cwd());
|
|
28
|
-
const checkers =
|
|
17
|
+
const checkers = fromIterable(yield* forEach(options.checkers, (name) => gen(function* () {
|
|
29
18
|
const contribution = yield* create(loaded.pluginsByKind, "Checker", name);
|
|
30
19
|
const checker = yield* buildChecker(contribution, options);
|
|
31
20
|
yield* checker.init;
|
|
@@ -34,20 +23,20 @@ const CheckerHandlers = CheckerRpcs.toLayer(Effect.gen(function* () {
|
|
|
34
23
|
concurrency: "unbounded",
|
|
35
24
|
discard: false
|
|
36
25
|
}));
|
|
37
|
-
const resolve = (checkerName, mutants) =>
|
|
38
|
-
onNone: () =>
|
|
26
|
+
const resolve = (checkerName, mutants) => match(get(checkers, checkerName), {
|
|
27
|
+
onNone: () => fail(new CheckerFailed({
|
|
39
28
|
cause: `Checker ${checkerName} does not exist`,
|
|
40
29
|
checkerName,
|
|
41
30
|
mutantIds: mutantIdsOf(mutants)
|
|
42
31
|
})),
|
|
43
|
-
onSome: (checker) =>
|
|
32
|
+
onSome: (checker) => succeed$1(checker)
|
|
44
33
|
});
|
|
45
34
|
return {
|
|
46
|
-
check: ({ checkerName, mutants }) => resolve(checkerName, mutants).pipe(
|
|
47
|
-
group: ({ checkerName, mutants }) => resolve(checkerName, mutants).pipe(
|
|
35
|
+
check: ({ checkerName, mutants }) => resolve(checkerName, mutants).pipe(flatMap((checker) => checker.check([...mutants])), map((resultMap) => Object.fromEntries(resultMap))),
|
|
36
|
+
group: ({ checkerName, mutants }) => resolve(checkerName, mutants).pipe(flatMap((checker) => checker.group([...mutants])))
|
|
48
37
|
};
|
|
49
|
-
})).pipe(
|
|
50
|
-
const MainLayer =
|
|
38
|
+
})).pipe(provide$1(mergeAll(layer, layer$1)));
|
|
39
|
+
const MainLayer = layer$2(CheckerRpcs).pipe(provide$1(CheckerHandlers), provide$1(layerProtocolSocketServer), provide$1(layerNdjson), provide$1(layer$3({ path: workerSocketPath("checker worker") })), provide$1(nodeModuleLayer));
|
|
51
40
|
launchWorker(MainLayer, "checker worker");
|
|
52
41
|
//#endregion
|
|
53
42
|
export {};
|
|
@@ -1,24 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import * as Layer from "effect/Layer";
|
|
5
|
-
import * as Option from "effect/Option";
|
|
6
|
-
import { errorToString } from "@systemfsoftware/stryker-js/Mutant";
|
|
7
|
-
import * as Cause from "effect/Cause";
|
|
8
|
-
import * as Path from "effect/Path";
|
|
9
|
-
import * as FileSystem from "effect/FileSystem";
|
|
10
|
-
import { NodeFileSystem, NodePath, NodeSocketServer } from "@effect/platform-node";
|
|
11
|
-
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
|
|
12
|
-
import { RunConfiguration, SandboxDirectory } from "@systemfsoftware/stryker-js/Plugin";
|
|
13
|
-
import * as RpcServer from "effect/unstable/rpc/RpcServer";
|
|
14
|
-
import { MutantCoverageSchema, TestRunnerRpcs, create, decodeWorkerOptions, loadPlugins } from "@systemfsoftware/stryker-js-engine/worker";
|
|
15
|
-
import { TestRunner, TestRunnerFailed } from "@systemfsoftware/stryker-js/TestRunner";
|
|
16
|
-
import { Match, Schema } from "effect";
|
|
1
|
+
import { Ar as fail, Cs as match, Dr as die, Hr as ignore, Mr as flatMap, Ot as optional, Ss as map, Vr as gen, Vt as exhaustive, Xt as value, Zt as when, _r as catchCause, cs as exists, da as merge, dt as decodeUnknownEffect, ei as map$1, fa as mergeAll, fi as provide, g as SandboxDirectory, h as RunConfiguration, ha as succeed$1, ki as succeed, ms as getOrElse, nn as Path, on as FileSystem, pa as provide$1, ps as fromUndefinedOr, to as pretty, ui as orElseSucceed, ur as addFinalizer, w as TestRunnerFailed, xs as liftPredicate } from "../Reporter-Bx0LTTkQ.mjs";
|
|
2
|
+
import { B as errorToString, I as loadPlugins, M as TestRunnerRpcs, N as create, P as decodeWorkerOptions, R as TestRunner, X as layerNdjson, i as layer, j as MutantCoverageSchema, r as layer$1, t as nodeModuleLayer } from "../node-7-yHBdZ2.mjs";
|
|
3
|
+
import { a as layerProtocolSocketServer, i as layer$2, n as workerSocketPath, r as layer$3, t as launchWorker } from "../worker-runtime-CU41J_c_.mjs";
|
|
17
4
|
//#region src/workers/child-process-test-runner-worker.ts
|
|
18
5
|
const isCompleteDryRun = (result) => result.status === "complete";
|
|
19
6
|
const COVERAGE_SETTLED = [
|
|
20
7
|
(result) => result.status !== "complete",
|
|
21
|
-
(result) =>
|
|
8
|
+
(result) => exists(liftPredicate(result, isCompleteDryRun), (complete) => complete.mutantCoverage !== void 0),
|
|
22
9
|
(_result, options) => options.coverageAnalysis === "off"
|
|
23
10
|
];
|
|
24
11
|
const coverageNeeded = (result, options) => !COVERAGE_SETTLED.some((settled) => settled(result, options));
|
|
@@ -29,17 +16,17 @@ const normalizeDryRun = (result) => {
|
|
|
29
16
|
};
|
|
30
17
|
return result;
|
|
31
18
|
};
|
|
32
|
-
const decodeCoverageInto = (result) =>
|
|
33
|
-
const decoded = yield*
|
|
34
|
-
return
|
|
19
|
+
const decodeCoverageInto = (result) => gen(function* () {
|
|
20
|
+
const decoded = yield* decodeUnknownEffect(optional(MutantCoverageSchema))(globalThis.__mutantCoverage__).pipe(orElseSucceed(() => void 0));
|
|
21
|
+
return match(liftPredicate(result, isCompleteDryRun), {
|
|
35
22
|
onNone: () => normalizeDryRun(result),
|
|
36
|
-
onSome: (complete) =>
|
|
23
|
+
onSome: (complete) => getOrElse(map(fromUndefinedOr(decoded), (coverage) => ({
|
|
37
24
|
...complete,
|
|
38
25
|
mutantCoverage: coverage
|
|
39
26
|
})), () => complete)
|
|
40
27
|
});
|
|
41
28
|
});
|
|
42
|
-
const withCoverage = (result, options) =>
|
|
29
|
+
const withCoverage = (result, options) => value(coverageNeeded(result, options)).pipe(when(true, () => decodeCoverageInto(result)), when(false, () => succeed(normalizeDryRun(result))), exhaustive);
|
|
43
30
|
const normalizeMutantRun = (result) => {
|
|
44
31
|
if (result.status === "error") return {
|
|
45
32
|
...result,
|
|
@@ -47,32 +34,32 @@ const normalizeMutantRun = (result) => {
|
|
|
47
34
|
};
|
|
48
35
|
return result;
|
|
49
36
|
};
|
|
50
|
-
const readWorkerOptions =
|
|
51
|
-
const workerDir = process.env["STRYKER_WORKER_DIR"] ?? (yield*
|
|
52
|
-
const fs = yield* FileSystem
|
|
53
|
-
const path = yield* Path
|
|
37
|
+
const readWorkerOptions = gen(function* () {
|
|
38
|
+
const workerDir = process.env["STRYKER_WORKER_DIR"] ?? (yield* die(/* @__PURE__ */ new Error("STRYKER_WORKER_DIR is not set")));
|
|
39
|
+
const fs = yield* FileSystem;
|
|
40
|
+
const path = yield* Path;
|
|
54
41
|
const raw = yield* fs.readFileString(path.join(workerDir, "options.json"));
|
|
55
42
|
return yield* decodeWorkerOptions(raw);
|
|
56
43
|
});
|
|
57
|
-
const TestRunnerHandlers = TestRunnerRpcs.toLayer(
|
|
44
|
+
const TestRunnerHandlers = TestRunnerRpcs.toLayer(gen(function* () {
|
|
58
45
|
const options = yield* readWorkerOptions;
|
|
59
46
|
const runnerName = options.testRunner;
|
|
60
|
-
const failed = (phase) => (cause) =>
|
|
61
|
-
cause:
|
|
47
|
+
const failed = (phase) => (cause) => fail(new TestRunnerFailed({
|
|
48
|
+
cause: pretty(cause),
|
|
62
49
|
phase,
|
|
63
50
|
runnerName
|
|
64
51
|
}));
|
|
65
|
-
const loaded = yield* loadPlugins(options.plugins, process.cwd()).pipe(
|
|
66
|
-
const underlying = yield* create(loaded.pluginsByKind, "TestRunner", runnerName).pipe(
|
|
67
|
-
yield* underlying.init.pipe(
|
|
68
|
-
yield*
|
|
52
|
+
const loaded = yield* loadPlugins(options.plugins, process.cwd()).pipe(catchCause(failed("init")));
|
|
53
|
+
const underlying = yield* create(loaded.pluginsByKind, "TestRunner", runnerName).pipe(flatMap((contribution) => TestRunner.pipe(provide(contribution.layer))), provide(merge(succeed$1(RunConfiguration, options), succeed$1(SandboxDirectory, process.cwd()))), catchCause(failed("init")));
|
|
54
|
+
yield* underlying.init.pipe(catchCause(failed("init")));
|
|
55
|
+
yield* addFinalizer(() => underlying.dispose.pipe(ignore));
|
|
69
56
|
return {
|
|
70
|
-
capabilities: () => underlying.capabilities.pipe(
|
|
71
|
-
dryRun: ({ options: runOptions }) => underlying.dryRun(runOptions).pipe(
|
|
72
|
-
mutantRun: ({ options: runOptions }) => underlying.mutantRun(runOptions).pipe(
|
|
57
|
+
capabilities: () => underlying.capabilities.pipe(catchCause(failed("capabilities"))),
|
|
58
|
+
dryRun: ({ options: runOptions }) => underlying.dryRun(runOptions).pipe(flatMap((result) => withCoverage(result, runOptions)), catchCause(failed("dryRun"))),
|
|
59
|
+
mutantRun: ({ options: runOptions }) => underlying.mutantRun(runOptions).pipe(map$1(normalizeMutantRun), catchCause(failed("mutantRun")))
|
|
73
60
|
};
|
|
74
|
-
})).pipe(
|
|
75
|
-
const MainLayer =
|
|
61
|
+
})).pipe(provide$1(mergeAll(layer, layer$1)));
|
|
62
|
+
const MainLayer = layer$2(TestRunnerRpcs).pipe(provide$1(TestRunnerHandlers), provide$1(layerProtocolSocketServer), provide$1(layerNdjson), provide$1(layer$3({ path: workerSocketPath("test runner worker") })), provide$1(nodeModuleLayer));
|
|
76
63
|
launchWorker(MainLayer, "test runner worker");
|
|
77
64
|
//#endregion
|
|
78
65
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@systemfsoftware/stryker-js-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/systemfsoftware/systemfsoftware.git",
|
|
@@ -13,40 +13,41 @@
|
|
|
13
13
|
"files": [
|
|
14
14
|
"dist"
|
|
15
15
|
],
|
|
16
|
-
"
|
|
16
|
+
"devDependencies": {
|
|
17
17
|
"@effect/platform-node": "4.0.0-rc.112",
|
|
18
18
|
"@effect/platform-node-shared": "4.0.0-rc.112",
|
|
19
|
-
"@noble/hashes": "
|
|
20
|
-
"
|
|
21
|
-
"@systemfsoftware/
|
|
22
|
-
"@systemfsoftware/stryker-js": "^3.0.0",
|
|
23
|
-
"@systemfsoftware/stryker-js-engine": "^2.0.0",
|
|
24
|
-
"@systemfsoftware/stryker-js-html-reporter": "^3.0.0"
|
|
25
|
-
},
|
|
26
|
-
"devDependencies": {
|
|
27
|
-
"@systemfsoftware/arethetypeswrong-cli": "^1.1.1",
|
|
19
|
+
"@noble/hashes": "2.4.0",
|
|
20
|
+
"@oxc-parser/binding-wasm32-wasi": "^0.140.0",
|
|
21
|
+
"@systemfsoftware/arethetypeswrong-cli": "^4.1.0",
|
|
28
22
|
"@types/node": "^24",
|
|
29
23
|
"@vitest/coverage-v8": "^4",
|
|
24
|
+
"effect": "4.0.0-rc.112",
|
|
25
|
+
"mutation-testing-elements": "3.7.3",
|
|
26
|
+
"oxc-parser": "^0.140.0",
|
|
30
27
|
"oxlint": "^1.77.0",
|
|
31
28
|
"rimraf": "^6.1.3",
|
|
32
29
|
"testcontainers": "^12.1.0",
|
|
33
30
|
"tsdown": "^0.22.14",
|
|
34
31
|
"vite-tsconfig-paths": "^6.1.1",
|
|
35
32
|
"vitest": "^4",
|
|
36
|
-
"@systemfsoftware/
|
|
37
|
-
"@systemfsoftware/
|
|
38
|
-
"@systemfsoftware/effect-
|
|
39
|
-
"@systemfsoftware/effect-schema-law": "^2.0.2",
|
|
40
|
-
"@systemfsoftware/stryker-js-typescript-checker": "^5.0.1",
|
|
33
|
+
"@systemfsoftware/all": "^2.0.1",
|
|
34
|
+
"@systemfsoftware/effect-schema-law": "^2.1.1",
|
|
35
|
+
"@systemfsoftware/effect-cell-types": "^7.0.1",
|
|
41
36
|
"@systemfsoftware/oxlint-config": "^0.1.0",
|
|
42
|
-
"@systemfsoftware/
|
|
43
|
-
"@systemfsoftware/stryker-
|
|
44
|
-
"@systemfsoftware/
|
|
45
|
-
"@systemfsoftware/stryker-
|
|
46
|
-
"@systemfsoftware/
|
|
37
|
+
"@systemfsoftware/effect-schema-vite": "^2.1.1",
|
|
38
|
+
"@systemfsoftware/stryker-js": "^3.0.2",
|
|
39
|
+
"@systemfsoftware/effect-gherkin-spec": "^4.0.2",
|
|
40
|
+
"@systemfsoftware/stryker-js-engine": "^3.0.0",
|
|
41
|
+
"@systemfsoftware/stryker-js-html-reporter": "^3.0.2",
|
|
42
|
+
"@systemfsoftware/stryker-js-typescript-checker": "^5.0.3",
|
|
43
|
+
"@systemfsoftware/stryker-js-vitest-runner": "^4.0.3",
|
|
44
|
+
"@systemfsoftware/stryker-plugins": "^3.0.2",
|
|
45
|
+
"@systemfsoftware/stryker-test-contribution": "^2.0.2",
|
|
46
|
+
"@systemfsoftware/vitest-config": "^0.1.0",
|
|
47
|
+
"@systemfsoftware/tsconfig": "^1.3.4"
|
|
47
48
|
},
|
|
48
49
|
"engines": {
|
|
49
|
-
"node": ">=20.
|
|
50
|
+
"node": ">=20.19.0"
|
|
50
51
|
},
|
|
51
52
|
"license": "Apache-2.0",
|
|
52
53
|
"publishConfig": {
|
package/dist/node-B7U4hEuW.mjs
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import * as Effect from "effect/Effect";
|
|
2
|
-
import * as Layer from "effect/Layer";
|
|
3
|
-
import * as Option from "effect/Option";
|
|
4
|
-
import * as NodeChildProcessSpawner from "@effect/platform-node-shared/NodeChildProcessSpawner";
|
|
5
|
-
import { ChildProcessCrashedError, WorkerEntries, WorkerLauncher } from "@systemfsoftware/stryker-js-engine";
|
|
6
|
-
import * as Match from "effect/Match";
|
|
7
|
-
import * as Path from "effect/Path";
|
|
8
|
-
import * as FileSystem from "effect/FileSystem";
|
|
9
|
-
import { NodeFileSystem, NodePath, NodeSocket } from "@effect/platform-node";
|
|
10
|
-
import { Module } from "@systemfsoftware/stryker-js/Module";
|
|
11
|
-
import * as ChildProcess from "effect/unstable/process/ChildProcess";
|
|
12
|
-
import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner";
|
|
13
|
-
import * as RpcClient from "effect/unstable/rpc/RpcClient";
|
|
14
|
-
import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
|
|
15
|
-
//#region src/platform/node.ts
|
|
16
|
-
const EMPTY_PATHS = [];
|
|
17
|
-
const makeModuleRequire = (nodeModule, filename) => {
|
|
18
|
-
const requireFrom = nodeModule.createRequire(filename);
|
|
19
|
-
const requireFn = (request) => requireFrom(request);
|
|
20
|
-
requireFn.resolve = (request, options) => Option.match(Option.fromUndefinedOr(options), {
|
|
21
|
-
onNone: () => requireFrom.resolve(request),
|
|
22
|
-
onSome: (present) => requireFrom.resolve(request, { paths: [...Option.getOrElse(Option.fromNullishOr(present.paths), () => EMPTY_PATHS)] })
|
|
23
|
-
});
|
|
24
|
-
return requireFn;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* The Node implementation of the {@link Module} port: every call routes
|
|
28
|
-
* through the runtime's own `node:module` via `process.getBuiltinModule`, so
|
|
29
|
-
* this package imports no host builtins and the import ban holds here too.
|
|
30
|
-
*/
|
|
31
|
-
const nodeModuleLayer = Layer.effect(Module, Effect.sync(() => {
|
|
32
|
-
const nodeModule = process.getBuiltinModule("node:module");
|
|
33
|
-
return {
|
|
34
|
-
createRequire: (filename) => makeModuleRequire(nodeModule, filename),
|
|
35
|
-
isBuiltin: (moduleName) => nodeModule.isBuiltin(moduleName)
|
|
36
|
-
};
|
|
37
|
-
}));
|
|
38
|
-
/**
|
|
39
|
-
* The worker entries this package's own build emits. The engine spawns by
|
|
40
|
-
* address; this process package knows its dist layout and hands the
|
|
41
|
-
* addresses in.
|
|
42
|
-
*/
|
|
43
|
-
const workerEntriesLayer = Layer.succeed(WorkerEntries, {
|
|
44
|
-
checkerWorkerUrl: new URL("./workers/checker-worker.mjs", import.meta.url),
|
|
45
|
-
testRunnerWorkerUrl: new URL("./workers/child-process-test-runner-worker.mjs", import.meta.url)
|
|
46
|
-
});
|
|
47
|
-
/**
|
|
48
|
-
* The Node worker launcher: spawn a worker child with this runtime's
|
|
49
|
-
* executable, host the RPC server's address as a `net` `path` endpoint (a
|
|
50
|
-
* socket file in the worker directory on POSIX, a same-user named pipe on
|
|
51
|
-
* Windows), and connect the NDJSON protocol client over `NodeSocket`.
|
|
52
|
-
*/
|
|
53
|
-
const nodeWorkerLauncherLayer = Layer.effect(WorkerLauncher, Effect.gen(function* () {
|
|
54
|
-
const fs = yield* FileSystem.FileSystem;
|
|
55
|
-
const path = yield* Path.Path;
|
|
56
|
-
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
57
|
-
return { spawn: (params) => Effect.gen(function* () {
|
|
58
|
-
const workerDir = yield* fs.makeTempDirectoryScoped({ prefix: params.tempDirPrefix });
|
|
59
|
-
const socketPath = Match.value(process.platform).pipe(Match.when("win32", () => `\\\\.\\pipe\\stryker-worker-${globalThis.crypto.randomUUID()}`), Match.orElse(() => path.join(workerDir, "worker.sock")));
|
|
60
|
-
yield* fs.writeFileString(path.join(workerDir, "options.json"), params.optionsJson);
|
|
61
|
-
const entryPath = yield* path.fromFileUrl(params.entryUrl);
|
|
62
|
-
const handle = yield* ChildProcess.make(process.execPath, [...params.execArgv, entryPath], {
|
|
63
|
-
cwd: params.workingDirectory,
|
|
64
|
-
extendEnv: true,
|
|
65
|
-
env: {
|
|
66
|
-
STRYKER_WORKER_DIR: workerDir,
|
|
67
|
-
STRYKER_SOCKET: socketPath
|
|
68
|
-
},
|
|
69
|
-
stderr: "inherit"
|
|
70
|
-
}).pipe(Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner));
|
|
71
|
-
const clientLayer = RpcClient.layerProtocolSocket({ retryTransientErrors: true }).pipe(Layer.provide(NodeSocket.layerNet({ path: socketPath })), Layer.provide(RpcSerialization.layerNdjson));
|
|
72
|
-
const exited = handle.exitCode.pipe(Effect.orDie, Effect.flatMap((exitCode) => Effect.fail(new ChildProcessCrashedError({
|
|
73
|
-
pid: Number(handle.pid),
|
|
74
|
-
exit: {
|
|
75
|
-
_tag: "Code",
|
|
76
|
-
code: exitCode
|
|
77
|
-
},
|
|
78
|
-
cause: "worker exited before it accepted the RPC connection"
|
|
79
|
-
}))));
|
|
80
|
-
return {
|
|
81
|
-
pid: Number(handle.pid),
|
|
82
|
-
clientLayer,
|
|
83
|
-
exited
|
|
84
|
-
};
|
|
85
|
-
}).pipe(Effect.catch((error) => {
|
|
86
|
-
if (error instanceof ChildProcessCrashedError) return Effect.fail(error);
|
|
87
|
-
return Effect.fail(new ChildProcessCrashedError({
|
|
88
|
-
pid: 0,
|
|
89
|
-
exit: {
|
|
90
|
-
_tag: "Code",
|
|
91
|
-
code: 1
|
|
92
|
-
},
|
|
93
|
-
cause: "worker spawn failed"
|
|
94
|
-
}));
|
|
95
|
-
})) };
|
|
96
|
-
}));
|
|
97
|
-
const nodeFsPathLayer = Layer.mergeAll(NodeFileSystem.layer, NodePath.layer);
|
|
98
|
-
const nodeSpawnerLayer = NodeChildProcessSpawner.layer.pipe(Layer.provide(nodeFsPathLayer));
|
|
99
|
-
const nodeBase = Layer.merge(nodeFsPathLayer, nodeSpawnerLayer);
|
|
100
|
-
/**
|
|
101
|
-
* Every port the engine requires, provided from this runtime: the file
|
|
102
|
-
* system, the path service, the module loader, the child-process spawner,
|
|
103
|
-
* the worker launcher, and this build's worker entry addresses.
|
|
104
|
-
*/
|
|
105
|
-
const nodePlatformLayer = Layer.mergeAll(nodeModuleLayer, workerEntriesLayer, nodeWorkerLauncherLayer.pipe(Layer.provide(nodeBase)), nodeBase);
|
|
106
|
-
//#endregion
|
|
107
|
-
export { nodePlatformLayer as n, nodeModuleLayer as t };
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import * as Effect from "effect/Effect";
|
|
2
|
-
import * as Layer from "effect/Layer";
|
|
3
|
-
import * as Cause from "effect/Cause";
|
|
4
|
-
//#region src/workers/worker-runtime.ts
|
|
5
|
-
const workerSocketPath = (label) => {
|
|
6
|
-
const socketPath = process.env["STRYKER_SOCKET"];
|
|
7
|
-
if (socketPath === void 0) {
|
|
8
|
-
process.stderr.write(`${label}: STRYKER_SOCKET is not set\n`);
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
return socketPath;
|
|
12
|
-
};
|
|
13
|
-
const launchWorker = (main, label) => {
|
|
14
|
-
Effect.runFork(Layer.launch(main).pipe(Effect.tapCause((cause) => Effect.sync(() => {
|
|
15
|
-
process.stderr.write(`${label}: ${Cause.pretty(cause)}\n`);
|
|
16
|
-
process.exitCode = 1;
|
|
17
|
-
}))));
|
|
18
|
-
};
|
|
19
|
-
//#endregion
|
|
20
|
-
export { workerSocketPath as n, launchWorker as t };
|