@systemfsoftware/stryker-js-mutation-run 1.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/LICENSE +212 -0
  2. package/README.md +38 -0
  3. package/dist/checker-C4tGiXtZ.mjs +588 -0
  4. package/dist/checker-resource-DTYEKXdg.d.mts +108 -0
  5. package/dist/checker-worker.d.mts +16 -0
  6. package/dist/checker-worker.mjs +2 -0
  7. package/dist/child-process-proxy-worker-lx1M5Mz3.mjs +567 -0
  8. package/dist/child-process-proxy-worker-main.d.mts +1 -0
  9. package/dist/child-process-proxy-worker-main.mjs +6 -0
  10. package/dist/child-process-test-runner-worker-BTWRYb8V.mjs +50 -0
  11. package/dist/child-process-test-runner-worker.d.mts +16 -0
  12. package/dist/child-process-test-runner-worker.mjs +2 -0
  13. package/dist/config/base.d.mts +21 -0
  14. package/dist/config/base.mjs +47 -0
  15. package/dist/config/config-resolution.d.mts +80 -0
  16. package/dist/config/config-resolution.mjs +2 -0
  17. package/dist/config/fork-schema.d.mts +5 -0
  18. package/dist/config/fork-schema.mjs +2 -0
  19. package/dist/errors-BkjxkY_S.d.mts +6 -0
  20. package/dist/errors.d.mts +2 -0
  21. package/dist/errors.mjs +10 -0
  22. package/dist/exit-classification.d.mts +28 -0
  23. package/dist/exit-classification.mjs +39 -0
  24. package/dist/fork-schema-BHuTbRBR.mjs +62 -0
  25. package/dist/incremental-differ-DDVwtXBn.d.mts +72 -0
  26. package/dist/incremental-differ-DY8AA09Q.mjs +579 -0
  27. package/dist/index-CyOSz6LC.d.mts +104 -0
  28. package/dist/index.d.mts +87 -0
  29. package/dist/index.mjs +1885 -0
  30. package/dist/mutants/incremental-differ.d.mts +2 -0
  31. package/dist/mutants/incremental-differ.mjs +2 -0
  32. package/dist/output-mode-CfGHDpi5.d.mts +17 -0
  33. package/dist/output-mode.d.mts +2 -0
  34. package/dist/output-mode.mjs +1 -0
  35. package/dist/plugins-Nx86IJQW.mjs +1618 -0
  36. package/dist/plugins.d.mts +2 -0
  37. package/dist/plugins.mjs +2 -0
  38. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  39. package/dist/run-event-CzRz9Gtk.d.mts +121 -0
  40. package/dist/run-event.d.mts +2 -0
  41. package/dist/run-event.mjs +1 -0
  42. package/dist/stryker-package-CTcsIZ4S.mjs +23 -0
  43. package/dist/stryker-package.d.mts +7 -0
  44. package/dist/stryker-package.mjs +2 -0
  45. package/dist/timer-BMrE1SQ3.d.mts +20 -0
  46. package/dist/timer.d.mts +2 -0
  47. package/dist/timer.mjs +48 -0
  48. package/dist/verdict-envelope-BWc61mHm.mjs +229 -0
  49. package/dist/verdict-envelope-CKLZPjxC.d.mts +94 -0
  50. package/dist/verdict-envelope.d.mts +2 -0
  51. package/dist/verdict-envelope.mjs +2 -0
  52. package/package.json +102 -0
  53. package/schema/stryker-schema.json +903 -0
