@systemfsoftware/stryker-js-cli 4.0.2 → 4.0.3

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/main.mjs +56 -58
  3. package/package.json +10 -10
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @systemfsoftware/stryker-js-cli
2
2
 
3
+ ## 4.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Refreshed builds on the platform-services dependency graph; the packages no longer reach for host builtins directly. No CLI flags or option names change.
8
+
9
+ - Updated dependencies:
10
+ - @systemfsoftware/stryker-js@0.2.0
11
+ - @systemfsoftware/stryker-js-platform-node@0.2.0
12
+
3
13
  ## 4.0.2
4
14
 
5
15
  ### Patch Changes
package/dist/main.mjs CHANGED
@@ -1,10 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { createRequire } from "node:module";
3
- import * as NodeFileSystem from "@effect/platform-node-shared/NodeFileSystem";
4
- import * as NodePath from "@effect/platform-node-shared/NodePath";
2
+ import * as NodeFileSystem$1 from "@effect/platform-node-shared/NodeFileSystem";
3
+ import * as NodePath$1 from "@effect/platform-node-shared/NodePath";
5
4
  import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
6
5
  import * as NodeStdio from "@effect/platform-node/NodeStdio";
7
- import { ConfigFileUnreadableError, buildVerdictEnvelope, defaultOptions, generateRunId, makeRunLayer, readConfig, runMutationTest, strykerEngines, strykerVersion, toRelativeNormalizedFileName } from "@systemfsoftware/stryker-js-platform-node";
6
+ import { ConfigFileUnreadableError, buildVerdictEnvelope, defaultOptions, generateRunId, makeRunLayer, nodeModuleLayer, readConfig, runMutationTest, strykerEngines, strykerVersion, toRelativeNormalizedFileName } from "@systemfsoftware/stryker-js-platform-node";
8
7
  import * as Effect from "effect/Effect";
9
8
  import * as Exit from "effect/Exit";
10
9
  import * as Layer from "effect/Layer";
@@ -30,8 +29,6 @@ import * as CliError from "effect/unstable/cli/CliError";
30
29
  import * as Command from "effect/unstable/cli/Command";
31
30
  import * as Flag from "effect/unstable/cli/Flag";
32
31
  import * as GlobalFlag from "effect/unstable/cli/GlobalFlag";
33
- import { readFileSync } from "node:fs";
34
- import { resolve } from "node:path";
35
32
  import { ExitClass, highestExitClass } from "@systemfsoftware/stryker-js/ExitClass";
36
33
  import { Mutant, causeText } from "@systemfsoftware/stryker-js/Mutant";
37
34
  import * as Clock from "effect/Clock";
@@ -42,8 +39,10 @@ import * as Context from "effect/Context";
42
39
  import { pipe } from "effect/Function";
43
40
  import * as Stdio from "effect/Stdio";
44
41
  import * as Stream from "effect/Stream";
42
+ import { NodeFileSystem, NodePath } from "@effect/platform-node";
45
43
  import { sha256 } from "@noble/hashes/sha256";
46
44
  import { bytesToHex, utf8ToBytes } from "@noble/hashes/utils";
45
+ import "@systemfsoftware/stryker-js/Module";
47
46
  //#region src/RunOutcome.workflow.ts
