@systemfsoftware/stryker-js 10.0.0 → 10.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { $ as WorkerPluginKind, F as MutationTestingPlanReady, G as TRACEPARENT_HEADER, I as NonNegativeInt, J as TestRunnerFailed, K as TRACESTATE_HEADER, L as PropagatedTrace, M as MutantTested, N as MutationTestReportReady, O as Metrics, P as MutationTestResultSchema$1, Q as WorkerEntryUrl, S as CheckerMutantWire, T as DryRunCompleted, U as ReporterRpcs, V as ReporterFailed, W as StrykerOptionsSchema, X as TraceContextMiddleware, Y as TestRunnerRpcs, Z as TraceContextReference, _ as RunStarted, c as PhaseEntered, dt as errorToString, et as formatTraceparent, f as RunEvent, ft as instrument, it as INSTRUMENTER_CONSTANTS, k as MetricsResultSchema, l as PlanKnown, m as RunMutantTested, n as StageError, nt as parseTraceparent, ot as Mutant, pt as normalizeFileName$4, r as Heartbeat, rt as toMutantRunResult, t as PrepareError, tt as isCustomTestRunner, ut as disableTypeChecks, v as VerdictReached, w as CheckerRpcs } from "./Run.schema-C0Cxsfe9.mjs";
1
+ import { $ as WorkerPluginKind, F as MutationTestingPlanReady, G as TRACEPARENT_HEADER, I as NonNegativeInt, J as TestRunnerFailed, K as TRACESTATE_HEADER, L as PropagatedTrace, M as MutantTested, N as MutationTestReportReady, O as Metrics, P as MutationTestResultSchema$1, Q as WorkerEntryUrl, S as CheckerMutantWire, T as DryRunCompleted, U as ReporterRpcs, V as ReporterFailed, W as StrykerOptionsSchema, X as TraceContextMiddleware, Y as TestRunnerRpcs, Z as TraceContextReference, _ as RunStarted, c as PhaseEntered, dt as errorToString, et as formatTraceparent, f as RunEvent, ft as instrument, it as INSTRUMENTER_CONSTANTS, k as MetricsResultSchema, l as PlanKnown, m as RunMutantTested, n as StageError, nt as parseTraceparent, ot as Mutant, pt as normalizeFileName$4, r as Heartbeat, rt as toMutantRunResult, t as PrepareError, tt as isCustomTestRunner, ut as disableTypeChecks, v as VerdictReached, w as CheckerRpcs } from "./Run.schema-CgVfoOfk.mjs";
2
2
  import { t as mergeConfig } from "./merge-config-BrrNQWje.mjs";
3
3
  import * as Effect$1 from "effect/Effect";
4
4
  import * as FileSystem from "effect/FileSystem";
@@ -16,12 +16,12 @@ import * as Ref from "effect/Ref";
16
16
  import * as Result from "effect/Result";
17
17
  import * as S from "effect/Schema";
18
18
  import * as Stream from "effect/Stream";
19
- import { Cell, Workflow } from "@systemfsoftware/effect-cell-types";
19
+ import { Cell, Sandwich, Workflow } from "@systemfsoftware/effect-cell-types";
20
20
  import * as Predicate from "effect/Predicate";
21
21
  import * as Array$1 from "effect/Array";
22
- import { Schema } from "effect";
22
+ import { Schema, SchemaGetter } from "effect";
23
23
  import * as RpcMiddleware from "effect/unstable/rpc/RpcMiddleware";
24
- import * as SchemaGetter from "effect/SchemaGetter";
24
+ import * as SchemaGetter$1 from "effect/SchemaGetter";
25
25
  import * as Exit from "effect/Exit";
26
26
  import * as Scope from "effect/Scope";
27
27
  import * as Duration from "effect/Duration";
@@ -52,7 +52,7 @@ import * as Equivalence from "effect/Equivalence";
52
52
  import * as Metric from "effect/Metric";
53
53
  import * as Pool from "effect/Pool";
54
54
  import * as Semaphore from "effect/Semaphore";
55
- import * as SchemaTransformation from "effect/SchemaTransformation";
55
+ import * as SchemaTransformation$1 from "effect/SchemaTransformation";
56
56
  import { randomBytes } from "@noble/hashes/utils.js";
57
57
  import * as Console from "effect/Console";
58
58
  import "effect/Sink";
@@ -142,8 +142,8 @@ const frameRunEvent = Workflow.total(FrameRunEventCommand, decideFrame);
142
142
  //#endregion
143
143
  //#region src/run-event-wire.schema.ts
144
144
  const RunEventWireLine = S.String.pipe(S.decodeTo(S.fromJsonString(RunEvent), {
145
- decode: SchemaGetter.transform((line) => line.replace(/\n$/, "")),
146
- encode: SchemaGetter.transform((json) => `${json}\n`)
145
+ decode: SchemaGetter$1.transform((line) => line.replace(/\n$/, "")),
146
+ encode: SchemaGetter$1.transform((json) => `${json}\n`)
147
147
  }));
148
148
  //#endregion
149
149
  //#region src/RunEvents.ts
@@ -915,9 +915,9 @@ Layer.succeed(TraceContextMiddleware, serverMiddleware);
915
915
  let wire;
916
916
  const workerOptionsWire = () => wire ??= S.fromJsonString(S.toCodecJson(StrykerOptionsSchema));
917
917
  const encodeWorkerOptions = (options) => S.encodeEffect(workerOptionsWire())(options).pipe(Effect$1.orDie);