@@ -0,0 +1,47 @@
1
+ import "@systemfsoftware/stryker-js-plugin-api/core";
2
+ //#region src/config/base-preset.ts
3
+ /**
4
+ * Modal Stryker options, inherited via
5
+ * `"extends": "@systemfsoftware/stryker-js-mutation-run/config/base"`.
6
+ *
7
+ * Relative paths below resolve against the working directory of the run that
8
+ * reads them — the consuming package — not against this file.
9
+ */
10
+ const basePreset = {
11
+ packageManager: "pnpm",
12
+ testRunner: "vitest",
13
+ checkers: ["typescript"],
14
+ plugins: [
15
+ "@systemfsoftware/stryker-js-vitest-runner",
16
+ "@systemfsoftware/stryker-js-typescript-checker",
17
+ "@systemfsoftware/stryker-plugins/effect-schema-ignorer",
18
+ "@systemfsoftware/stryker-plugins/workflow-make-ignorer"
19
+ ],
20
+ reporters: [
21
+ "progress",
22
+ "html",
23
+ "json",
24
+ "progress-stream"
25
+ ],
26
+ htmlReporter: { fileName: "reports/mutation-report.html" },
27
+ jsonReporter: { fileName: "reports/mutation-report.json" },
28
+ vitest: {
29
+ configFile: "vitest.config.ts",
30
+ dir: ".",
31
+ related: true
32
+ },
33
+ typescriptChecker: { prioritizePerformanceOverAccuracy: true },
34
+ coverageAnalysis: "perTest",
35
+ incremental: true,
36
+ incrementalFile: "reports/stryker-incremental.json",
37
+ ignorePatterns: ["reports", "coverage"],
38
+ disableBail: true,
39
+ ignorers: ["effect-schema-declarations"],
40
+ thresholds: {
41
+ high: 100,
42
+ low: 80,
43
+ break: 100
44
+ }
45
+ };
46
+ //#endregion
47
+ export { basePreset as default };
@@ -0,0 +1,80 @@
1
+ import "../errors-BkjxkY_S.mjs";
2
+ import { PartialStrykerOptions, StrykerOptions } from "@systemfsoftware/stryker-js-plugin-api/core";
3
+ import { I, Immutable } from "@stryker-mutator/util";
4
+ import { Logger } from "@systemfsoftware/stryker-js-plugin-api/logging";
5
+ //#region src/config/options-validator.d.ts
6
+ /**
7
+ * The validation document. Its `properties` map names every option the core and
8
+ * the loaded plugins declare, which is what an unknown-option warning is keyed
9
+ * on. It is read as DATA only: validation itself runs on `StrykerOptionsSchema`,
10
+ * the same declaration the defaults come from.
11
+ */
12
+ type ValidationSchemaDocument = {
13
+ readonly properties?: unknown;
14
+ readonly [key: string]: unknown;
15
+ };
16
+ declare class OptionsValidator {
17
+ private readonly schema;
18
+ private readonly log;
19
+ static readonly inject: ["validationSchema", "logger"];
20
+ constructor(schema: ValidationSchemaDocument, log: Logger);
21
+ /**
22
+ * Validates the provided options, throwing an error if something is wrong.
23
+ * Optionally also warns about excess or unserializable options.
24
+ * @param options The stryker options to validate
25
+ * @param mark Wether or not to log warnings on unknown properties or unserializable properties
26
+ */
27
+ validate(options: Record<string, unknown>, mark?: boolean): asserts options is StrykerOptions;
28
+ /**
29
+ * Hard-fails on config names the rebuild removed (U2-U9): a removed
30
+ * top-level key (`dashboard`, `eventReporter`) or a removed reporter name
31
+ * inside `reporters` (`dots`, `event-recorder`, `progress-append-only`,
32
+ * `dashboard`). Runs ahead of `schemaValidate` because a removed key is
33
+ * absent from the AJV schema, so schema validation can never see it, and
34
+ * the warning path (`markExcessOptions`) only fires when `mark` is set and
35
+ * the `unknownOptions` warning is enabled — a removed key could otherwise
36
+ * be silently accepted. Only the known-removed names are checked; an
37
+ * unknown-but-not-removed key keeps its warning-only behaviour.
38
+ */
39
+ private validateRemovedSurface;
40
+ private removeDeprecatedOptions;
41
+ private static recordOf;
42
+ private removeStringMutator;
43
+ private removeMutatorName;
44
+ private removeTestFramework;
45
+ private removeTranspilers;
46
+ private rewriteFiles;
47
+ private removeJestEnableBail;
48
+ private removeHtmlReporterBaseDir;
49
+ private migrateMaxConcurrentTestRunners;
50
+ private customValidation;
51
+ /**
52
+ * Decodes the options against their declaration, then writes the result back
53
+ * onto the caller's object: the previous engine filled defaults in place and
54
+ * every caller reads them off the object it passed, so the fill has to land
55
+ * there rather than in a copy.
56
+ */
57
+ private schemaValidate;
58
+ private throwErrorIfNeeded;
59
+ private markOptions;
60
+ private markExcessOptions;
61
+ private markUnserializableOptions;
62
+ }
63
+ declare const defaultOptions: Immutable<StrykerOptions>;
64
+ //#endregion
65
+ //#region src/config/config-reader.d.ts
66
+ declare class ConfigReader {
67
+ private readonly log;
68
+ private readonly validator;
69
+ static inject: ["logger", "optionsValidator"];
70
+ constructor(log: Logger, validator: I<OptionsValidator>);
71
+ readConfig(cliOptions: PartialStrykerOptions): Promise<StrykerOptions>;
72
+ private loadOptionsFromConfigFile;
73
+ private findConfigFile;
74
+ private readJsonConfig;
75
+ private importJSConfig;
76
+ private importJSConfigModule;
77
+ private hasDefaultExport;
78
+ }
79
+ //#endregion
80
+ export { ConfigReader, OptionsValidator, defaultOptions };
@@ -0,0 +1,2 @@
1
+ import { d as ConfigReader, n as OptionsValidator, r as defaultOptions } from "../plugins-Nx86IJQW.mjs";
2
+ export { ConfigReader, OptionsValidator, defaultOptions };
@@ -0,0 +1,5 @@
1
+ //#region src/config/fork-schema.d.ts
2
+ /** The fork's option document: `StrykerOptionsSchema` minus the removed surface, plus the fork options. */
3
+ declare const forkCoreSchema: Record<string, unknown>;
4
+ //#endregion
5
+ export { forkCoreSchema };
@@ -0,0 +1,2 @@
1
+ import { t as forkCoreSchema } from "../fork-schema-BHuTbRBR.mjs";
2
+ export { forkCoreSchema };
@@ -0,0 +1,6 @@
1
+ import { StrykerError } from "@stryker-mutator/util";
2
+ //#region src/errors.d.ts
3
+ declare class ConfigError extends StrykerError {}
4
+ declare function retrieveCause(error: unknown): unknown;
5
+ //#endregion
6
+ export { retrieveCause as n, ConfigError as t };
@@ -0,0 +1,2 @@
1
+ import { n as retrieveCause, t as ConfigError } from "./errors-BkjxkY_S.mjs";
2
+ export { ConfigError, retrieveCause };
@@ -0,0 +1,10 @@
1
+ import { InjectionError } from "typed-inject";
2
+ import { StrykerError } from "@stryker-mutator/util";
3
+ //#region src/errors.ts
4
+ var ConfigError = class extends StrykerError {};
5
+ function retrieveCause(error) {
6
+ if (error instanceof InjectionError) return error.cause;
7
+ else return error;
8
+ }
9
+ //#endregion
10
+ export { ConfigError, retrieveCause };
@@ -0,0 +1,28 @@
1
+ //#region src/exit-classification.d.ts
2
+ /**
3
+ * The classed process exit codes (R6). The final code is decided once, at
4
+ * teardown, by the precedence `signal > 4 > 3 > 2 > 1 > 0`; verdict gates
5
+ * record a pending class instead of writing `process.exitCode` directly.
6
+ */
7
+ declare enum ExitClass {
8
+ VerdictFail = 1,
9
+ ConfigError = 2,
10
+ RuntimeError = 3,
11
+ InternalError = 4
12
+ }
13
+ declare function setPendingExitClass(exitClass: ExitClass): void;
14
+ declare function getPendingExitClasses(): ReadonlySet<ExitClass>;
15
+ /**
16
+ * Resolves the final process exit code (R6): a terminating signal wins over
17
+ * every pending class and maps to the POSIX `128 + n` convention; otherwise
18
+ * the highest pending class wins; no signal and no pending class is 0.
19
+ *
20
+ * Pure function — unit-tested over the whole precedence matrix.
21
+ *
22
+ * @param pending the classes recorded by the verdict gates
23
+ * @param signal the OS signal number that terminated the run, if any
24
+ * (SIGINT = 2, SIGTERM = 15, …)
25
+ */
26
+ declare function resolveExitCode(pending: ReadonlySet<ExitClass>, signal: number | null): number;
27
+ //#endregion
28
+ export { ExitClass, getPendingExitClasses, resolveExitCode, setPendingExitClass };
@@ -0,0 +1,39 @@
1
+ //#region src/exit-classification.ts
2
+ /**
3
+ * The classed process exit codes (R6). The final code is decided once, at
4
+ * teardown, by the precedence `signal > 4 > 3 > 2 > 1 > 0`; verdict gates
5
+ * record a pending class instead of writing `process.exitCode` directly.
6
+ */
7
+ let ExitClass = /* @__PURE__ */ function(ExitClass) {
8
+ ExitClass[ExitClass["VerdictFail"] = 1] = "VerdictFail";
9
+ ExitClass[ExitClass["ConfigError"] = 2] = "ConfigError";
10
+ ExitClass[ExitClass["RuntimeError"] = 3] = "RuntimeError";
11
+ ExitClass[ExitClass["InternalError"] = 4] = "InternalError";
12
+ return ExitClass;
13
+ }({});
14
+ const pendingExitClasses = /* @__PURE__ */ new Set();
15
+ function setPendingExitClass(exitClass) {
16
+ pendingExitClasses.add(exitClass);
17
+ }
18
+ function getPendingExitClasses() {
19
+ return pendingExitClasses;
20
+ }
21
+ /**
22
+ * Resolves the final process exit code (R6): a terminating signal wins over
23
+ * every pending class and maps to the POSIX `128 + n` convention; otherwise
24
+ * the highest pending class wins; no signal and no pending class is 0.
25
+ *
26
+ * Pure function — unit-tested over the whole precedence matrix.
27
+ *
28
+ * @param pending the classes recorded by the verdict gates
29
+ * @param signal the OS signal number that terminated the run, if any
30
+ * (SIGINT = 2, SIGTERM = 15, …)
31
+ */
32
+ function resolveExitCode(pending, signal) {
33
+ if (signal !== null) return 128 + signal;
34
+ let code = 0;
35
+ for (const exitClass of pending) if (exitClass > code) code = exitClass;
36
+ return code;
37
+ }
38
+ //#endregion
39
+ export { ExitClass, getPendingExitClasses, resolveExitCode, setPendingExitClass };
@@ -0,0 +1,62 @@
1
+ import { StrykerOptionsSchema } from "@systemfsoftware/stryker-js-plugin-api/core";
2
+ import { Effect } from "effect";
3
+ import * as S from "effect/Schema";
4
+ //#region src/config/removed-surface.ts
5
+ /**
6
+ * Config-file names the rebuild removed, mapped to their remediation.
7
+ *
8
+ * Separate module because its two consumers cannot import each other:
9
+ * `options-validator.ts` rejects these names, and `fork-schema.ts` deletes
10
+ * them from the schema so their defaults are never injected. The validator
11
+ * already imports the fork schema, so this cannot live there.
12
+ *
13
+ * Deliberately absent: CI-provider, initializer and dropped-command options
14
+ * (no config-file surface, environment variables and commands only); flags
15
+ * dropped from the CLI that were never config keys (`--files`,
16
+ * `--allowConsoleColors`, `--dashboard.*`), which fail as unknown arguments;
17
+ * and deprecated-but-migrated keys (`files`, `transpilers`, `testFramework`),
18
+ * which `removeDeprecatedOptions` rewrites and which stay soft on purpose.
19
+ */
20
+ const REMOVED_OPTIONS = {
21
+ "dots": "the \"dots\" reporter was removed; use \"clear-text\" instead",
22
+ "event-recorder": "the \"event-recorder\" reporter was removed; use the \"json\" reporter or the machine-mode progress stream for structured output",
23
+ "progress-append-only": "the \"progress-append-only\" reporter was removed; use \"progress-stream\" instead",
24
+ "dashboard": "the \"dashboard\" reporter and its options were removed; write the \"json\" or \"html\" report and publish it yourself",
25
+ "eventReporter": "the event-recorder reporter was removed; remove this option"
26
+ };
27
+ //#endregion
28
+ //#region src/config/fork-schema.schema.ts
29
+ const requireTestContribution = S.NullOr(S.Array(S.String)).pipe(S.annotate({
30
+ default: [
31
+ ".workflow.property.test.ts",
32
+ ".policy.property.test.ts",
33
+ ".kernel.property.test.ts"
34
+ ],
35
+ description: "Fail the run when a test file whose name ends with one of these suffixes kills no mutant that another test file does not also kill. Such a file could be deleted without leaving a single mutant alive, so a passing mutation score is no evidence it earns its place. Set to null to disable the check. The gate only applies to file classes the mutation operators can express — workflow, policy, and kernel property tests today; schema refusal tests are gated by refutation adequacy rather than by mutation."
36
+ }), S.withDecodingDefaultKey(Effect.succeed([
37
+ ".workflow.property.test.ts",
38
+ ".policy.property.test.ts",
39
+ ".kernel.property.test.ts"
40
+ ])));
41
+ const survivorsPriorReport = S.optionalKey(S.String.pipe(S.annotate({ description: "The path of the prior mutation report a --survivors run admits against and re-tests the survivors of. Defaults to \"reports/mutation-report.json\" when unset. Deliberately has no default: a default would be injected into every resolved options object and written into every report, poisoning the KTD7 marker that identifies a report produced by a survivors run." })));
42
+ const extendsPropertySchema = S.optionalKey(S.String.pipe(S.annotate({ description: "Path to another stryker config file whose options merge underneath this one. Resolved relative to this file. A child scalar or array replaces the inherited value; a child object merges one level deep; a child key set to null deletes the inherited key. Inheritance chains are not rewritten, so an inherited relative path value still resolves against the working directory of the run that reads it." })));
43
+ /**
44
+ * The option document schema, composed from the single `StrykerOptionsSchema`
45
+ * the plugin-api declares. The upstream schema still declares the removed
46
+ * options, several with defaults: AJV injects a default for every declared
47
+ * property, so leaving them here would put `dashboard` and `eventReporter`
48
+ * into the resolved options of runs whose config never mentioned them.
49
+ * Dropping the fields removes the defaults with them.
50
+ */
51
+ const forkOptionsSchema = S.StructWithRest(S.Struct({
52
+ ...Object.fromEntries(Object.entries(StrykerOptionsSchema.schema.fields).filter(([name]) => !Object.hasOwn(REMOVED_OPTIONS, name))),
53
+ requireTestContribution,
54
+ survivorsPriorReport,
55
+ extends: extendsPropertySchema
56
+ }), [S.Record(S.String, S.Unknown)]);
57
+ //#endregion
58
+ //#region src/config/fork-schema.ts
59
+ /** The fork's option document: `StrykerOptionsSchema` minus the removed surface, plus the fork options. */
60
+ const forkCoreSchema = S.toJsonSchemaDocument(forkOptionsSchema).schema;
61
+ //#endregion
62
+ export { REMOVED_OPTIONS as n, forkCoreSchema as t };
@@ -0,0 +1,72 @@
1
+ import { CoverageData, FileDescriptions, Mutant, StrykerOptions, schema } from "@systemfsoftware/stryker-js-plugin-api/core";
2
+ import { I } from "@stryker-mutator/util";
3
+ import { Logger } from "@systemfsoftware/stryker-js-plugin-api/logging";
4
+ import { CompleteDryRunResult, TestResult } from "@systemfsoftware/stryker-js-plugin-api/test-runner";
5
+ //#region src/mutants/diff-statistics-collector.d.ts
6
+ declare class DiffChanges {
7
+ added: number;
8
+ removed: number;
9
+ toString(): string;
10
+ }
11
+ type DiffChange = 'added' | 'removed';
12
+ declare class DiffStatisticsCollector {
13
+ readonly changesByFile: Map<string, DiffChanges>;
14
+ readonly total: DiffChanges;
15
+ count(file: string, change: DiffChange, amount?: number): void;
16
+ createDetailedReport(): string[];
17
+ createTotalsReport(): string;
18
+ }
19
+ //#endregion
20
+ //#region src/mutants/test-coverage.d.ts
21
+ declare class TestCoverage {
22
+ #private;
23
+ constructor(testsByMutantId: Map<string, Set<TestResult>>, testsById: Map<string, TestResult>, staticCoverage: CoverageData | undefined, hitsByMutantId: Map<string, number>);
24
+ get testsByMutantId(): ReadonlyMap<string, Set<TestResult>>;
25
+ get testsById(): ReadonlyMap<string, TestResult>;
26
+ get hitsByMutantId(): ReadonlyMap<string, number>;
27
+ get hasCoverage(): boolean;
28
+ hasStaticCoverage(mutantId: string): boolean;
29
+ addTest(testResult: TestResult): void;
30
+ addCoverage(mutantId: string, testIds: string[]): void;
31
+ forMutant(mutantId: string): ReadonlySet<TestResult> | undefined;
32
+ static from: typeof testCoverageFrom;
33
+ }
34
+ declare function testCoverageFrom({ tests, mutantCoverage }: CompleteDryRunResult, logger: Logger): TestCoverage;
35
+ //#endregion
36
+ //#region src/mutants/incremental-differ.d.ts
37
+ /**
38
+ * This class is responsible for calculating the diff between a run and a previous run based on the incremental report.
39
+ *
40
+ * Since the ids of tests and mutants can differ across reports (they are only unique within 1 report), this class
41
+ * identifies mutants and tests by attributes that make them unique:
42
+ * - Mutant: file name, mutator name, location and replacement
43
+ * - Test: test name, test file name (if present) and location (if present).
44
+ *
45
+ * We're storing these identifiers in local variables (maps and sets) as strings.
46
+ * We should move to 'records' for these when they come available: https://github.com/tc39/proposal-record-tuple
47
+ *
48
+ * A mutant result from the previous run is reused if the following conditions were met:
49
+ * - The location of the mutant refers to a piece of code that didn't change
50
+ * - If mutant was killed:
51
+ * - The culprit test wasn't changed
52
+ * - If the mutant survived:
53
+ * - No test was added, and the mutant is not static. Static mutants are
54
+ * attributed to no test, so no test change can ever invalidate one; reusing
55
+ * a non-killed verdict for one would freeze it permanently.
56
+ *
57
+ * It uses google's "diff-match-patch" project to calculate the new locations for tests and mutants, see https://github.com/google/diff-match-patch.
58
+ */
59
+ declare class IncrementalDiffer {
60
+ private readonly logger;
61
+ private readonly options;
62
+ mutantStatisticsCollector: DiffStatisticsCollector | undefined;
63
+ testStatisticsCollector: DiffStatisticsCollector | undefined;
64
+ private readonly mutateDescriptionByRelativeFileName;
65
+ static inject: readonly ["logger", "options", "fileDescriptions"];
66
+ constructor(logger: Logger, options: StrykerOptions, fileDescriptions: FileDescriptions);
67
+ private isInMutatedScope;
68
+ diff(currentMutants: readonly Mutant[], testCoverage: I<TestCoverage>, incrementalReport: schema.MutationTestResult, currentRelativeFiles: Map<string, string>): readonly Mutant[];
69
+ }
70
+ declare function toRelativeNormalizedFileName(fileName: string | undefined): string;
71
+ //#endregion
72
+ export { toRelativeNormalizedFileName as n, IncrementalDiffer as t };