48
47
  var RunOutcomeCommand = class extends S.TaggedClass()("RunOutcomeCommand", {
49
48
  succeeded: S.Boolean,
@@ -1184,7 +1183,6 @@ function survivorMutateSpans(survivors, basePath) {
1184
1183
  return spans;
1185
1184
  }
1186
1185
  const hashContent = (content) => bytesToHex(sha256(utf8ToBytes(content)));
1187
- const resolveAbsolutePath = (file) => resolve(file);
1188
1186
  /**
1189
1187
  * The survivors admission, as a description whose phases chain by type and
1190
1188
  * read in the order they run. The read gathers the admission's whole input
@@ -1196,8 +1194,9 @@ const resolveAbsolutePath = (file) => resolve(file);
1196
1194
  * stashed context back and dispatches the decision to the verdict/run,
1197
1195
  * failing the run with a rejection.
1198
1196
  */
1199
- const survivorsAdmissionDescription = (runMutationTest, stream, mode, runContext, basePath, services) => pipe(Cell.read((cliOptions) => Effect.provideContext(Effect.flatMap(Path.Path, (pathService) => resolveSurvivorsRunOptions(cliOptions, basePath).pipe(Effect.flatMap((resolvedOptions) => {
1197
+ const survivorsAdmissionDescription = (runMutationTest, stream, mode, runContext, basePath) => pipe(Cell.read((cliOptions) => Effect.flatMap(Path.Path, (pathService) => resolveSurvivorsRunOptions(cliOptions, basePath).pipe(Effect.flatMap((resolvedOptions) => {
1200
1198
  const priorReportPath = priorReportPathOf(resolvedOptions);
1199
+ const resolveAbsolutePath = (file) => pathService.resolve(file);
1201
1200
  return Effect.flatMap(readPriorReport(priorReportPath), (read) => Effect.flatMap(currentSourceHashesFor(priorReportFileKeys(read.raw)), (sourceContentHashes) => Ref.set(runContext, {
1202
1201
  resolvedOptions,
1203
1202
  priorReportPath,
@@ -1207,9 +1206,10 @@ const survivorsAdmissionDescription = (runMutationTest, stream, mode, runContext
1207
1206
  priorReportRaw: read.raw,
1208
1207
  priorReportFound: read.found,
1209
1208
  priorReportPath,
1210
- sourceContentHashes
1209
+ sourceContentHashes,
1210
+ resolveAbsolutePath
1211
1211
  }))));
1212
- }))), services)), Cell.decode(({ resolvedOptions, priorReportRaw, priorReportFound, sourceContentHashes }) => {
1212
+ }))).pipe(Effect.provide(Layer.mergeAll(NodeFileSystem.layer, NodePath.layer, nodeModuleLayer)))), Cell.decode(({ resolvedOptions, priorReportRaw, priorReportFound, sourceContentHashes, resolveAbsolutePath }) => {
1213
1213
  if (!priorReportFound) return Result.succeed(AdmitSurvivorsRunCommand.make({
1214
1214
  priorReport: void 0,
1215
1215
  currentConfig: resolvedOptions,
@@ -1261,9 +1261,8 @@ const survivorsAdmissionDescription = (runMutationTest, stream, mode, runContext
1261
1261
  */
1262
1262
  function runSurvivorsAdmission(runMutationTest, stream, mode, cliOptions, basePath) {
1263
1263
  return Effect.gen(function* () {
1264
- const services = yield* Effect.context();
1265
1264
  const admissionContext = yield* Ref.make(void 0);
1266
- return yield* Cell.apply(survivorsAdmissionDescription(runMutationTest, stream, mode, admissionContext, basePath, services), cliOptions);
1265
+ return yield* Cell.apply(survivorsAdmissionDescription(runMutationTest, stream, mode, admissionContext, basePath), cliOptions);
1267
1266
  });
1268
1267
  }
1269
1268
  function resolveSurvivorsRunOptions(cliOptions, basePath) {
@@ -1513,37 +1512,49 @@ function describeCommandNode(node) {
1513
1512
  };
1514
1513
  }
1515
1514
  function readCoreEntries() {
1516
- try {
1517
- const manifestPath = createRequire(import.meta.url).resolve("@systemfsoftware/stryker-js-platform-node/package.json");
1518
- const raw = readFileSync(manifestPath, "utf-8");
1519
- const parsed = JSON.parse(raw);
1515
+ return Effect.gen(function* () {
1516
+ const path = yield* Path.Path;
1517
+ const fs = yield* FileSystem.FileSystem;
1518
+ const resolved = import.meta.resolve("@systemfsoftware/stryker-js-platform-node/package.json");
1519
+ const manifestPath = yield* path.fromFileUrl(new URL(resolved));
1520
+ const raw = yield* fs.readFileString(manifestPath);
1521
+ let parsed;
1522
+ try {
1523
+ parsed = JSON.parse(raw);
1524
+ } catch {
1525
+ return [];
1526
+ }
1520
1527
  const ExportsSchema = S.Struct({ exports: S.Record(S.String, S.Unknown) });
1521
1528
  const decoded = S.decodeUnknownResult(ExportsSchema)(parsed);
1522
1529
  if (Result.isSuccess(decoded)) return Object.keys(decoded.success.exports).filter((key) => key !== "./package.json");
1523
1530
  return [];
1524
- } catch {
1525
- return [];
1526
- }
1531
+ }).pipe(Effect.catchCause(() => {
1532
+ return Effect.succeed([]);
1533
+ }), Effect.catchDefect(() => {
1534
+ return Effect.succeed([]);
1535
+ }));
1527
1536
  }
1528
1537
  function buildLLMSManifest(command, version) {
1529
- const root = describeCommandNode(command) ?? {
1530
- name: "",
1531
- description: "",
1532
- options: [],
1533
- args: [],
1534
- subcommands: []
1535
- };
1536
- return {
1537
- schemaVersion: "1.0",
1538
- tool: root.name,
1539
- version,
1540
- commands: [root],
1541
- entries: readCoreEntries()
1542
- };
1538
+ return Effect.gen(function* () {
1539
+ const root = describeCommandNode(command) ?? {
1540
+ name: "",
1541
+ description: "",
1542
+ options: [],
1543
+ args: [],
1544
+ subcommands: []
1545
+ };
1546
+ const entries = yield* readCoreEntries();
1547
+ return {
1548
+ schemaVersion: "1.0",
1549
+ tool: root.name,
1550
+ version,
1551
+ commands: [root],
1552
+ entries
1553
+ };
1554
+ });
1543
1555
  }
1544
- /** The manifest as one JSON document, ready for stdout — the U4 convention. */
1545
1556
  function emitLLMSManifest(command, version) {
1546
- return JSON.stringify(buildLLMSManifest(command, version));
1557
+ return Effect.map(buildLLMSManifest(command, version), (manifest) => JSON.stringify(manifest));
1547
1558
  }
1548
1559
  function createSplitter(separator) {
1549
1560
  return (value) => value.split(separator).filter(Boolean);
@@ -1716,39 +1727,26 @@ function makeStrykerCommand(requestRef) {
1716
1727
  if (Option.isSome(config["configFile"])) options["configFile"] = config["configFile"].value;
1717
1728
  return options;
1718
1729
  }
1719
- const strykerCommand = Command.make("stryker", rootConfig, (config) => {
1730
+ const strykerCommand = Command.make("stryker", rootConfig, (config) => Effect.gen(function* () {
1720
1731
  if (config.llms === true) {
1721
1732
  const document = {
1722
1733
  _tag: "manifest",
1723
1734
  schemaVersion: "1.0",
1724
1735
  code: 0,
1725
- manifest: emitLLMSManifest(strykerCommand, strykerVersion)
1736
+ manifest: yield* emitLLMSManifest(strykerCommand, strykerVersion)
1726
1737
  };
1727
- return Ref.set(requestRef, Option.some({
1738
+ return yield* Ref.set(requestRef, Option.some({
1728
1739
  _tag: "llms",
1729
1740
  document
1730
1741
  }));
1731
1742
  }
1732
- return Effect.failSync(() => CliError.ShowHelp.make({
1743
+ return yield* Effect.failSync(() => CliError.ShowHelp.make({
1733
1744
  commandPath: ["stryker"],
1734
1745
  errors: []
1735
1746
  }));
1736
- }).pipe(Command.withSubcommands([runCommand]));
1747
+ })).pipe(Command.withSubcommands([runCommand]));
1737
1748
  return strykerCommand;
1738
1749
  }
1739
- /**
1740
- * The CLI parses only text/number/choice options, so the framework's platform
1741
- * services are never read at runtime; the v4 runner still demands them in its
1742
- * environment. The bootstrap provides `Path.layer` (the universal
1743
- * implementation in `effect/Path`), an *empty* file system (`layerNoop`:
1744
- * every operation reports not-found), and a process-stdio `Terminal` whose
1745
- * interactive input primitives fail loudly — the run-only surface (R14) has
1746
- * no prompts. `@effect/platform-node` is a declared dependency of this
1747
- * package (it provides the `NodeRuntime` the bin runs through), but no
1748
- * platform-node service is wired into the command environment: the parser
1749
- * never reads a real file system at run time, so the noop layers are
1750
- * sufficient.
1751
- */
1752
1750
  const terminalLayer = Layer.succeed(Terminal.Terminal, Terminal.make({
1753
1751
  columns: Effect.sync(() => process.stdout.columns),
1754
1752
  rows: Effect.sync(() => process.stdout.rows),
@@ -1767,7 +1765,7 @@ const cliLayer = Layer.mergeAll(CliConfig.layer({ builtIns: [
1767
1765
  GlobalFlag.Wizard,
1768
1766
  GlobalFlag.Completions,
1769
1767
  GlobalFlag.LogLevel
1770
- ] }), Path.layer, FileSystem.layerNoop({}), terminalLayer, NodeStdio.layer, NodeChildProcessSpawner.layer.pipe(Layer.provideMerge(Layer.mergeAll(NodeFileSystem.layer, NodePath.layer))));
1768
+ ] }), Path.layer, NodeFileSystem$1.layer, terminalLayer, NodeStdio.layer, NodeChildProcessSpawner.layer.pipe(Layer.provideMerge(Layer.mergeAll(NodeFileSystem$1.layer, NodePath$1.layer))));
1771
1769
  function strykerCliEffect(argv, runMutationTest, detectMode, createRunEventStream, lastSignal) {
1772
1770
  return Effect.gen(function* () {
1773
1771
  const mode = yield* detectMode;
@@ -1790,13 +1788,13 @@ function strykerCliEffect(argv, runMutationTest, detectMode, createRunEventStrea
1790
1788
  return result.success;
1791
1789
  }).pipe(Effect.orElseSucceed(() => 2));
1792
1790
  }
1793
- const defaultRunMutationTest = (hostOptions, queue) => (options) => Effect.scoped(runMutationTest(options)).pipe(Effect.provideService(RunEvents, queue), Effect.provide(makeRunLayer(hostOptions)));
1791
+ const defaultRunMutationTest = (hostOptions, queue) => (options) => Effect.scoped(runMutationTest(options, makeRunLayer(hostOptions, queue))).pipe(Effect.provideService(RunEvents, queue));
1794
1792
  function hostOptionsOf(mode, stream) {
1795
1793
  return {
1796
1794
  runId: stream.runId,
1797
1795
  resolvedMode: mode,
1798
1796
  runStartedAt: stream.startedAt,
1799
- basePath: resolve(process.cwd()),
1797
+ basePath: process.cwd(),
1800
1798
  reporterPluginModules: [import.meta.resolve("@systemfsoftware/stryker-js-html-reporter"), import.meta.resolve("@systemfsoftware/stryker-js-platform-node/builtin-reporters")],
1801
1799
  allowConsoleColors: isColorEnabled(mode, process.env["NO_COLOR"])
1802
1800
  };
@@ -1806,7 +1804,7 @@ const runStrykerCli = (input, createRunEventStream) => Effect.gen(function* () {
1806
1804
  const hostOptions = hostOptionsOf(input.mode, stream);
1807
1805
  const runMutationTestImpl = input.runMutationTest ?? defaultRunMutationTest(hostOptions, stream.queue);
1808
1806
  const basePath = hostOptions.basePath;
1809
- const pathService = yield* Path.Path.pipe(Effect.provide(NodePath.layer));
1807
+ const pathService = yield* Path.Path.pipe(Effect.provide(NodePath$1.layer));
1810
1808
  let currentFiber = null;
1811
1809
  const onSignal = () => {
1812
1810
  process.removeListener("SIGINT", onSignal);
@@ -1890,7 +1888,7 @@ const program = Effect.gen(function* () {
1890
1888
  const outputMode = yield* OutputModeProbe;
1891
1889
  const runEvents = yield* RunEventStreamPort;
1892
1890
  return yield* strykerCliEffect(process.argv.slice(2), void 0, outputMode.detectMode, runEvents.createRunEventStream, lastSignal);
1893
- }).pipe(Effect.provideService(Logger.LogToStderr, true), Effect.provide(Layer.merge(OutputModeProbeLive, RunEventStreamFileLive).pipe(Layer.provide(Layer.mergeAll(NodeStdio.layer, NodeFileSystem.layer, NodePath.layer)))));
1891
+ }).pipe(Effect.provideService(Logger.LogToStderr, true), Effect.provide(Layer.merge(OutputModeProbeLive, RunEventStreamFileLive).pipe(Layer.provide(Layer.mergeAll(NodeStdio.layer, NodeFileSystem$1.layer, NodePath$1.layer)))));
1894
1892
  NodeRuntime.runMain(program, {
1895
1893
  disableErrorReporting: true,
1896
1894
  teardown: (exit, onExit) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@systemfsoftware/stryker-js-cli",
3
- "version": "4.0.2",
3
+ "version": "4.0.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/systemfsoftware/systemfsoftware.git",
@@ -19,9 +19,9 @@
19
19
  "@noble/hashes": "1.8.0",
20
20
  "effect": "^4.0.0-rc.112",
21
21
  "@systemfsoftware/effect-cell-types": "^5.0.2",
22
- "@systemfsoftware/stryker-js-html-reporter": "^0.1.1",
23
- "@systemfsoftware/stryker-js": "^0.1.1",
24
- "@systemfsoftware/stryker-js-platform-node": "^0.1.2"
22
+ "@systemfsoftware/stryker-js-html-reporter": "^0.1.2",
23
+ "@systemfsoftware/stryker-js-platform-node": "^0.2.0",
24
+ "@systemfsoftware/stryker-js": "^0.2.0"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@systemfsoftware/arethetypeswrong-cli": "^1.1.1",
@@ -33,17 +33,17 @@
33
33
  "tsdown": "^0.22.14",
34
34
  "vite-tsconfig-paths": "^6.1.1",
35
35
  "vitest": "^4",
36
- "@systemfsoftware/all": "^1.0.2",
37
36
  "@systemfsoftware/effect-gherkin-spec": "^4.0.0",
38
37
  "@systemfsoftware/effect-schema-law": "^2.0.1",
39
38
  "@systemfsoftware/effect-schema-vite": "^2.0.2",
40
- "@systemfsoftware/stryker-js-typescript-checker": "^3.0.2",
41
- "@systemfsoftware/stryker-js-vitest-runner": "^2.0.2",
42
- "@systemfsoftware/stryker-test-contribution": "^1.1.1",
43
- "@systemfsoftware/stryker-plugins": "^2.0.0",
39
+ "@systemfsoftware/all": "^1.1.0",
44
40
  "@systemfsoftware/oxlint-config": "^0.1.0",
41
+ "@systemfsoftware/stryker-js-typescript-checker": "^3.0.3",
42
+ "@systemfsoftware/stryker-js-vitest-runner": "^2.1.0",
43
+ "@systemfsoftware/stryker-plugins": "^2.0.1",
45
44
  "@systemfsoftware/tsconfig": "^1.3.3",
46
- "@systemfsoftware/vitest-config": "^0.1.0"
45
+ "@systemfsoftware/vitest-config": "^0.1.0",
46
+ "@systemfsoftware/stryker-test-contribution": "^1.1.2"
47
47
  },
48
48
  "engines": {
49
49
  "node": ">=20.0.0"