918
- const decodeWorkerOptions = (raw) => S.decodeUnknownEffect(workerOptionsWire())(raw);
918
+ const decodeWorkerOptions = (raw) => S.decodeEffect(workerOptionsWire())(raw);
919
919
  Effect$1.gen(function* () {
920
- const workerDir = yield* Config.string("STRYKER_WORKER_DIR");
920
+ const workerDir = yield* Config.String("STRYKER_WORKER_DIR");
921
921
  const fs = yield* FileSystem.FileSystem;
922
922
  const path = yield* Path.Path;
923
923
  const raw = yield* fs.readFileString(path.join(workerDir, "options.json"));
@@ -936,9 +936,9 @@ const otlpLayer = (serviceName, endpoint) => NodeSdk.layer(() => ({
936
936
  spanProcessor: new SimpleSpanProcessor(new OTLPTraceExporter({ url: tracesUrl(endpoint) }))
937
937
  }));
938
938
  Layer.unwrap(Effect$1.gen(function* () {
939
- if (!(yield* Config.boolean("OTEL_ENABLED").pipe(Config.withDefault(false)))) return Layer.empty;
940
- const serviceName = yield* Config.string("OTEL_SERVICE_NAME").pipe(Config.withDefault(WORKER_SERVICE_NAME));
941
- const endpoint = yield* Config.string("OTEL_EXPORTER_OTLP_ENDPOINT").pipe(Config.withDefault(DEFAULT_ENDPOINT));
939
+ if (!(yield* Config.Boolean("OTEL_ENABLED").pipe(Config.withDefault(false)))) return Layer.empty;
940
+ const serviceName = yield* Config.String("OTEL_SERVICE_NAME").pipe(Config.withDefault(WORKER_SERVICE_NAME));
941
+ const endpoint = yield* Config.String("OTEL_EXPORTER_OTLP_ENDPOINT").pipe(Config.withDefault(DEFAULT_ENDPOINT));
942
942
  return otlpLayer(serviceName, endpoint);
943
943
  }));
944
944
  //#endregion
@@ -1202,7 +1202,7 @@ const makeWorkerClient = (params) => Effect$1.gen(function* () {
1202
1202
  });
1203
1203
  //#endregion
1204
1204
  //#region src/platform/node.ts
1205
- const restrictToOwnerOrWarn = (fs, file) => fs.chmod(file, 384).pipe(Effect$1.catchTag("PlatformError", (cause) => Effect$1.logWarning(`Could not restrict "${file}" to its owner; the worker directory's own mode still protects it.`).pipe(Effect$1.annotateLogs("cause", cause))));
1205
+ const restrictToOwnerOrWarn = (fs, file) => fs.chmod(file, 384).pipe(Effect$1.tapError((cause) => Effect$1.logWarning(`Could not restrict "${file}" to its owner; the worker directory's own mode still protects it.`).pipe(Effect$1.annotateLogs("cause", cause))), Effect$1.catchTag("PlatformError", () => Effect$1.void));
1206
1206
  /**
1207
1207
  * The Node worker launcher: spawn a worker child with this runtime's
1208
1208
  * executable, host the RPC server's address as a `net` `path` endpoint (a
@@ -1217,12 +1217,12 @@ const nodeWorkerLauncherLayer = Layer.effect(WorkerLauncher, Effect$1.gen(functi
1217
1217
  return { spawn: (params) => Effect$1.gen(function* () {
1218
1218
  const workerDir = yield* fs.makeTempDirectoryScoped({ prefix: params.tempDirPrefix });
1219
1219
  const workerId = yield* crypto.randomUUIDv4;
1220
- const socketPath = Match.value(process.platform).pipe(Match.when("win32", () => `\\\\.\\pipe\\stryker-worker-${workerId}`), Match.orElse(() => path.join(workerDir, "worker.sock")));
1220
+ const socketPath = Match.value(globalThis.process.platform).pipe(Match.when("win32", () => `\\\\.\\pipe\\stryker-worker-${workerId}`), Match.orElse(() => path.join(workerDir, "worker.sock")));
1221
1221
  const optionsFile = path.join(workerDir, "options.json");
1222
1222
  yield* fs.writeFileString(optionsFile, params.optionsJson);
1223
1223
  yield* restrictToOwnerOrWarn(fs, optionsFile);
1224
1224
  const entrypointPath = yield* path.fromFileUrl(new URL(params.entrypoint));
1225
- const handle = yield* ChildProcess.make(process.execPath, [...params.execArgv, entrypointPath], {
1225
+ const handle = yield* ChildProcess.make(globalThis.process.execPath, [...params.execArgv, entrypointPath], {
1226
1226
  cwd: params.workingDirectory,
1227
1227
  extendEnv: true,
1228
1228
  env: {
@@ -1256,14 +1256,14 @@ const nodePlatformLayer = Layer.mergeAll(nodeWorkerLauncherLayer.pipe(Layer.prov
1256
1256
  * The in-memory runner's platform: the V8 sandbox module and the module
1257
1257
  * builtin that strips TypeScript and resolves a sandbox's `require`.
1258
1258
  *
1259
- * Reached through `process.getBuiltinModule` rather than an `import` because a
1259
+ * Reached through `globalThis.process.getBuiltinModule` rather than an `import` because a
1260
1260
  * Node builtin import is forbidden in product code; the call is wrapped in
1261
1261
  * `Effect.promise` so a platform without `node:vm` fails as a defect — the
1262
1262
  * runner has no fallback to fall back to.
1263
1263
  */
1264
1264
  const nodeVmPlatformLayer = Layer.effect(VmRunner, Effect$1.sync(() => ({
1265
- module: process.getBuiltinModule("node:module"),
1266
- vm: process.getBuiltinModule("node:vm")
1265
+ module: globalThis.process.getBuiltinModule("node:module"),
1266
+ vm: globalThis.process.getBuiltinModule("node:vm")
1267
1267
  })));
1268
1268
  S.TaggedError()("CommandRunnerUnsupportedOption", { option: S.String });
1269
1269
  S.Struct({
@@ -2002,7 +2002,7 @@ function findConfigFile(configFileName) {
2002
2002
  return Match.value(configFileName).pipe(Match.when(Match.string, (fileName) => configFileFor(fileName)), Match.orElse(() => discoverConfigFile()));
2003
2003
  }
2004
2004
  const resolveChildExtends = (configFile, child, configEnv) => Match.value("extends" in child).pipe(Match.when(true, () => resolveExtends(configFile, child, configEnv)), Match.orElse(() => Effect$1.succeed(child)));
2005
- const isCiEnvironment = Config.string("CI").pipe(Effect$1.map((value) => Match.value(value.trim().toLowerCase()).pipe(Match.when("", () => false), Match.when("0", () => false), Match.when("false", () => false), Match.orElse(() => true))), Effect$1.orElseSucceed(() => false));
2005
+ const isCiEnvironment = Config.String("CI").pipe(Effect$1.map((value) => Match.value(value.trim().toLowerCase()).pipe(Match.when("", () => false), Match.when("0", () => false), Match.when("false", () => false), Match.orElse(() => true))), Effect$1.orElseSucceed(() => false));
2006
2006
  function loadOptionsFromConfigFile(cliOptions, configEnv) {
2007
2007
  return findConfigFile(cliOptions["configFile"]).pipe(Effect$1.flatMap((configFile) => Match.value(configFile).pipe(Match.when(void 0, () => Effect$1.succeed({})), Match.orElse((found) => readConfigModule(found, configEnv).pipe(Effect$1.flatMap((child) => resolveChildExtends(found, child, configEnv)))))));
2008
2008
  }
@@ -2014,7 +2014,7 @@ function readConfig(cliOptions, invocation) {
2014
2014
  isDryRun: cliOptions["dryRunOnly"] === true,
2015
2015
  isCi: yield* isCiEnvironment
2016
2016
  };
2017
- const cliRecord = yield* S.decodeUnknownEffect(ConfigDocumentSchema)(cliOptions).pipe(Effect$1.orDie);
2017
+ const cliRecord = yield* S.decodeEffect(ConfigDocumentSchema)(cliOptions).pipe(Effect$1.orDie);
2018
2018
  const fileRecord = yield* loadOptionsFromConfigFile(cliRecord, configEnv);
2019
2019
  const fileOptions = yield* Result.match(S.decodeUnknownResult(ConfigDocumentSchema)(fileRecord), {
2020
2020
  onFailure: (cause) => Effect$1.fail(ConfigFileInvalidError.make({
@@ -2046,9 +2046,13 @@ const PluginDescriptorSchema = Schema.Union([Schema.Struct({
2046
2046
  const PluginModuleSchema = Schema.Struct({ strykerPlugins: Schema.Array(PluginDescriptorSchema) });
2047
2047
  const isShouldIgnore = (value) => typeof value === "function";
2048
2048
  const ignoreNothing = () => void 0;
2049
+ const shouldIgnoreArbitrary = Schema.link()(Schema.Null, {
2050
+ decode: SchemaGetter.transform(() => ignoreNothing),
2051
+ encode: SchemaGetter.transform(() => null)
2052
+ });
2049
2053
  const IgnorerEntrySchema = Schema.Struct({
2050
2054
  name: Schema.String,
2051
- shouldIgnore: Schema.declare(isShouldIgnore, { toArbitrary: () => (fc) => fc.constant(ignoreNothing) })
2055
+ shouldIgnore: Schema.declare(isShouldIgnore, { toCodecArbitrary: () => shouldIgnoreArbitrary })
2052
2056
  });
2053
2057
  const IgnorerModuleSchema = Schema.Struct({ strykerIgnorers: Schema.Array(IgnorerEntrySchema) });
2054
2058
  const SchemaValidationContributionSchema = Schema.Struct({ strykerValidationSchema: Schema.Record(Schema.String, Schema.Unknown) });
@@ -2436,8 +2440,8 @@ const initFromPhaseSpan = (span) => {
2436
2440
  };
2437
2441
  };
2438
2442
  const environmentTraceInit = () => Effect$1.gen(function* () {
2439
- const traceparent = yield* Config.string("TRACEPARENT").pipe(Effect$1.option);
2440
- const tracestate = yield* Config.string("TRACESTATE").pipe(Effect$1.option);
2443
+ const traceparent = yield* Config.String("TRACEPARENT").pipe(Effect$1.option);
2444
+ const tracestate = yield* Config.String("TRACESTATE").pipe(Effect$1.option);
2441
2445
  return {
2442
2446
  ...traceparentInit(Option.getOrUndefined(traceparent)),
2443
2447
  ...tracestateInit(Option.getOrUndefined(tracestate))
@@ -2532,104 +2536,98 @@ const completeDryRunPassed = (raw) => Effect$1.gen(function* () {
2532
2536
  timeOverhead: Duration.millis(overheadMillis)
2533
2537
  };
2534
2538
  });
2535
- const dryRunCell = Cell.layer({
2536
- read: (command) => Effect$1.gen(function* () {
2537
- yield* Scope.Scope;
2538
- const idGenerator = yield* IdGenerator;
2539
- const { files, testFiles } = buildDryRunFiles(command);
2540
- const dryRunTimeout = command.options.dryRunTimeoutMinutes * 60 * 1e3;
2541
- yield* Effect$1.logInfo("Starting dry run");
2542
- const { rawResult, capabilities, gross } = yield* Effect$1.scoped(Effect$1.gen(function* () {
2543
- const childRunnerEffect = Effect$1.suspend(() => {
2544
- const runnerConfigured = command.options.testRunner;
2545
- const runnerLabel = Match.value(runnerConfigured).pipe(Match.when(isCustomTestRunner, (runner) => runner.plugin), Match.orElse((name) => name));
2546
- return resolveConfiguredWorkerSpawn({
2547
- loaded: command.loadedPlugins,
2548
- kind: "TestRunner",
2549
- configured: runnerConfigured
2550
- }).pipe(Effect$1.mapError(missingWorkerEntry("dryRun", "test runner", runnerLabel)), Effect$1.flatMap(({ spawn }) => makeChildProcessTestRunner({
2551
- options: command.options,
2552
- fileDescriptions: command.project.fileDescriptions,
2553
- sandboxWorkingDirectory: command.sandbox.workingDirectory,
2554
- workerEntrypoint: spawn.entrypoint,
2555
- idGenerator
2556
- })));
2557
- });
2558
- const runner = yield* buildTestRunner({
2539
+ const dryRunCell = Sandwich.read((command) => Effect$1.gen(function* () {
2540
+ yield* Scope.Scope;
2541
+ const idGenerator = yield* IdGenerator;
2542
+ const { files, testFiles } = buildDryRunFiles(command);
2543
+ const dryRunTimeout = command.options.dryRunTimeoutMinutes * 60 * 1e3;
2544
+ yield* Effect$1.logInfo("Starting dry run");
2545
+ const { rawResult, capabilities, gross } = yield* Effect$1.scoped(Effect$1.gen(function* () {
2546
+ const childRunnerEffect = Effect$1.suspend(() => {
2547
+ const runnerConfigured = command.options.testRunner;
2548
+ const runnerLabel = Match.value(runnerConfigured).pipe(Match.when(isCustomTestRunner, (runner) => runner.plugin), Match.orElse((name) => name));
2549
+ return resolveConfiguredWorkerSpawn({
2550
+ loaded: command.loadedPlugins,
2551
+ kind: "TestRunner",
2552
+ configured: runnerConfigured
2553
+ }).pipe(Effect$1.mapError(missingWorkerEntry("dryRun", "test runner", runnerLabel)), Effect$1.flatMap(({ spawn }) => makeChildProcessTestRunner({
2559
2554
  options: command.options,
2560
2555
  fileDescriptions: command.project.fileDescriptions,
2561
2556
  sandboxWorkingDirectory: command.sandbox.workingDirectory,
2562
- idGenerator,
2563
- retire: Effect$1.void,
2564
- testFiles: testFiles ?? []
2565
- }, childRunnerEffect);
2566
- const extra = Option.match(Option.fromUndefinedOr(testFiles), {
2567
- onNone: () => ({}),
2568
- onSome: (files) => ({ testFiles: files })
2569
- });
2570
- const timed = yield* Effect$1.timed(runner.dryRun({
2571
- timeout: dryRunTimeout,
2572
- coverageAnalysis: command.options.coverageAnalysis,
2573
- disableBail: command.options.disableBail,
2574
- files,
2575
- ...extra
2576
- }).pipe(Effect$1.mapError((cause) => StageError.make({
2577
- stage: "dryRun",
2578
- reason: "Dry run failed",
2579
- cause
2580
- }))));
2581
- const gross = timed[0];
2582
- return {
2583
- rawResult: timed[1],
2584
- capabilities: yield* runner.capabilities.pipe(Effect$1.mapError((cause) => StageError.make({
2585
- stage: "dryRun",
2586
- reason: "Failed to get test runner capabilities",
2587
- cause
2588
- }))),
2589
- gross
2590
- };
2591
- })).pipe(Effect$1.mapError((cause) => {
2592
- if (S.is(StageError)(cause)) return cause;
2593
- return StageError.make({
2557
+ workerEntrypoint: spawn.entrypoint,
2558
+ idGenerator
2559
+ })));
2560
+ });
2561
+ const runner = yield* buildTestRunner({
2562
+ options: command.options,
2563
+ fileDescriptions: command.project.fileDescriptions,
2564
+ sandboxWorkingDirectory: command.sandbox.workingDirectory,
2565
+ idGenerator,
2566
+ retire: Effect$1.void,
2567
+ testFiles: testFiles ?? []
2568
+ }, childRunnerEffect);
2569
+ const extra = Option.match(Option.fromUndefinedOr(testFiles), {
2570
+ onNone: () => ({}),
2571
+ onSome: (files) => ({ testFiles: files })
2572
+ });
2573
+ const timed = yield* Effect$1.timed(runner.dryRun({
2574
+ timeout: dryRunTimeout,
2575
+ coverageAnalysis: command.options.coverageAnalysis,
2576
+ disableBail: command.options.disableBail,
2577
+ files,
2578
+ ...extra
2579
+ }).pipe(Effect$1.mapError((cause) => StageError.make({
2580
+ stage: "dryRun",
2581
+ reason: "Dry run failed",
2582
+ cause
2583
+ }))));
2584
+ const gross = timed[0];
2585
+ return {
2586
+ rawResult: timed[1],
2587
+ capabilities: yield* runner.capabilities.pipe(Effect$1.mapError((cause) => StageError.make({
2594
2588
  stage: "dryRun",
2595
- reason: "Dry run failed to start test runner",
2589
+ reason: "Failed to get test runner capabilities",
2596
2590
  cause
2597
- });
2598
- }));
2599
- return {
2600
- prev: command,
2601
- rawResult,
2602
- capabilities,
2591
+ }))),
2603
2592
  gross
2604
2593
  };
2605
- }),
2606
- decode: (raw) => Match.value(raw.rawResult).pipe(Match.when(isCompleteDryRun, (complete) => decodeCompleteDryRun(complete, raw.prev.options.allowEmpty)), Match.when(isFailedDryRun, (failed) => decodeFailedDryRun(failed, raw.prev.options.allowEmpty)), Match.orElse((timedOut) => decodeTimedOutDryRun(timedOut, raw.prev.options.allowEmpty))),
2607
- decide: dryRun,
2608
- encode: (outcome) => outcome,
2609
- write: (outcome, raw) => withPhaseSpan("dryRun", {}, () => Effect$1.gen(function* () {
2610
- const env = yield* RunEnvironment;
2611
- const now = yield* Clock.currentTimeMillis;
2612
- const queue = yield* RunEvents;
2613
- yield* Queue.offer(queue, PhaseEntered.make({
2614
- phase: "dry-run",
2615
- elapsedMs: now - env.runStartedAt
2616
- }));
2617
- const out = outcome;
2618
- if (Result.isFailure(out)) {
2619
- const err = out.failure;
2620
- return yield* StageError.make({
2621
- stage: err.stage,
2622
- reason: err.reason,
2623
- cause: err
2624
- });
2625
- }
2626
- return yield* Match.value(out.success).pipe(Match.tag("DryRunFailed", (decision) => Effect$1.fail(StageError.make({
2594
+ })).pipe(Effect$1.mapError((cause) => {
2595
+ if (S.is(StageError)(cause)) return cause;
2596
+ return StageError.make({
2627
2597
  stage: "dryRun",
2628
- reason: "There were failed tests in the initial test run.",
2629
- cause: decision
2630
- }))), Match.tag("DryRunPassed", () => completeDryRunPassed(raw)), Match.exhaustive);
2631
- }))
2632
- });
2598
+ reason: "Dry run failed to start test runner",
2599
+ cause
2600
+ });
2601
+ }));
2602
+ return {
2603
+ prev: command,
2604
+ rawResult,
2605
+ capabilities,
2606
+ gross
2607
+ };
2608
+ })).decode(Sandwich.pure((raw) => Match.value(raw.rawResult).pipe(Match.when(isCompleteDryRun, (complete) => decodeCompleteDryRun(complete, raw.prev.options.allowEmpty)), Match.when(isFailedDryRun, (failed) => decodeFailedDryRun(failed, raw.prev.options.allowEmpty)), Match.orElse((timedOut) => decodeTimedOutDryRun(timedOut, raw.prev.options.allowEmpty))))).decide(dryRun).encode(Sandwich.pure((outcome) => Result.succeed(outcome))).write((outcome, raw) => withPhaseSpan("dryRun", {}, () => Effect$1.gen(function* () {
2609
+ const env = yield* RunEnvironment;
2610
+ const now = yield* Clock.currentTimeMillis;
2611
+ const queue = yield* RunEvents;
2612
+ yield* Queue.offer(queue, PhaseEntered.make({
2613
+ phase: "dry-run",
2614
+ elapsedMs: now - env.runStartedAt
2615
+ }));
2616
+ const out = outcome;
2617
+ if (Result.isFailure(out)) {
2618
+ const err = out.failure;
2619
+ return yield* StageError.make({
2620
+ stage: err.stage,
2621
+ reason: err.reason,
2622
+ cause: err
2623
+ });
2624
+ }
2625
+ return yield* Match.value(out.success).pipe(Match.tag("DryRunFailed", (decision) => Effect$1.fail(StageError.make({
2626
+ stage: "dryRun",
2627
+ reason: "There were failed tests in the initial test run.",
2628
+ cause: decision
2629
+ }))), Match.tag("DryRunPassed", () => completeDryRunPassed(raw)), Match.exhaustive);
2630
+ })));
2633
2631
  //#endregion
2634
2632
  //#region src/plan-instrumentation.workflow.ts
2635
2633
  var InstrumentError = class extends S.TaggedError()("InstrumentError", {
@@ -2846,118 +2844,8 @@ const decide = (command) => Option.match(Option.fromUndefinedOr(command.report),
2846
2844
  });
2847
2845
  const admitIncrementalReport = Workflow.total(AdmitIncrementalReportCommand, (command) => Result.succeed(decide(command)));
2848
2846
  //#endregion
2849
- //#region package.json
2850
- var package_default = {
2851
- name: "@systemfsoftware/stryker-js",
2852
- version: "10.0.0",
2853
- repository: {
2854
- "type": "git",
2855
- "url": "git+https://github.com/systemfsoftware/stryker-js-effect.git",
2856
- "directory": "packages/stryker-js"
2857
- },
2858
- homepage: "https://github.com/systemfsoftware/stryker-js-effect",
2859
- bugs: { "url": "https://github.com/systemfsoftware/stryker-js-effect/issues" },
2860
- description: "The Stryker mutation testing tool — the stryker executable, the run engine, and the configuration surface.",
2861
- type: "module",
2862
- files: ["dist"],
2863
- bin: { "stryker": "./dist/main.mjs" },
2864
- scripts: {
2865
- "clean": "rimraf dist",
2866
- "build": "pnpm run typecheck && rimraf dist && tsdown --config tsdown.bin.config.ts && tsdown --config tsdown.config.ts",
2867
- "typecheck": "tsc --noEmit --incremental && tsc -p tsconfig.node.json --noEmit",
2868
- "test": "vitest run",
2869
- "mutation": "stryker run",
2870
- "attw": "attw --pack .",
2871
- "lint": "f=${OXLINT_FORMAT:-${AGENT:+agent}}; oxlint . --format=${f:-default}",
2872
- "api:check": "api-extractor run",
2873
- "api:update": "api-extractor run --local",
2874
- "lint:tsgo": "effect-tsgo diagnostics --project tsconfig.json --format ${TSGO_FORMAT:-text}"
2875
- },
2876
- license: "Apache-2.0",
2877
- engines: { "node": ">=22.18.0" },
2878
- dependencies: {
2879
- "@effect/opentelemetry": "4.0.0-rc.112",
2880
- "@effect/platform-node": "catalog:",
2881
- "@effect/platform-node-shared": "catalog:",
2882
- "@noble/hashes": "catalog:",
2883
- "@opentelemetry/api": "^1.9.0",
2884
- "@opentelemetry/exporter-metrics-otlp-http": "^0.208.0",
2885
- "@opentelemetry/exporter-trace-otlp-http": "^0.208.0",
2886
- "@opentelemetry/sdk-metrics": "^2.2.0",
2887
- "@opentelemetry/sdk-trace-base": "^2.2.0",
2888
- "@systemfsoftware/effect-cell-types": "catalog:"
2889
- },
2890
- peerDependencies: { "effect": "catalog:" },
2891
- devDependencies: {
2892
- "@effect/tsgo": "catalog:",
2893
- "@effect/vitest": "catalog:",
2894
- "@microsoft/api-extractor": "catalog:",
2895
- "@oxc-parser/binding-wasm32-wasi": "catalog:",
2896
- "@std/jsonc": "catalog:",
2897
- "@systemfsoftware/all": "catalog:",
2898
- "@systemfsoftware/arethetypeswrong-cli": "catalog:",
2899
- "@systemfsoftware/effect-gherkin-spec": "catalog:",
2900
- "@systemfsoftware/effect-schema-law": "catalog:",
2901
- "@systemfsoftware/effect-schema-vite": "catalog:",
2902
- "@systemfsoftware/stryker-config": "workspace:^",
2903
- "@systemfsoftware/stryker-ignorer-effect-schema-declarations": "catalog:stryker",
2904
- "@systemfsoftware/stryker-ignorer-in-source-vitest-block": "catalog:stryker",
2905
- "@systemfsoftware/stryker-ignorer-interface": "workspace:^",
2906
- "@systemfsoftware/stryker-js": "catalog:stryker",
2907
- "@systemfsoftware/stryker-js-html-reporter": "workspace:^",
2908
- "@systemfsoftware/stryker-js-instrumenter": "workspace:^",
2909
- "@systemfsoftware/stryker-js-plugin-interface": "workspace:^",
2910
- "@systemfsoftware/stryker-js-plugin-runtime": "workspace:^",
2911
- "@systemfsoftware/stryker-js-typescript-checker": "catalog:stryker",
2912
- "@systemfsoftware/stryker-js-vitest-runner": "catalog:stryker",
2913
- "@systemfsoftware/stryker-test-contribution": "catalog:stryker",
2914
- "@systemfsoftware/tsconfig": "catalog:",
2915
- "@systemfsoftware/tsdown-config": "workspace:^",
2916
- "@systemfsoftware/vitest-config": "workspace:^",
2917
- "@types/node": "catalog:",
2918
- "@vitest/coverage-v8": "catalog:",
2919
- "concurrently": "catalog:",
2920
- "mutation-testing-elements": "catalog:stryker",
2921
- "oxc-parser": "catalog:",
2922
- "oxlint": "catalog:",
2923
- "oxlint-tsgolint": "catalog:",
2924
- "rimraf": "catalog:",
2925
- "tsdown": "catalog:",
2926
- "typescript": "catalog:",
2927
- "vitest": "catalog:"
2928
- },
2929
- publishConfig: {
2930
- "access": "public",
2931
- "provenance": true,
2932
- "exports": {
2933
- ".": {
2934
- "types": "./dist/index.d.mts",
2935
- "default": "./dist/index.mjs"
2936
- },
2937
- "./config": {
2938
- "types": "./dist/config.d.mts",
2939
- "default": "./dist/config.mjs"
2940
- },
2941
- "./events": {
2942
- "types": "./dist/events.d.mts",
2943
- "default": "./dist/events.mjs"
2944
- },
2945
- "./promises": {
2946
- "types": "./dist/promises.d.mts",
2947
- "default": "./dist/promises.mjs"
2948
- },
2949
- "./package.json": "./package.json"
2950
- }
2951
- },
2952
- exports: { "./package.json": "./package.json" }
2953
- };
2954
- //#endregion
2955
- //#region src/stryker-package.schema.ts
2956
- const PackageJsonSchema = Schema.Struct({ version: Schema.String });
2957
- //#endregion
2958
2847
  //#region src/stryker-package.ts
2959
- const rawPackageJson = package_default;
2960
- const strykerVersion = Schema.decodeUnknownSync(PackageJsonSchema)(rawPackageJson).version;
2848
+ const strykerVersion = "10.0.1";
2961
2849
  //#endregion
2962
2850
  //#region src/incremental-report.cell.ts
2963
2851
  const parseAndDecodeIncrementalReport = S.decodeUnknownResult(S.fromJsonString(IncrementalReportSchema));
@@ -2968,7 +2856,7 @@ const readIncrementalReportRaw = (input) => {
2968
2856
  contents: void 0
2969
2857
  });
2970
2858
  return Effect$1.gen(function* () {
2971
- const contents = yield* (yield* FileSystem.FileSystem).readFileString(input.incrementalFile).pipe(Effect$1.catchTag("PlatformError", (error) => Match.value(error.reason).pipe(Match.tag("NotFound", () => Effect$1.logInfo(`No incremental result file found at ${input.incrementalFile}, a full mutation testing run will be performed.`).pipe(Effect$1.as(void 0))), Match.orElse(() => Effect$1.fail(error)))));
2859
+ const contents = yield* (yield* FileSystem.FileSystem).readFileString(input.incrementalFile).pipe(Effect$1.tapError((error) => Match.value(error.reason).pipe(Match.tag("NotFound", () => Effect$1.logInfo(`No incremental result file found at ${input.incrementalFile}, a full mutation testing run will be performed.`)), Match.orElse(() => Effect$1.void))), Effect$1.catchTag("PlatformError", (error) => Match.value(error.reason).pipe(Match.tag("NotFound", () => Effect$1.undefined), Match.orElse(() => Effect$1.fail(error)))));
2972
2860
  return {
2973
2861
  incremental: true,
2974
2862
  incrementalFile: input.incrementalFile,
@@ -2996,13 +2884,7 @@ const writeIncrementalReportOutcome = (outcome, raw) => Result.match(outcome, {
2996
2884
  });
2997
2885
  }), Match.exhaustive)
2998
2886
  });
2999
- const incrementalReportCell = Cell.layer({
3000
- read: readIncrementalReportRaw,
3001
- decode: decodeIncrementalReportRaw,
3002
- decide: admitIncrementalReport,
3003
- encode: (outcome) => outcome,
3004
- write: writeIncrementalReportOutcome
3005
- });
2887
+ const incrementalReportCell = Sandwich.read(readIncrementalReportRaw).decode(Sandwich.pure(decodeIncrementalReportRaw)).decide(admitIncrementalReport).encode(Sandwich.pure((outcome) => Result.succeed(outcome))).write(writeIncrementalReportOutcome);
3006
2888
  //#endregion
3007
2889
  //#region src/Project.ts
3008
2890
  const DEFAULT_GLOB$1 = "**/*.{js,ts,jsx,tsx,html,vue,mjs,mts,cts,cjs}";
@@ -3736,9 +3618,9 @@ const makeDisableTypeChecksPreprocessor = (options, impl) => (project) => Effect
3736
3618
  const content = yield* Effect$1.map(impl(instrumenterFile), (instrumented) => instrumented.content).pipe(Effect$1.mapError((cause) => StrykerError.make({
3737
3619
  message: "disableTypeChecks failed",
3738
3620
  cause
3739
- })), Effect$1.catch((_error) => Effect$1.gen(function* () {
3621
+ })), Effect$1.tapError(() => Effect$1.gen(function* () {
3740
3622
  if (isWarningEnabled("preprocessorErrors", options.warnings)) yield* Effect$1.logWarning(`Unable to disable type checking for file "${name}". Shouldn't type checking be disabled for this file? Consider configuring a more restrictive "${optionsPath("disableTypeChecks")}" settings (or turn it completely off with \`false\`)`);
3741
- })));
3623
+ })), Effect$1.orElseSucceed(() => void 0));
3742
3624
  if (content !== void 0) return withContent(file, content);
3743
3625
  })), Match.orElse(() => Effect$1.succeedNone)), { concurrency: 24 })).forEach(mergeUpdatedInto(project));
3744
3626
  });
@@ -3885,7 +3767,7 @@ const directoryChain = (from, pathService) => {
3885
3767
  return [from, ...directoryChain(parent, pathService)];
3886
3768
  };
3887
3769
  const binDirectoriesFrom = (from, pathService) => directoryChain(pathService.resolve(from), pathService).map((directory) => pathService.join(directory, "node_modules", ".bin"));
3888
- const inheritedPath = () => Config.string("PATH").pipe(Effect$1.option, Effect$1.map((value) => Option.getOrUndefined(value) ?? ""));
3770
+ const inheritedPath = () => Config.String("PATH").pipe(Effect$1.option, Effect$1.map((value) => Option.getOrUndefined(value) ?? ""));
3889
3771
  const failOnBuildFailure = (command, result) => Match.value(result.exitCode).pipe(Match.when((exitCode) => exitCode !== 0, (exitCode) => Effect$1.fail(StrykerError.make({ message: `Build command "${command}" failed with exit code ${String(exitCode)}.\n${result.stderr}` }))), Match.orElse(() => Effect$1.void));
3890
3772
  const runBuildCommandIn = (command, workingDirectory) => Effect$1.gen(function* () {
3891
3773
  const pathService = yield* Path.Path;
@@ -4012,7 +3894,7 @@ const linkNodeModules = (nodeModules, workingDirectory, basePath, pathService) =
4012
3894
  const resolvedTo = pathService.resolve(pathService.join(basePath, nodeModules));
4013
3895
  const resolvedFrom = pathService.join(workingDirectory, nodeModules);
4014
3896
  yield* Effect$1.logDebug(`Create symlink from ${resolvedTo} to ${resolvedFrom}`);
4015
- yield* symlinkJunction(resolvedTo, resolvedFrom).pipe(Effect$1.catch((_error) => Effect$1.logWarning(`Unexpected error while trying to symlink "${nodeModules}" in sandbox directory.`)));
3897
+ yield* symlinkJunction(resolvedTo, resolvedFrom).pipe(Effect$1.tapError(() => Effect$1.logWarning(`Unexpected error while trying to symlink "${nodeModules}" in sandbox directory.`)), Effect$1.catchTag("PlatformError", () => Effect$1.void));
4016
3898
  });
4017
3899
  const linkFoundNodeModules = (options, workingDirectory, basePath, pathService) => Effect$1.gen(function* () {
4018
3900
  const nodeModulesList = yield* findNodeModulesList(basePath, options.tempDirName);
@@ -4050,90 +3932,84 @@ const makeSandbox = (input) => Effect$1.gen(function* () {
4050
3932
  });
4051
3933
  //#endregion
4052
3934
  //#region src/run/instrument.cell.ts
4053
- const instrumentCell = Cell.layer({
4054
- read: (command) => Effect$1.gen(function* () {
4055
- yield* Scope.Scope;
4056
- const env = yield* RunEnvironment;
4057
- const filesToMutate = yield* Effect$1.forEach([...MutableHashMap.values(command.project.filesToMutate)], (file) => toInstrumenterFile(file), { concurrency: 24 }).pipe(Effect$1.mapError((cause) => StageError.make({
3935
+ const instrumentCell = Sandwich.read((command) => Effect$1.gen(function* () {
3936
+ yield* Scope.Scope;
3937
+ const env = yield* RunEnvironment;
3938
+ const filesToMutate = yield* Effect$1.forEach([...MutableHashMap.values(command.project.filesToMutate)], (file) => toInstrumenterFile(file), { concurrency: 24 }).pipe(Effect$1.mapError((cause) => StageError.make({
3939
+ stage: "instrument",
3940
+ reason: "Failed to read files to mutate",
3941
+ cause
3942
+ })));
3943
+ const instrumentResult = yield* instrument(filesToMutate, {
3944
+ ignorers: [...command.ignorers],
3945
+ excludedMutations: [...command.options.mutator.excludedMutations]
3946
+ }, env.basePath).pipe(Effect$1.mapError((cause) => StageError.make({
3947
+ stage: "instrument",
3948
+ reason: "Instrumenter failed",
3949
+ cause
3950
+ })));
3951
+ const instrumentedProject = withInstrumentedFiles(command.project, instrumentResult.files);
3952
+ const basePath = env.basePath;
3953
+ let workingDirectory = command.temporaryDirectoryPath;
3954
+ let backupDirectory = "";
3955
+ if (command.options.inPlace) {
3956
+ workingDirectory = basePath;
3957
+ backupDirectory = command.temporaryDirectoryPath;
3958
+ }
3959
+ return {
3960
+ prev: command,
3961
+ filesToMutate,
3962
+ instrumentResult,
3963
+ instrumentedProject,
3964
+ sandbox: yield* makeSandbox({
3965
+ options: command.options,
3966
+ project: instrumentedProject,
3967
+ workingDirectory,
3968
+ backupDirectory,
3969
+ basePath
3970
+ }).pipe(Effect$1.mapError((cause) => StageError.make({
4058
3971
  stage: "instrument",
4059
- reason: "Failed to read files to mutate",
3972
+ reason: "Sandbox initialization failed",
4060
3973
  cause
4061
- })));
4062
- const instrumentResult = yield* instrument(filesToMutate, {
4063
- ignorers: [...command.ignorers],
4064
- excludedMutations: [...command.options.mutator.excludedMutations]
4065
- }, env.basePath).pipe(Effect$1.mapError((cause) => StageError.make({
3974
+ }))),
3975
+ concurrency: yield* makeConcurrency(command.options).pipe(Effect$1.mapError((cause) => StageError.make({
4066
3976
  stage: "instrument",
4067
- reason: "Instrumenter failed",
3977
+ reason: "Failed to compute concurrency",
4068
3978
  cause
4069
- })));
4070
- const instrumentedProject = withInstrumentedFiles(command.project, instrumentResult.files);
4071
- const basePath = env.basePath;
4072
- let workingDirectory = command.temporaryDirectoryPath;
4073
- let backupDirectory = "";
4074
- if (command.options.inPlace) {
4075
- workingDirectory = basePath;
4076
- backupDirectory = command.temporaryDirectoryPath;
4077
- }
4078
- return {
4079
- prev: command,
4080
- filesToMutate,
4081
- instrumentResult,
4082
- instrumentedProject,
4083
- sandbox: yield* makeSandbox({
4084
- options: command.options,
4085
- project: instrumentedProject,
4086
- workingDirectory,
4087
- backupDirectory,
4088
- basePath
4089
- }).pipe(Effect$1.mapError((cause) => StageError.make({
4090
- stage: "instrument",
4091
- reason: "Sandbox initialization failed",
4092
- cause
4093
- }))),
4094
- concurrency: yield* makeConcurrency(command.options).pipe(Effect$1.mapError((cause) => StageError.make({
4095
- stage: "instrument",
4096
- reason: "Failed to compute concurrency",
4097
- cause
4098
- })))
4099
- };
4100
- }),
4101
- decode: (raw) => Result.succeed(InstrumentCommand.make({
4102
- fileCount: raw.filesToMutate.length,
4103
- inPlace: raw.prev.options.inPlace,
4104
- pluginCount: raw.prev.loadedPlugins.pluginModulePaths.length
4105
- })),
4106
- decide: planInstrumentation,
4107
- encode: (outcome) => outcome,
4108
- write: (output, raw) => withPhaseSpan("instrument", { fileCount: raw.filesToMutate.length }, () => Effect$1.gen(function* () {
4109
- const env = yield* RunEnvironment;
4110
- const now = yield* Clock.currentTimeMillis;
4111
- const queue = yield* RunEvents;
4112
- yield* Queue.offer(queue, PhaseEntered.make({
4113
- phase: "instrument",
4114
- elapsedMs: now - env.runStartedAt
4115
- }));
4116
- const out = output;
4117
- if (Result.isFailure(out)) {
4118
- const err = out.failure;
4119
- return yield* StageError.make({
4120
- stage: err.stage,
4121
- reason: err.reason,
4122
- cause: err
4123
- });
3979
+ })))
3980
+ };
3981
+ })).decode(Sandwich.pure((raw) => Result.succeed(InstrumentCommand.make({
3982
+ fileCount: raw.filesToMutate.length,
3983
+ inPlace: raw.prev.options.inPlace,
3984
+ pluginCount: raw.prev.loadedPlugins.pluginModulePaths.length
3985
+ })))).decide(planInstrumentation).encode(Sandwich.pure((outcome) => Result.succeed(outcome))).write((output, raw) => withPhaseSpan("instrument", { fileCount: raw.filesToMutate.length }, () => Effect$1.gen(function* () {
3986
+ const env = yield* RunEnvironment;
3987
+ const now = yield* Clock.currentTimeMillis;
3988
+ const queue = yield* RunEvents;
3989
+ yield* Queue.offer(queue, PhaseEntered.make({
3990
+ phase: "instrument",
3991
+ elapsedMs: now - env.runStartedAt
3992
+ }));
3993
+ const out = output;
3994
+ if (Result.isFailure(out)) {
3995
+ const err = out.failure;
3996
+ return yield* StageError.make({
3997
+ stage: err.stage,
3998
+ reason: err.reason,
3999
+ cause: err
4000
+ });
4001
+ }
4002
+ return {
4003
+ ...raw.prev,
4004
+ project: raw.instrumentedProject,
4005
+ mutants: raw.instrumentResult.mutants,
4006
+ sandbox: raw.sandbox,
4007
+ concurrency: {
4008
+ testRunners: raw.concurrency.testRunners,
4009
+ checkers: raw.concurrency.checkers
4124
4010
  }
4125
- return {
4126
- ...raw.prev,
4127
- project: raw.instrumentedProject,
4128
- mutants: raw.instrumentResult.mutants,
4129
- sandbox: raw.sandbox,
4130
- concurrency: {
4131
- testRunners: raw.concurrency.testRunners,
4132
- checkers: raw.concurrency.checkers
4133
- }
4134
- };
4135
- }))
4136
- });
4011
+ };
4012
+ })));
4137
4013
  //#endregion
4138
4014
  //#region src/MutationTest.schema.ts
4139
4015
  var MutationTestCommand = class extends S.TaggedClass()("MutationTestCommand", {
@@ -4168,7 +4044,7 @@ const admitMutationTest = Workflow.make(MutationTestCommand, (command) => Match.
4168
4044
  }, () => Result.succeed(MutationTestNoTests.make({}))), Match.orElse(() => Result.succeed(MutationTestProceed.make({})))));
4169
4045
  //#endregion
4170
4046
  //#region src/checker-mutant-wire.ts
4171
- const CheckerMutantFromMutant = Mutant.pipe(S.decodeTo(CheckerMutantWire, SchemaTransformation.transform({
4047
+ const CheckerMutantFromMutant = Mutant.pipe(S.decodeTo(CheckerMutantWire, SchemaTransformation$1.transform({
4172
4048
  decode: (m) => ({
4173
4049
  id: m.id,
4174
4050
  fileName: m.fileName,
@@ -4184,7 +4060,7 @@ const CheckerMutantFromMutant = Mutant.pipe(S.decodeTo(CheckerMutantWire, Schema
4184
4060
  location: w.location
4185
4061
  })
4186
4062
  })));
4187
- const wireRecordOf = (mutant) => Result.mapError(S.decodeUnknownResult(CheckerMutantFromMutant)(mutant), (error) => ({
4063
+ const wireRecordOf = (mutant) => Result.mapError(S.decodeResult(CheckerMutantFromMutant)(mutant), (error) => ({
4188
4064
  id: mutant.id,
4189
4065
  fileName: mutant.fileName,
4190
4066
  reason: error.message
@@ -4501,35 +4377,29 @@ const logSkippedMutants = (checkerName, undescribable) => Match.value(undescriba
4501
4377
  * that joins them back. The join is where the work is, and it is pure.
4502
4378
  */
4503
4379
  const checkPlans = (checker, checkerName, plans, lookup) => {
4504
- return Cell.layer({
4505
- read: (command) => Effect$1.gen(function* () {
4506
- const partitioned = Option.match(Option.fromUndefinedOr(command.lookup), {
4507
- onSome: (known) => selectedFromLookup(command.plans, known),
4508
- onNone: () => partitionMutantsForWire(command.plans)
4509
- });
4510
- yield* logSkippedMutants(command.checkerName, partitioned.undescribable);
4511
- if (partitioned.undescribable.length > 0) yield* Metric.update(checkerMutantsSkipped, partitioned.undescribable.length);
4512
- yield* Effect$1.annotateCurrentSpan({ "stryker.checker.skipped_mutants_count": partitioned.undescribable.length });
4513
- const answers = yield* command.checker.check(command.checkerName, partitioned.wire);
4514
- return {
4515
- checkerName: command.checkerName,
4516
- requestedIds: command.plans.map((plan) => plan.mutant.id),
4517
- answers: {
4518
- ...compileErrorAnswersOf(partitioned.undescribable),
4519
- ...answers
4520
- }
4521
- };
4522
- }),
4523
- decode: (raw) => Result.succeed(CheckerCommand.make({
4524
- checkerName: raw.checkerName,
4525
- requestedIds: [...raw.requestedIds],
4526
- phase: "check",
4527
- answers: { ...raw.answers }
4528
- })),
4529
- decide: admitCheckerAnswer,
4530
- encode: (outcome) => outcome,
4531
- write: (outcome, raw) => writeCheckerOutcome(plans, raw.checkerName, outcome)
4532
- }).run({
4380
+ return Sandwich.read((command) => Effect$1.gen(function* () {
4381
+ const partitioned = Option.match(Option.fromUndefinedOr(command.lookup), {
4382
+ onSome: (known) => selectedFromLookup(command.plans, known),
4383
+ onNone: () => partitionMutantsForWire(command.plans)
4384
+ });
4385
+ yield* logSkippedMutants(command.checkerName, partitioned.undescribable);
4386
+ if (partitioned.undescribable.length > 0) yield* Metric.update(checkerMutantsSkipped, partitioned.undescribable.length);
4387
+ yield* Effect$1.annotateCurrentSpan({ "stryker.checker.skipped_mutants_count": partitioned.undescribable.length });
4388
+ const answers = yield* command.checker.check(command.checkerName, partitioned.wire);
4389
+ return {
4390
+ checkerName: command.checkerName,
4391
+ requestedIds: command.plans.map((plan) => plan.mutant.id),
4392
+ answers: {
4393
+ ...compileErrorAnswersOf(partitioned.undescribable),
4394
+ ...answers
4395
+ }
4396
+ };
4397
+ })).decode(Sandwich.pure((raw) => Result.succeed(CheckerCommand.make({
4398
+ checkerName: raw.checkerName,
4399
+ requestedIds: [...raw.requestedIds],
4400
+ phase: "check",
4401
+ answers: { ...raw.answers }
4402
+ })))).decide(admitCheckerAnswer).encode(Sandwich.pure((outcome) => Result.succeed(outcome))).write((outcome, raw) => writeCheckerOutcome(plans, raw.checkerName, outcome)).run({
4533
4403
  checker,
4534
4404
  checkerName,
4535
4405
  plans,
@@ -4540,31 +4410,25 @@ const checkPlans = (checker, checkerName, plans, lookup) => {
4540
4410
  * Ask a checker how to group run plans, and get groups of run plans back.
4541
4411
  */
4542
4412
  const groupPlans = (checker, checkerName, plans, lookup) => {
4543
- return Cell.layer({
4544
- read: (command) => Effect$1.gen(function* () {
4545
- const partitioned = Option.match(Option.fromUndefinedOr(command.lookup), {
4546
- onSome: (known) => selectedFromLookup(command.plans, known),
4547
- onNone: () => partitionMutantsForWire(command.plans)
4548
- });
4549
- yield* Effect$1.annotateCurrentSpan({ "stryker.checker.skipped_mutants_count": partitioned.undescribable.length });
4550
- const undescribableIds = undescribableIdsOf(partitioned.undescribable);
4551
- const withoutSkipped = (yield* command.checker.group(command.checkerName, partitioned.wire)).map((group) => group.filter((id) => !undescribableIds.has(id))).filter((group) => group.length > 0);
4552
- return {
4553
- checkerName: command.checkerName,
4554
- requestedIds: command.plans.map((plan) => plan.mutant.id),
4555
- idGroups: [...singletonGroupsOf(partitioned.undescribable), ...withoutSkipped]
4556
- };
4557
- }),
4558
- decode: (raw) => Result.succeed(CheckerCommand.make({
4559
- checkerName: raw.checkerName,
4560
- requestedIds: [...raw.requestedIds],
4561
- phase: "group",
4562
- idGroups: raw.idGroups.map((group) => [...group])
4563
- })),
4564
- decide: admitCheckerAnswer,
4565
- encode: (outcome) => outcome,
4566
- write: (outcome, raw) => writeGroupOutcome(plans, raw.checkerName, outcome)
4567
- }).run({
4413
+ return Sandwich.read((command) => Effect$1.gen(function* () {
4414
+ const partitioned = Option.match(Option.fromUndefinedOr(command.lookup), {
4415
+ onSome: (known) => selectedFromLookup(command.plans, known),
4416
+ onNone: () => partitionMutantsForWire(command.plans)
4417
+ });
4418
+ yield* Effect$1.annotateCurrentSpan({ "stryker.checker.skipped_mutants_count": partitioned.undescribable.length });
4419
+ const undescribableIds = undescribableIdsOf(partitioned.undescribable);
4420
+ const withoutSkipped = (yield* command.checker.group(command.checkerName, partitioned.wire)).map((group) => group.filter((id) => !undescribableIds.has(id))).filter((group) => group.length > 0);
4421
+ return {
4422
+ checkerName: command.checkerName,
4423
+ requestedIds: command.plans.map((plan) => plan.mutant.id),
4424
+ idGroups: [...singletonGroupsOf(partitioned.undescribable), ...withoutSkipped]
4425
+ };
4426
+ })).decode(Sandwich.pure((raw) => Result.succeed(CheckerCommand.make({
4427
+ checkerName: raw.checkerName,
4428
+ requestedIds: [...raw.requestedIds],
4429
+ phase: "group",
4430
+ idGroups: raw.idGroups.map((group) => [...group])
4431
+ })))).decide(admitCheckerAnswer).encode(Sandwich.pure((outcome) => Result.succeed(outcome))).write((outcome, raw) => writeGroupOutcome(plans, raw.checkerName, outcome)).run({
4568
4432
  checker,
4569
4433
  checkerName,
4570
4434
  plans,
@@ -4800,7 +4664,7 @@ function embeddedConfig(report) {
4800
4664
  }
4801
4665
  function breakThreshold(thresholds) {
4802
4666
  const ThresholdsBreakSchema = S.StructWithRest(S.Struct({ break: S.optional(S.Union([S.Finite, S.Null])) }), [S.Record(S.String, S.Unknown)]);
4803
- const decoded = S.decodeUnknownOption(ThresholdsBreakSchema)(thresholds);
4667
+ const decoded = S.decodeOption(ThresholdsBreakSchema)(thresholds);
4804
4668
  return Option.getOrNull(Option.flatMap(decoded, (value) => Option.fromNullishOr(value.break)));
4805
4669
  }
4806
4670
  const actionableMutants = (files) => Object.entries(files).flatMap(([file, fileResult]) => fileResult.mutants.filter((mutant) => isActionableStatus(mutant.status)).map((mutant) => ({
@@ -4965,7 +4829,7 @@ const makeMutationReportingService = (input) => {
4965
4829
  const resolved = yield* Effect$1.try(() => new URL(import.meta.resolve(`${specifier}/package.json`)));
4966
4830
  const manifestPath = yield* pathService.fromFileUrl(resolved);
4967
4831
  const text = yield* fs.readFileString(manifestPath);
4968
- return Result.match(S.decodeUnknownResult(S.fromJsonString(ManifestSchema))(text), {
4832
+ return Result.match(S.decodeResult(S.fromJsonString(ManifestSchema))(text), {
4969
4833
  onFailure: () => Option.none(),
4970
4834
  onSuccess: (manifest) => Option.some(manifest.version ?? "")
4971
4835
  });
@@ -5215,160 +5079,168 @@ const reportDroppedMutants = (dropped) => Match.value(dropped.length).pipe(Match
5215
5079
  yield* Metric.update(checkerMutantsSkipped, dropped.length);
5216
5080
  yield* Effect$1.logWarning(`${dropped.length} mutant(s) cannot be described to a checker and were left out of the run (${droppedIdsOf(dropped)})`);
5217
5081
  })));
5218
- const mutationTestCell$1 = Cell.layer({
5219
- read: (command) => Effect$1.gen(function* () {
5220
- yield* Scope.Scope;
5221
- return { prev: command };
5222
- }),
5223
- decode: (raw) => Result.succeed(MutationTestCommand.make({
5224
- dryRunOnly: raw.prev.options.dryRunOnly,
5225
- allowEmpty: raw.prev.options.allowEmpty,
5226
- testCount: raw.prev.dryRunResult.tests.length,
5227
- isZero: raw.prev.dryRunResult.tests.length === 0
5228
- })),
5229
- decide: admitMutationTest,
5230
- encode: (outcome) => outcome,
5231
- write: (outcome, raw) => {
5232
- const { dropped, plannable: plannableMutants } = partitionPlannable(raw.prev.mutants);
5233
- return withPhaseSpan("mutationTest", {
5234
- mutantCount: raw.prev.mutants.length,
5235
- skippedMutantCount: dropped.length,
5236
- testCount: raw.prev.dryRunResult.tests.length
5237
- }, () => Effect$1.gen(function* () {
5238
- yield* reportDroppedMutants(dropped);
5239
- const decision = yield* Result.match(outcome, {
5240
- onFailure: (err) => Effect$1.fail(StageError.make({
5241
- stage: err.stage,
5242
- reason: err.reason,
5243
- cause: err
5244
- })),
5245
- onSuccess: (d) => Effect$1.succeed(d)
5246
- });
5247
- return yield* Match.value(decision).pipe(Match.tag("MutationTestDryRunOnly", () => Effect$1.gen(function* () {
5248
- const env = yield* RunEnvironment;
5249
- const queue = yield* RunEvents;
5082
+ const mutationTestCell$1 = Sandwich.read((command) => Effect$1.gen(function* () {
5083
+ yield* Scope.Scope;
5084
+ return { prev: command };
5085
+ })).decode(Sandwich.pure((raw) => Result.succeed(MutationTestCommand.make({
5086
+ dryRunOnly: raw.prev.options.dryRunOnly,
5087
+ allowEmpty: raw.prev.options.allowEmpty,
5088
+ testCount: raw.prev.dryRunResult.tests.length,
5089
+ isZero: raw.prev.dryRunResult.tests.length === 0
5090
+ })))).decide(admitMutationTest).encode(Sandwich.pure((outcome) => Result.succeed(outcome))).write((outcome, raw) => {
5091
+ const { dropped, plannable: plannableMutants } = partitionPlannable(raw.prev.mutants);
5092
+ return withPhaseSpan("mutationTest", {
5093
+ mutantCount: raw.prev.mutants.length,
5094
+ skippedMutantCount: dropped.length,
5095
+ testCount: raw.prev.dryRunResult.tests.length
5096
+ }, () => Effect$1.gen(function* () {
5097
+ yield* reportDroppedMutants(dropped);
5098
+ const decision = yield* Result.match(outcome, {
5099
+ onFailure: (err) => Effect$1.fail(StageError.make({
5100
+ stage: err.stage,
5101
+ reason: err.reason,
5102
+ cause: err
5103
+ })),
5104
+ onSuccess: (d) => Effect$1.succeed(d)
5105
+ });
5106
+ return yield* Match.value(decision).pipe(Match.tag("MutationTestDryRunOnly", () => Effect$1.gen(function* () {
5107
+ const env = yield* RunEnvironment;
5108
+ const queue = yield* RunEvents;
5109
+ const nowEmit = yield* Clock.currentTimeMillis;
5110
+ yield* Queue.offer(queue, PhaseEntered.make({
5111
+ phase: "mutation-test",
5112
+ elapsedMs: nowEmit - env.runStartedAt
5113
+ }));
5114
+ yield* Effect$1.logInfo("The dry-run has been completed successfully. No mutations have been executed.");
5115
+ return {
5116
+ results: [],
5117
+ verdict: null
5118
+ };
5119
+ })), Match.tag("MutationTestNoTests", () => Effect$1.gen(function* () {
5120
+ const env = yield* RunEnvironment;
5121
+ const queue = yield* RunEvents;
5122
+ const now = yield* Clock.currentTimeMillis;
5123
+ const elapsed = Duration.millis(now - env.runStartedAt);
5124
+ yield* Effect$1.logInfo(`Done in ${Duration.format(elapsed)}.`);
5125
+ const nowEmit = yield* Clock.currentTimeMillis;
5126
+ yield* Queue.offer(queue, PhaseEntered.make({
5127
+ phase: "mutation-test",
5128
+ elapsedMs: nowEmit - env.runStartedAt
5129
+ }));
5130
+ return {
5131
+ results: [],
5132
+ verdict: null
5133
+ };
5134
+ })), Match.tag("MutationTestProceed", () => Effect$1.gen(function* () {
5135
+ const prev = raw.prev;
5136
+ const env = yield* RunEnvironment;
5137
+ yield* Effect$1.gen(function* () {
5250
5138
  const nowEmit = yield* Clock.currentTimeMillis;
5251
- yield* Queue.offer(queue, PhaseEntered.make({
5252
- phase: "mutation-test",
5253
- elapsedMs: nowEmit - env.runStartedAt
5254
- }));
5255
- yield* Effect$1.logInfo("The dry-run has been completed successfully. No mutations have been executed.");
5256
- return {
5257
- results: [],
5258
- verdict: null
5259
- };
5260
- })), Match.tag("MutationTestNoTests", () => Effect$1.gen(function* () {
5261
- const env = yield* RunEnvironment;
5262
5139
  const queue = yield* RunEvents;
5263
- const now = yield* Clock.currentTimeMillis;
5264
- const elapsed = Duration.millis(now - env.runStartedAt);
5265
- yield* Effect$1.logInfo(`Done in ${Duration.format(elapsed)}.`);
5266
- const nowEmit = yield* Clock.currentTimeMillis;
5267
5140
  yield* Queue.offer(queue, PhaseEntered.make({
5268
5141
  phase: "mutation-test",
5269
5142
  elapsedMs: nowEmit - env.runStartedAt
5270
5143
  }));
5144
+ });
5145
+ const idGenerator = yield* IdGenerator;
5146
+ const checkerPool = yield* makeCheckerPool(prev, idGenerator, env.basePath);
5147
+ const testRunnerContext = {
5148
+ options: prev.options,
5149
+ fileDescriptions: prev.project.fileDescriptions,
5150
+ sandboxWorkingDirectory: prev.sandbox.workingDirectory,
5151
+ idGenerator,
5152
+ retire: Effect$1.void,
5153
+ testFiles: prev.project.testFiles.map((file) => prev.sandbox.sandboxFileFor(file))
5154
+ };
5155
+ const testRunnerPool = yield* Pool.make({
5156
+ acquire: buildTestRunner(testRunnerContext, Effect$1.suspend(() => {
5157
+ const runnerConfigured = prev.options.testRunner;
5158
+ const runnerLabel = Match.value(runnerConfigured).pipe(Match.when(isCustomTestRunner, (runner) => runner.plugin), Match.orElse((name) => name));
5159
+ return resolveConfiguredWorkerSpawn({
5160
+ loaded: prev.loadedPlugins,
5161
+ kind: "TestRunner",
5162
+ configured: runnerConfigured
5163
+ }).pipe(Effect$1.mapError(missingWorkerEntry("mutationTest", "test runner", runnerLabel)), Effect$1.flatMap(({ spawn }) => makeChildProcessTestRunner({
5164
+ options: prev.options,
5165
+ fileDescriptions: prev.project.fileDescriptions,
5166
+ sandboxWorkingDirectory: prev.sandbox.workingDirectory,
5167
+ workerEntrypoint: spawn.entrypoint,
5168
+ idGenerator
5169
+ })));
5170
+ })),
5171
+ size: prev.concurrency.testRunners
5172
+ });
5173
+ const reporting = makeMutationReportingService({
5174
+ reporterStage: prev.reporterStage,
5175
+ options: prev.options,
5176
+ project: prev.project,
5177
+ testCoverage: prev.testCoverage,
5178
+ runId: env.runId,
5179
+ resolvedMode: env.resolvedMode,
5180
+ sandboxDirectory: prev.sandbox.workingDirectory,
5181
+ basePath: env.basePath
5182
+ });
5183
+ const sandboxFileByName = Object.fromEntries([...MutableHashMap.keys(prev.project.filesToMutate)].map((name) => [name, prev.sandbox.sandboxFileFor(name)]));
5184
+ const currentRelativeFiles = yield* readCurrentRelativeFiles(prev.project, env.basePath);
5185
+ const incremental = incrementalDiff({
5186
+ currentMutants: plannableMutants,
5187
+ testCoverage: prev.testCoverage,
5188
+ incrementalReport: prev.project.incrementalReport,
5189
+ currentRelativeFiles,
5190
+ basePath: env.basePath,
5191
+ force: prev.options.force
5192
+ });
5193
+ const rememberedResults = rememberedResultsOf(plannableMutants, incremental.remembered);
5194
+ yield* Effect$1.when(Effect$1.logInfo(`Incremental mode: reusing ${rememberedResults.length} mutant result(s), running ${incremental.mutants.length} mutant(s).`), Effect$1.succeed(rememberedResults.length > 0));
5195
+ const { runPlans, earlyResults: noCoverageResults } = partitionRunPlans(yield* decidePlans(incremental.mutants, prev.testCoverage, {
5196
+ disableBail: prev.options.disableBail,
5197
+ timeoutMS: prev.options.timeoutMS,
5198
+ timeoutFactor: prev.options.timeoutFactor,
5199
+ ignoreStatic: prev.options.ignoreStatic
5200
+ }, Duration.toMillis(prev.timeOverhead), void 0, sandboxFileByName));
5201
+ const sortedPlans = sortRunPlans(runPlans);
5202
+ const allPlansForReporter = [...sortedPlans];
5203
+ yield* offerReporterEvent(prev.reporterStage, MutationTestingPlanReady.make({
5204
+ total: allPlansForReporter.length + noCoverageResults.length + rememberedResults.length,
5205
+ plans: allPlansForReporter.map((plan) => ({
5206
+ mutantId: plan.mutant.id,
5207
+ plan: plan.plan,
5208
+ netTime: plan.netTime,
5209
+ reloadEnvironment: plan.runOptions.reloadEnvironment
5210
+ }))
5211
+ })).pipe(Effect$1.ignoreCause);
5212
+ {
5213
+ const queue2 = yield* RunEvents;
5214
+ yield* Queue.offer(queue2, PlanKnown.make({ total: allPlansForReporter.length + noCoverageResults.length }));
5215
+ }
5216
+ const { passedPlans, checkerResults } = yield* checkPlansWithConfiguredCheckers(checkerPool, sortedPlans, reporting);
5217
+ const testRunnerStream = Stream.fromIterable(passedPlans);
5218
+ const plannedTotal = allPlansForReporter.length + noCoverageResults.length + rememberedResults.length;
5219
+ const pathService = yield* Path.Path;
5220
+ const progressQueue = yield* RunEvents;
5221
+ const completedRef = yield* Ref.make(0);
5222
+ const preparedStreamableOf = (result) => {
5223
+ if (!isMutantStatus(result.status)) return;
5271
5224
  return {
5272
- results: [],
5273
- verdict: null
5274
- };
5275
- })), Match.tag("MutationTestProceed", () => Effect$1.gen(function* () {
5276
- const prev = raw.prev;
5277
- const env = yield* RunEnvironment;
5278
- yield* Effect$1.gen(function* () {
5279
- const nowEmit = yield* Clock.currentTimeMillis;
5280
- const queue = yield* RunEvents;
5281
- yield* Queue.offer(queue, PhaseEntered.make({
5282
- phase: "mutation-test",
5283
- elapsedMs: nowEmit - env.runStartedAt
5284
- }));
5285
- });
5286
- const idGenerator = yield* IdGenerator;
5287
- const checkerPool = yield* makeCheckerPool(prev, idGenerator, env.basePath);
5288
- const testRunnerContext = {
5289
- options: prev.options,
5290
- fileDescriptions: prev.project.fileDescriptions,
5291
- sandboxWorkingDirectory: prev.sandbox.workingDirectory,
5292
- idGenerator,
5293
- retire: Effect$1.void,
5294
- testFiles: prev.project.testFiles.map((file) => prev.sandbox.sandboxFileFor(file))
5225
+ status: result.status,
5226
+ file: reportFileName(pathService.relative(env.basePath, result.fileName)),
5227
+ location: toSchemaLocation(result.location)
5295
5228
  };
5296
- const testRunnerPool = yield* Pool.make({
5297
- acquire: buildTestRunner(testRunnerContext, Effect$1.suspend(() => {
5298
- const runnerConfigured = prev.options.testRunner;
5299
- const runnerLabel = Match.value(runnerConfigured).pipe(Match.when(isCustomTestRunner, (runner) => runner.plugin), Match.orElse((name) => name));
5300
- return resolveConfiguredWorkerSpawn({
5301
- loaded: prev.loadedPlugins,
5302
- kind: "TestRunner",
5303
- configured: runnerConfigured
5304
- }).pipe(Effect$1.mapError(missingWorkerEntry("mutationTest", "test runner", runnerLabel)), Effect$1.flatMap(({ spawn }) => makeChildProcessTestRunner({
5305
- options: prev.options,
5306
- fileDescriptions: prev.project.fileDescriptions,
5307
- sandboxWorkingDirectory: prev.sandbox.workingDirectory,
5308
- workerEntrypoint: spawn.entrypoint,
5309
- idGenerator
5310
- })));
5311
- })),
5312
- size: prev.concurrency.testRunners
5313
- });
5314
- const reporting = makeMutationReportingService({
5315
- reporterStage: prev.reporterStage,
5316
- options: prev.options,
5317
- project: prev.project,
5318
- testCoverage: prev.testCoverage,
5319
- runId: env.runId,
5320
- resolvedMode: env.resolvedMode,
5321
- sandboxDirectory: prev.sandbox.workingDirectory,
5322
- basePath: env.basePath
5323
- });
5324
- const sandboxFileByName = Object.fromEntries([...MutableHashMap.keys(prev.project.filesToMutate)].map((name) => [name, prev.sandbox.sandboxFileFor(name)]));
5325
- const currentRelativeFiles = yield* readCurrentRelativeFiles(prev.project, env.basePath);
5326
- const incremental = incrementalDiff({
5327
- currentMutants: plannableMutants,
5328
- testCoverage: prev.testCoverage,
5329
- incrementalReport: prev.project.incrementalReport,
5330
- currentRelativeFiles,
5331
- basePath: env.basePath,
5332
- force: prev.options.force
5333
- });
5334
- const rememberedResults = rememberedResultsOf(plannableMutants, incremental.remembered);
5335
- yield* Effect$1.when(Effect$1.logInfo(`Incremental mode: reusing ${rememberedResults.length} mutant result(s), running ${incremental.mutants.length} mutant(s).`), Effect$1.succeed(rememberedResults.length > 0));
5336
- const { runPlans, earlyResults: noCoverageResults } = partitionRunPlans(yield* decidePlans(incremental.mutants, prev.testCoverage, {
5337
- disableBail: prev.options.disableBail,
5338
- timeoutMS: prev.options.timeoutMS,
5339
- timeoutFactor: prev.options.timeoutFactor,
5340
- ignoreStatic: prev.options.ignoreStatic
5341
- }, Duration.toMillis(prev.timeOverhead), void 0, sandboxFileByName));
5342
- const sortedPlans = sortRunPlans(runPlans);
5343
- const allPlansForReporter = [...sortedPlans];
5344
- yield* offerReporterEvent(prev.reporterStage, MutationTestingPlanReady.make({
5345
- total: allPlansForReporter.length + noCoverageResults.length + rememberedResults.length,
5346
- plans: allPlansForReporter.map((plan) => ({
5347
- mutantId: plan.mutant.id,
5348
- plan: plan.plan,
5349
- netTime: plan.netTime,
5350
- reloadEnvironment: plan.runOptions.reloadEnvironment
5351
- }))
5352
- })).pipe(Effect$1.ignoreCause);
5353
- {
5354
- const queue2 = yield* RunEvents;
5355
- yield* Queue.offer(queue2, PlanKnown.make({ total: allPlansForReporter.length + noCoverageResults.length }));
5356
- }
5357
- const { passedPlans, checkerResults } = yield* checkPlansWithConfiguredCheckers(checkerPool, sortedPlans, reporting);
5358
- const testRunnerStream = Stream.fromIterable(passedPlans);
5359
- const plannedTotal = allPlansForReporter.length + noCoverageResults.length + rememberedResults.length;
5360
- const pathService = yield* Path.Path;
5361
- const progressQueue = yield* RunEvents;
5362
- const completedRef = yield* Ref.make(0);
5363
- const preparedStreamableOf = (result) => {
5364
- if (!isMutantStatus(result.status)) return;
5365
- return {
5366
- status: result.status,
5367
- file: reportFileName(pathService.relative(env.basePath, result.fileName)),
5368
- location: toSchemaLocation(result.location)
5369
- };
5370
- };
5371
- const toStreamEvent = (result, completed, prepared) => MutantTested.make({
5229
+ };
5230
+ const toStreamEvent = (result, completed, prepared) => MutantTested.make({
5231
+ id: result.id,
5232
+ status: prepared.status,
5233
+ file: prepared.file,
5234
+ location: prepared.location,
5235
+ mutator: result.mutatorName,
5236
+ replacement: result.replacement,
5237
+ completed,
5238
+ total: plannedTotal
5239
+ });
5240
+ const offerFinished = (result, prepared) => Effect$1.gen(function* () {
5241
+ if (prepared === void 0) return;
5242
+ const completed = yield* Ref.updateAndGet(completedRef, (n) => n + 1);
5243
+ yield* Queue.offer(progressQueue, RunMutantTested.make({
5372
5244
  id: result.id,
5373
5245
  status: prepared.status,
5374
5246
  file: prepared.file,
@@ -5377,90 +5249,76 @@ const mutationTestCell$1 = Cell.layer({
5377
5249
  replacement: result.replacement,
5378
5250
  completed,
5379
5251
  total: plannedTotal
5380
- });
5381
- const offerFinished = (result, prepared) => Effect$1.gen(function* () {
5382
- if (prepared === void 0) return;
5383
- const completed = yield* Ref.updateAndGet(completedRef, (n) => n + 1);
5384
- yield* Queue.offer(progressQueue, RunMutantTested.make({
5385
- id: result.id,
5386
- status: prepared.status,
5387
- file: prepared.file,
5388
- location: prepared.location,
5389
- mutator: result.mutatorName,
5390
- replacement: result.replacement,
5391
- completed,
5392
- total: plannedTotal
5393
- }));
5394
- return completed;
5395
- });
5396
- const reportStreamTested = (result, completed, prepared) => offerReporterEvent(prev.reporterStage, toStreamEvent(result, completed, prepared)).pipe(Effect$1.catchCause((cause) => Effect$1.logWarning("Reporter stream failed handling mutantTested", cause)));
5397
- const offerStreamTested = (result, completed, prepared) => Option.match(Option.all([Option.fromNullishOr(completed), Option.fromNullishOr(prepared)]), {
5398
- onNone: () => Effect$1.void,
5399
- onSome: ([done, streamable]) => reportStreamTested(result, done, streamable)
5400
- });
5401
- const announceSettledMutant = (result) => Effect$1.gen(function* () {
5402
- const prepared = preparedStreamableOf(result);
5403
- const completed = yield* offerFinished(result, prepared);
5404
- yield* offerStreamTested(result, completed, prepared);
5405
- });
5406
- yield* Effect$1.forEach([
5407
- ...rememberedResults,
5408
- ...noCoverageResults,
5409
- ...checkerResults
5410
- ], announceSettledMutant, {
5411
- concurrency: 1,
5412
- discard: true
5413
- });
5414
- const completedMutants = yield* Ref.make([
5415
- ...rememberedResults,
5416
- ...noCoverageResults,
5417
- ...checkerResults
5418
- ]);
5419
- const checkpointGate = yield* Semaphore.make(1);
5420
- yield* reporting.checkpoint(yield* Ref.get(completedMutants)).pipe(Effect$1.catchCause((cause) => Effect$1.logWarning("Failed to persist the mutation checkpoint", cause)));
5421
- const persist = (result) => checkpointGate.withPermits(1)(Effect$1.gen(function* () {
5422
- const next = yield* Ref.updateAndGet(completedMutants, (prev) => [...prev, result]);
5423
- yield* reporting.checkpoint(next).pipe(Effect$1.catchCause((cause) => Effect$1.logWarning("Failed to persist the mutation checkpoint", cause)));
5424
5252
  }));
5425
- const runResults = yield* withPhaseSpan("mutationTest.batch", {
5426
- total: plannedTotal,
5427
- testRunners: prev.concurrency.testRunners
5428
- }, () => Stream.mapEffect(testRunnerStream, (plan) => Effect$1.scoped(Effect$1.gen(function* () {
5429
- const pool = testRunnerPool;
5430
- const runner = yield* Pool.get(pool);
5431
- const result = yield* runner.mutantRun(plan.runOptions).pipe(Effect$1.withSpan("stryker.testRunner.mutantRun", { attributes: {
5432
- "stryker.mutant.id": plan.mutant.id,
5433
- "stryker.mutant.mutator": plan.mutant.mutatorName,
5434
- "stryker.mutant.file": plan.mutant.fileName
5435
- } }), Effect$1.tap((runResult) => Effect$1.annotateCurrentSpan({ "stryker.mutant.status": runResult.status })), Effect$1.catchTags({
5436
- OutOfMemoryError: (error) => invalidateSlot(pool, runner, error),
5437
- ChildProcessCrashedError: (error) => invalidateSlot(pool, runner, error)
5438
- }));
5439
- const reported = yield* reporting.reportMutantRunResult(toReportedMutant(plan.mutant), result);
5440
- const prepared = preparedStreamableOf(reported);
5441
- const finished = yield* offerFinished(reported, prepared);
5442
- yield* offerStreamTested(reported, finished, prepared);
5443
- yield* persist(reported);
5444
- return reported;
5445
- })), { concurrency: Math.max(1, prev.concurrency.testRunners) }).pipe(Stream.runCollect, Effect$1.map((chunk) => [...chunk])));
5446
- const allResults = [
5447
- ...rememberedResults,
5448
- ...noCoverageResults,
5449
- ...checkerResults,
5450
- ...runResults
5451
- ];
5452
- const outcomeResult = yield* reporting.reportAll(allResults);
5453
- const doneNow = yield* Clock.currentTimeMillis;
5454
- const elapsed = Duration.millis(doneNow - env.runStartedAt);
5455
- yield* Effect$1.logInfo(`Done in ${Duration.format(elapsed)}.`);
5456
- return outcomeResult;
5457
- })), Match.exhaustive);
5458
- })).pipe(Effect$1.mapError((cause) => Match.value(cause).pipe(Match.tag("StageError", (stage) => stage), Match.tag("ChildProcessCrashedError", "OutOfMemoryError", "PlatformError", "TestRunnerFailed", () => StageError.make({
5459
- stage: "mutationTest",
5460
- reason: "Mutation testing failed",
5461
- cause
5462
- })), Match.exhaustive)));
5463
- }
5253
+ return completed;
5254
+ });
5255
+ const reportStreamTested = (result, completed, prepared) => offerReporterEvent(prev.reporterStage, toStreamEvent(result, completed, prepared)).pipe(Effect$1.tapCause((cause) => Effect$1.logWarning("Reporter stream failed handling mutantTested", cause)), Effect$1.ignoreCause);
5256
+ const offerStreamTested = (result, completed, prepared) => Option.match(Option.all([Option.fromNullishOr(completed), Option.fromNullishOr(prepared)]), {
5257
+ onNone: () => Effect$1.void,
5258
+ onSome: ([done, streamable]) => reportStreamTested(result, done, streamable)
5259
+ });
5260
+ const announceSettledMutant = (result) => Effect$1.gen(function* () {
5261
+ const prepared = preparedStreamableOf(result);
5262
+ const completed = yield* offerFinished(result, prepared);
5263
+ yield* offerStreamTested(result, completed, prepared);
5264
+ });
5265
+ yield* Effect$1.forEach([
5266
+ ...rememberedResults,
5267
+ ...noCoverageResults,
5268
+ ...checkerResults
5269
+ ], announceSettledMutant, {
5270
+ concurrency: 1,
5271
+ discard: true
5272
+ });
5273
+ const completedMutants = yield* Ref.make([
5274
+ ...rememberedResults,
5275
+ ...noCoverageResults,
5276
+ ...checkerResults
5277
+ ]);
5278
+ const checkpointGate = yield* Semaphore.make(1);
5279
+ yield* reporting.checkpoint(yield* Ref.get(completedMutants)).pipe(Effect$1.tapCause((cause) => Effect$1.logWarning("Failed to persist the mutation checkpoint", cause)), Effect$1.ignoreCause);
5280
+ const persist = (result) => checkpointGate.withPermits(1)(Effect$1.gen(function* () {
5281
+ const next = yield* Ref.updateAndGet(completedMutants, (prev) => [...prev, result]);
5282
+ yield* reporting.checkpoint(next).pipe(Effect$1.tapCause((cause) => Effect$1.logWarning("Failed to persist the mutation checkpoint", cause)), Effect$1.ignoreCause);
5283
+ }));
5284
+ const runResults = yield* withPhaseSpan("mutationTest.batch", {
5285
+ total: plannedTotal,
5286
+ testRunners: prev.concurrency.testRunners
5287
+ }, () => Stream.mapEffect(testRunnerStream, (plan) => Effect$1.scoped(Effect$1.gen(function* () {
5288
+ const pool = testRunnerPool;
5289
+ const runner = yield* Pool.get(pool);
5290
+ const result = yield* runner.mutantRun(plan.runOptions).pipe(Effect$1.withSpan("stryker.testRunner.mutantRun", { attributes: {
5291
+ "stryker.mutant.id": plan.mutant.id,
5292
+ "stryker.mutant.mutator": plan.mutant.mutatorName,
5293
+ "stryker.mutant.file": plan.mutant.fileName
5294
+ } }), Effect$1.tap((runResult) => Effect$1.annotateCurrentSpan({ "stryker.mutant.status": runResult.status })), Effect$1.catchTags({
5295
+ OutOfMemoryError: (error) => invalidateSlot(pool, runner, error),
5296
+ ChildProcessCrashedError: (error) => invalidateSlot(pool, runner, error)
5297
+ }));
5298
+ const reported = yield* reporting.reportMutantRunResult(toReportedMutant(plan.mutant), result);
5299
+ const prepared = preparedStreamableOf(reported);
5300
+ const finished = yield* offerFinished(reported, prepared);
5301
+ yield* offerStreamTested(reported, finished, prepared);
5302
+ yield* persist(reported);
5303
+ return reported;
5304
+ })), { concurrency: Math.max(1, prev.concurrency.testRunners) }).pipe(Stream.runCollect, Effect$1.map((chunk) => [...chunk])));
5305
+ const allResults = [
5306
+ ...rememberedResults,
5307
+ ...noCoverageResults,
5308
+ ...checkerResults,
5309
+ ...runResults
5310
+ ];
5311
+ const outcomeResult = yield* reporting.reportAll(allResults);
5312
+ const doneNow = yield* Clock.currentTimeMillis;
5313
+ const elapsed = Duration.millis(doneNow - env.runStartedAt);
5314
+ yield* Effect$1.logInfo(`Done in ${Duration.format(elapsed)}.`);
5315
+ return outcomeResult;
5316
+ })), Match.exhaustive);
5317
+ })).pipe(Effect$1.mapError((cause) => Match.value(cause).pipe(Match.tag("StageError", (stage) => stage), Match.tag("ChildProcessCrashedError", "OutOfMemoryError", "PlatformError", "TestRunnerFailed", () => StageError.make({
5318
+ stage: "mutationTest",
5319
+ reason: "Mutation testing failed",
5320
+ cause
5321
+ })), Match.exhaustive)));
5464
5322
  });
5465
5323
  //#endregion
5466
5324
  //#region src/reporter-output.ts
@@ -5475,7 +5333,7 @@ const write = (stdio, channel, chunks) => Stream.run(Stream.fromIterable(chunks)
5475
5333
  * that cannot compose Effects — its writes fire inside a synchronous for-await).
5476
5334
  * Write errors are ignored like a broken pipe on a stream handle.
5477
5335
  *
5478
- * Note: effect 4.0.0-rc.112 exports the runner as `Effect.runPromise`; there is no
5336
+ * Note: effect 4.0.0-rc.116 exports the runner as `Effect.runPromise`; there is no
5479
5337
  * `Runtime.runPromise` in this version (verified against the installed source) —
5480
5338
  * do not invent that import.
5481
5339
  */
@@ -5887,7 +5745,7 @@ const rememberTerminalReport = (seen, event) => {
5887
5745
  };
5888
5746
  }), Match.orElse(() => void 0));
5889
5747
  };
5890
- const decodeClearTextReport = (terminal) => S.decodeUnknownEffect(ClearTextReportCommand)({
5748
+ const decodeClearTextReport = (terminal) => S.decodeEffect(ClearTextReportCommand)({
5891
5749
  _tag: "ClearTextReportCommand",
5892
5750
  report: terminal.report,
5893
5751
  metrics: terminal.metrics
@@ -6329,13 +6187,7 @@ const writePrepare = (outcome, raw) => withPhaseSpan("prepare", {}, (span) => Ef
6329
6187
  reporterStage
6330
6188
  };
6331
6189
  }));
6332
- const prepareCell = Cell.layer({
6333
- read: readPrepare,
6334
- decode: decodePrepare,
6335
- decide: planPrepare,
6336
- encode: encodePrepareDecision,
6337
- write: writePrepare
6338
- });
6190
+ const prepareCell = Sandwich.read(readPrepare).decode(Sandwich.pure(decodePrepare)).decide(planPrepare).encode(Sandwich.pure((outcome) => Result.succeed(encodePrepareDecision(outcome)))).write(writePrepare);
6339
6191
  //#endregion
6340
6192
  //#region src/Run.ts
6341
6193
  const RUN_EVENTS_QUEUE_BOUND = 256;
@@ -6385,7 +6237,7 @@ const framedEventOf = (decision) => Option.match(decision, {
6385
6237
  onSome: (d) => Match.value(d).pipe(Match.tag("EventFramed", (framed) => Result.succeed(framed.event)), Match.tag("EventSuppressed", () => Result.fail(void 0)), Match.exhaustive)
6386
6238
  });
6387
6239
  var RunEventDrain = class extends Context.Service()("@systemfsoftware/stryker-js/run-event-stream/RunEventDrain") {};
6388
- const drainOf = (stdio, framed) => Stream.run(framed, stdio.stdout({ endOnDone: true })).pipe(Effect$1.withSpan("stryker.output.drain"), Effect$1.catchCause((cause) => Effect$1.logError("stryker.output.drain_failed", cause)));
6240
+ const drainOf = (stdio, framed) => Stream.run(framed, stdio.stdout({ endOnDone: true })).pipe(Effect$1.withSpan("stryker.output.drain"), Effect$1.tapCause((cause) => Effect$1.logError("stryker.output.drain_failed", cause)), Effect$1.ignoreCause);
6389
6241
  const RunEventDrainLive = Layer.effect(RunEventDrain, Effect$1.gen(function* () {
6390
6242
  const stdio = yield* Stdio.Stdio;
6391
6243
  return RunEventDrain.of({
@@ -6552,7 +6404,7 @@ const RunEventDrainFileLive = Layer.effect(RunEventDrain, Effect$1.gen(function*
6552
6404
  drainFramed: (framed) => Effect$1.gen(function* () {
6553
6405
  const fileName = yield* Ref.get(fileNameRef);
6554
6406
  yield* drainStdoutAndFile(fs, path, stdio, fileName, framed);
6555
- }).pipe(Effect$1.catchCause((cause) => Effect$1.logError("stryker.output.drain_file_failed", cause))),
6407
+ }).pipe(Effect$1.tapCause((cause) => Effect$1.logError("stryker.output.drain_file_failed", cause)), Effect$1.ignoreCause),
6556
6408
  setProgressStreamFile: (fileName) => Ref.set(fileNameRef, fileName)
6557
6409
  });
6558
6410
  }));