@systemfsoftware/stryker-js-plugin-interface 7.1.0 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @systemfsoftware/stryker-js-plugin-interface
2
2
 
3
+ ## 7.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - A finite mutant is killed or survived from its tests. Timeout is reserved for one named nonterminating trap, detected by a hit bound rather than a wall-clock budget. A wall-clock timeout fails the run instead of being stored as a detected mutant.
8
+
9
+ ## 7.1.1
10
+
11
+ ### Patch Changes
12
+
13
+ - Effect moves to `4.0.0-rc.116` (with `@effect/platform-node`, `@effect/platform-node-shared`, `@effect/vitest` and `@effect/opentelemetry` on the same release), the `@systemfsoftware/*` toolchain pins move to their current releases, and `vitest` 5 with `oxc-parser` 0.150 come along. Both worker bundles (`stryker-js-typescript-checker`, `stryker-js-vitest-runner`) now inline their whole runtime rather than resolving `effect`, `@effect/*` and the sibling packages from the host's tree, so a worker runs on its own copy of the effect that built it; the project's `typescript` and `vitest` remain the only imports beside Node builtins. The filter-level `arbitrary.candidate` generators that the thresholds schemas carried are gone: v4 no longer reads them, so thresholds still reject a `low` above `high` and the property tests generate the pair from the schema again. Log calls inside `Effect.catch*` handlers moved to `Effect.tapError`/`Effect.tapCause` at the same level and message. `@systemfsoftware/stryker-ignorer-interface` re-exports the 0.150 AST, where `FormalParameterRest.decorators` is now `Array<Decorator>`.
14
+
3
15
  ## 7.1.0
4
16
 
5
17
  ### Minor Changes
package/dist/index.d.mts CHANGED
@@ -419,10 +419,18 @@ export declare const FrameworkInformationSchema: S.Struct<{
419
419
  readonly dependencies: S.optional<S.$Record<S.String, S.String>>;
420
420
  }>;
421
421
 
422
+ export declare const HIT_LIMIT_REASON_PREFIX = "Hit limit reached";
423
+
424
+ export declare const hitLimitReachedReason: (count: number, limit: number) => string;
425
+
422
426
  export declare const InvalidStatus: S.Union<readonly [S.Literal<"CompileError">, S.Literal<"RuntimeError">]>;
423
427
 
424
428
  export declare const isCustomTestRunner: (value: TestRunnerConfig) => value is TestRunnerCustomConfig;
425
429
 
430
+ export declare const isHitLimitReason: (reason: string | undefined) => boolean;
431
+
432
+ export declare const isNamedTrap: (activeMutantId: string, namedTrapId: string | undefined) => boolean;
433
+
426
434
  export declare interface KilledMutantRunResult {
427
435
  readonly status: 'killed';
428
436
  readonly killedBy: readonly string[];
@@ -579,11 +587,19 @@ declare const MutantTested_base: S.Class<MutantTested, S.TaggedStruct<"mutantTes
579
587
 
580
588
  export declare type MutationScoreThresholds = typeof MutationScoreThresholdsSchema.Type;
581
589
 
582
- export declare const MutationScoreThresholdsSchema: S.Struct<{
590
+ export declare const MutationScoreThresholdsSchema: S.decodeTo<S.declare<{
591
+ readonly high: number;
592
+ readonly low: number;
593
+ readonly break: number | null;
594
+ }, {
595
+ readonly high: number;
596
+ readonly low: number;
597
+ readonly break: number | null;
598
+ }>, S.Struct<{
583
599
  readonly high: S.withDecodingDefaultKey<S.Finite, never>;
584
600
  readonly low: S.withDecodingDefaultKey<S.Finite, never>;
585
601
  readonly break: S.withDecodingDefaultKey<S.NullOr<S.Finite>, never>;
586
- }>;
602
+ }>, never, never>;
587
603
 
588
604
  export declare class MutationTestingPlanReady extends MutationTestingPlanReady_base {}
589
605
 
@@ -629,10 +645,16 @@ declare const MutationTestReportReady_base: S.Class<MutationTestReportReady, S.T
629
645
  readonly duration: S.optional<S.Finite>;
630
646
  }>>;
631
647
  }>>;
632
- readonly thresholds: S.Struct<{
648
+ readonly thresholds: S.decodeTo<S.declare<{
649
+ readonly high: number;
650
+ readonly low: number;
651
+ }, {
652
+ readonly high: number;
653
+ readonly low: number;
654
+ }>, S.Struct<{
633
655
  readonly high: S.Finite;
634
656
  readonly low: S.Finite;
635
- }>;
657
+ }>, never, never>;
636
658
  readonly config: S.optional<S.$Record<S.String, S.Unknown>>;
637
659
  readonly testFiles: S.optional<S.$Record<S.String, S.Struct<{
638
660
  readonly source: S.optional<S.String>;
@@ -696,10 +718,16 @@ export declare const MutationTestResultSchema: S.Struct<{
696
718
  readonly duration: S.optional<S.Finite>;
697
719
  }>>;
698
720
  }>>;
699
- readonly thresholds: S.Struct<{
721
+ readonly thresholds: S.decodeTo<S.declare<{
722
+ readonly high: number;
723
+ readonly low: number;
724
+ }, {
725
+ readonly high: number;
726
+ readonly low: number;
727
+ }>, S.Struct<{
700
728
  readonly high: S.Finite;
701
729
  readonly low: S.Finite;
702
- }>;
730
+ }>, never, never>;
703
731
  readonly config: S.optional<S.$Record<S.String, S.Unknown>>;
704
732
  readonly testFiles: S.optional<S.$Record<S.String, S.Struct<{
705
733
  readonly source: S.optional<S.String>;
@@ -949,11 +977,19 @@ export declare const StrykerOptionsSchema: S.StructWithRest<S.Struct<{
949
977
  readonly options: S.optional<S.$Record<S.String, S.Unknown>>;
950
978
  }>]>, never>;
951
979
  readonly testRunnerNodeArgs: S.withDecodingDefaultKey<S.$Array<S.String>, never>;
952
- readonly thresholds: S.withDecodingDefaultKey<S.Struct<{
980
+ readonly thresholds: S.withDecodingDefaultKey<S.decodeTo<S.declare<{
981
+ readonly high: number;
982
+ readonly low: number;
983
+ readonly break: number | null;
984
+ }, {
985
+ readonly high: number;
986
+ readonly low: number;
987
+ readonly break: number | null;
988
+ }>, S.Struct<{
953
989
  readonly high: S.withDecodingDefaultKey<S.Finite, never>;
954
990
  readonly low: S.withDecodingDefaultKey<S.Finite, never>;
955
991
  readonly break: S.withDecodingDefaultKey<S.NullOr<S.Finite>, never>;
956
- }>, never>;
992
+ }>, never, never>, never>;
957
993
  readonly timeoutFactor: S.withDecodingDefaultKey<S.Finite, never>;
958
994
  readonly timeoutMS: S.withDecodingDefaultKey<S.Finite, never>;
959
995
  readonly dryRunTimeoutMinutes: S.withDecodingDefaultKey<S.Finite, never>;
@@ -1167,10 +1203,16 @@ export declare type TestStatus = typeof TestStatus.Type;
1167
1203
 
1168
1204
  export declare type Thresholds = typeof ThresholdsSchema.Type;
1169
1205
 
1170
- export declare const ThresholdsSchema: S.Struct<{
1206
+ export declare const ThresholdsSchema: S.decodeTo<S.declare<{
1207
+ readonly high: number;
1208
+ readonly low: number;
1209
+ }, {
1210
+ readonly high: number;
1211
+ readonly low: number;
1212
+ }>, S.Struct<{
1171
1213
  readonly high: S.Finite;
1172
1214
  readonly low: S.Finite;
1173
- }>;
1215
+ }>, never, never>;
1174
1216
 
1175
1217
  export declare interface TimeoutDryRunResult {
1176
1218
  readonly status: 'timeout';
@@ -1212,6 +1254,10 @@ export declare const UndetectedStatus: S.Union<readonly [S.Literal<"Survived">,
1212
1254
 
1213
1255
  export declare const UntestedStatus: S.Union<readonly [S.Literal<"Ignored">, S.Literal<"Pending">]>;
1214
1256
 
1257
+ export declare const WALL_CLOCK_TIMEOUT_REASON = "wall-clock-timeout";
1258
+
1259
+ export declare const wallClockTimeoutStopsRun: (status: string, reason: string | undefined) => boolean;
1260
+
1215
1261
  export declare const WorkerEntryUrl: S.String;
1216
1262
 
1217
1263
  export declare type WorkerEntryUrl = typeof WorkerEntryUrl.Type;
package/dist/index.mjs CHANGED
@@ -3,8 +3,8 @@ import * as Context from "effect/Context";
3
3
  import * as S from "effect/Schema";
4
4
  import * as Rpc from "effect/unstable/rpc/Rpc";
5
5
  import * as RpcGroup from "effect/unstable/rpc/RpcGroup";
6
+ import { Effect, SchemaGetter, SchemaTransformation } from "effect";
6
7
  import * as RpcMiddleware from "effect/unstable/rpc/RpcMiddleware";
7
- import { Effect } from "effect";
8
8
  import * as Match from "effect/Match";
9
9
  import * as Option from "effect/Option";
10
10
  //#region src/Checker.schema.ts
@@ -155,6 +155,14 @@ const MetricsResultSchema = S.Struct({
155
155
  childResults: S.Array(S.suspend(() => MetricsResultSchema))
156
156
  }).annotate({ identifier: "MetricsResult" });
157
157
  //#endregion
158
+ //#region src/mutant-timeout-reason.ts
159
+ const HIT_LIMIT_REASON_PREFIX = "Hit limit reached";
160
+ const WALL_CLOCK_TIMEOUT_REASON = "wall-clock-timeout";
161
+ const hitLimitReachedReason = (count, limit) => `${HIT_LIMIT_REASON_PREFIX} (${count}/${limit})`;
162
+ const isHitLimitReason = (reason) => reason !== void 0 && reason.startsWith("Hit limit reached");
163
+ const isNamedTrap = (activeMutantId, namedTrapId) => namedTrapId !== void 0 && activeMutantId === namedTrapId;
164
+ const wallClockTimeoutStopsRun = (status, reason) => status === "timeout" && !isHitLimitReason(reason);
165
+ //#endregion
158
166
  //#region src/Report.schema.ts
159
167
  const MutantResultSchema = S.Struct({
160
168
  id: S.String,
@@ -186,24 +194,30 @@ const TestFileSchema = S.Struct({
186
194
  tests: S.Array(TestDefinitionSchema)
187
195
  });
188
196
  const TestFileDefinitionDictionarySchema = S.Record(S.String, TestFileSchema);
189
- const ThresholdsSchema = S.Struct({
197
+ const ThresholdsValuesSchema = S.Struct({
190
198
  high: Percentage,
191
199
  low: Percentage
192
- }).pipe(S.check(S.makeFilter((t) => t.low <= t.high, {
193
- expected: "thresholds where low <= high",
194
- arbitrary: { candidate: { make: (fc) => fc.tuple(fc.float({
195
- min: 0,
196
- max: 100,
197
- noNaN: true
198
- }), fc.float({
199
- min: 0,
200
- max: 100,
201
- noNaN: true
202
- })).map(([a, b]) => ({
203
- high: Math.max(a, b),
204
- low: Math.min(a, b)
205
- })) } }
206
- })));
200
+ });
201
+ const isThresholds = (value) => S.is(ThresholdsValuesSchema)(value) && value.low <= value.high;
202
+ /**
203
+ * The pair is *built* ordered — a drawn pair is sorted — rather than drawn at
204
+ * random and discarded until it happens to be ordered. The invariant lives on
205
+ * the declaration because a filter over the pair cannot express `low <= high`
206
+ * in the generation-constraint vocabulary, and only a declaration carries a
207
+ * `toCodecArbitrary` derivation. `ThresholdsValuesSchema` stays the wire side, so
208
+ * decoding keeps its field paths.
209
+ */
210
+ const OrderedThresholds = S.declare(isThresholds, {
211
+ message: "expected thresholds where low <= high",
212
+ toCodecArbitrary: () => S.link()(ThresholdsValuesSchema, {
213
+ decode: SchemaGetter.transform(({ high, low }) => ({
214
+ high: Math.max(high, low),
215
+ low: Math.min(high, low)
216
+ })),
217
+ encode: SchemaGetter.transform((thresholds) => thresholds)
218
+ })
219
+ });
220
+ const ThresholdsSchema = ThresholdsValuesSchema.pipe(S.decodeTo(OrderedThresholds, SchemaTransformation.passthrough()));
207
221
  const BrandingInformationSchema = S.Struct({
208
222
  homepageUrl: S.String,
209
223
  imageUrl: S.optional(S.String)
@@ -548,30 +562,32 @@ const ClearTextReporterOptions = openStruct({
548
562
  });
549
563
  const HtmlReporterOptions = S.Struct({ fileName: defaulted(S.String, "reports/mutation/mutation.html") });
550
564
  const JsonReporterOptions = S.Struct({ fileName: defaulted(S.String, "reports/mutation/mutation.json") });
551
- const MutationScoreThresholdsSchema = S.Struct({
565
+ const MutationScoreThresholdsValuesSchema = S.Struct({
552
566
  high: defaulted(Percentage, 80),
553
567
  low: defaulted(Percentage, 60),
554
568
  break: defaulted(S.NullOr(Percentage), null)
555
- }).pipe(S.check(S.makeFilter((t) => t.low <= t.high, {
556
- expected: "thresholds where low <= high",
557
- arbitrary: { candidate: { make: (fc) => fc.tuple(fc.float({
558
- min: 0,
559
- max: 100,
560
- noNaN: true
561
- }), fc.float({
562
- min: 0,
563
- max: 100,
564
- noNaN: true
565
- }), fc.option(fc.float({
566
- min: 0,
567
- max: 100,
568
- noNaN: true
569
- }), { nil: null })).map(([a, b, brk]) => ({
570
- high: Math.max(a, b),
571
- low: Math.min(a, b),
572
- break: brk
573
- })) } }
574
- })));
569
+ });
570
+ const isMutationScoreThresholds = (value) => S.is(MutationScoreThresholdsValuesSchema)(value) && value.low <= value.high;
571
+ /**
572
+ * The pair is *built* ordered — a drawn pair is sorted — rather than drawn at
573
+ * random and discarded until it happens to be ordered. The invariant lives on
574
+ * the declaration because a filter over the pair cannot express `low <= high`
575
+ * in the generation-constraint vocabulary, and only a declaration carries a
576
+ * `toCodecArbitrary` derivation. The struct stays the wire side, so decoding
577
+ * keeps member defaults and field paths.
578
+ */
579
+ const OrderedMutationScoreThresholds = S.declare(isMutationScoreThresholds, {
580
+ message: "expected thresholds where low <= high",
581
+ toCodecArbitrary: () => S.link()(MutationScoreThresholdsValuesSchema, {
582
+ decode: SchemaGetter.transform(({ break: breaking, high, low }) => ({
583
+ break: breaking,
584
+ high: Math.max(high, low),
585
+ low: Math.min(high, low)
586
+ })),
587
+ encode: SchemaGetter.transform((thresholds) => thresholds)
588
+ })
589
+ });
590
+ const MutationScoreThresholdsSchema = MutationScoreThresholdsValuesSchema.pipe(S.decodeTo(OrderedMutationScoreThresholds, SchemaTransformation.passthrough()));
575
591
  const MutatorDescriptor = S.Struct({ excludedMutations: defaulted(S.Array(S.String), []) });
576
592
  const WarningOptions = openStruct({
577
593
  unknownOptions: defaulted(S.Boolean, true),
@@ -796,4 +812,4 @@ const parseTraceparent = (value) => {
796
812
  };
797
813
  const TraceContextReference = Context.Reference("@systemfsoftware/stryker-js-plugin-interface/TraceContextReference", { defaultValue: () => Option.none() });
798
814
  //#endregion
799
- export { BoundaryErrorSchema, BoundaryPayloadRejected, BoundaryUnrecognizedSignal, BrandingInformationSchema, CheckResultSchema, CheckStatus, Checker, CheckerCheckResult, CheckerCustomConfigSchema, CheckerEntryConfigSchema, CheckerFailed, CheckerGroupResult, CheckerMutantWire, CheckerRequest, CheckerRpcs, CommandRunnerOptionsSchema, CoverageAnalysisMode, CoverageAnalysisSchema, DependenciesSchema, DetectedStatus, DryRunCompleted, DryRunOptionsSchema, DryRunResultSchema, DryRunStatus, EXIT_CODE, Evaluator, EvaluatorFailed, ExitClass, FileResultDictionarySchema, FileResultSchema, FrameworkInformationSchema, InvalidStatus, LocationSchema, LogLevel, Metrics, MetricsResultSchema, MetricsSchema, MutantActivationSchema, MutantCoverageSchema, MutantResultSchema, MutantRunOptionsSchema, MutantRunResultSchema, MutantRunStatus, MutantStatusSchema, MutantTested, MutationScoreThresholdsSchema, MutationTestReportReady, MutationTestResultSchema, MutationTestingPlanReady, NonNegativeFinite, NonNegativeInt, OpenEndLocationSchema, PackageManager, Percentage, PluginFileUrl, PositionSchema, PropagatedTrace, RENDERED_OPTION_DEFAULTS, ReportType, ReporterAck, ReporterDrained, ReporterEventBatch, ReporterEventKind, ReporterEventSchema, ReporterEventUnion, ReporterFailed, ReporterInitOptions, ReporterPlanDescriptorSchema, ReporterPlanKind, ReporterRpcs, RunTimingSchema, StrykerOptionsSchema, TRACEPARENT_HEADER, TRACESTATE_HEADER, TestDefinitionSchema, TestFileDefinitionDictionarySchema, TestFileSchema, TestResultSchema, TestRunner, TestRunnerCapabilitiesSchema, TestRunnerConfigSchema, TestRunnerCustomConfigSchema, TestRunnerDryRunRequest, TestRunnerFailed, TestRunnerMutantRunRequest, TestRunnerRpcs, TestStatus, ThresholdsSchema, TraceContextMiddleware, TraceContextReference, UndetectedStatus, UntestedStatus, WorkerEntryUrl, WorkerPluginKind, WorkerPluginSpawnSchema, formatTraceparent, isCustomTestRunner, parseTraceparent, propertyPath, strykerCoreSchema, strykerReportBugUrl, testFilesProvided, toMutantRunResult };
815
+ export { BoundaryErrorSchema, BoundaryPayloadRejected, BoundaryUnrecognizedSignal, BrandingInformationSchema, CheckResultSchema, CheckStatus, Checker, CheckerCheckResult, CheckerCustomConfigSchema, CheckerEntryConfigSchema, CheckerFailed, CheckerGroupResult, CheckerMutantWire, CheckerRequest, CheckerRpcs, CommandRunnerOptionsSchema, CoverageAnalysisMode, CoverageAnalysisSchema, DependenciesSchema, DetectedStatus, DryRunCompleted, DryRunOptionsSchema, DryRunResultSchema, DryRunStatus, EXIT_CODE, Evaluator, EvaluatorFailed, ExitClass, FileResultDictionarySchema, FileResultSchema, FrameworkInformationSchema, HIT_LIMIT_REASON_PREFIX, InvalidStatus, LocationSchema, LogLevel, Metrics, MetricsResultSchema, MetricsSchema, MutantActivationSchema, MutantCoverageSchema, MutantResultSchema, MutantRunOptionsSchema, MutantRunResultSchema, MutantRunStatus, MutantStatusSchema, MutantTested, MutationScoreThresholdsSchema, MutationTestReportReady, MutationTestResultSchema, MutationTestingPlanReady, NonNegativeFinite, NonNegativeInt, OpenEndLocationSchema, PackageManager, Percentage, PluginFileUrl, PositionSchema, PropagatedTrace, RENDERED_OPTION_DEFAULTS, ReportType, ReporterAck, ReporterDrained, ReporterEventBatch, ReporterEventKind, ReporterEventSchema, ReporterEventUnion, ReporterFailed, ReporterInitOptions, ReporterPlanDescriptorSchema, ReporterPlanKind, ReporterRpcs, RunTimingSchema, StrykerOptionsSchema, TRACEPARENT_HEADER, TRACESTATE_HEADER, TestDefinitionSchema, TestFileDefinitionDictionarySchema, TestFileSchema, TestResultSchema, TestRunner, TestRunnerCapabilitiesSchema, TestRunnerConfigSchema, TestRunnerCustomConfigSchema, TestRunnerDryRunRequest, TestRunnerFailed, TestRunnerMutantRunRequest, TestRunnerRpcs, TestStatus, ThresholdsSchema, TraceContextMiddleware, TraceContextReference, UndetectedStatus, UntestedStatus, WALL_CLOCK_TIMEOUT_REASON, WorkerEntryUrl, WorkerPluginKind, WorkerPluginSpawnSchema, formatTraceparent, hitLimitReachedReason, isCustomTestRunner, isHitLimitReason, isNamedTrap, parseTraceparent, propertyPath, strykerCoreSchema, strykerReportBugUrl, testFilesProvided, toMutantRunResult, wallClockTimeoutStopsRun };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@systemfsoftware/stryker-js-plugin-interface",
3
- "version": "7.1.0",
3
+ "version": "7.2.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/systemfsoftware/stryker-js-effect.git",
@@ -18,24 +18,24 @@
18
18
  "node": ">=20.0.0"
19
19
  },
20
20
  "dependencies": {
21
- "effect": "4.0.0-rc.112",
22
- "@systemfsoftware/stryker-js-instrumenter": "^8.0.0"
21
+ "effect": "4.0.0-rc.116",
22
+ "@systemfsoftware/stryker-js-instrumenter": "^8.0.1"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@effect/tsgo": "^0.45.0",
26
26
  "@microsoft/api-extractor": "^7",
27
- "@systemfsoftware/all": "^2",
28
- "@systemfsoftware/arethetypeswrong-cli": "^4",
29
- "@systemfsoftware/effect-schema-law": "^2",
30
- "@systemfsoftware/effect-schema-vite": "^2",
31
- "@systemfsoftware/tsconfig": "^1",
27
+ "@systemfsoftware/arethetypeswrong-cli": "^4.2.0",
28
+ "@systemfsoftware/effect-schema-law": "^2.2.1",
29
+ "@systemfsoftware/effect-schema-vite": "^2.2.1",
30
+ "@systemfsoftware/oxlint-config-recommended": "^1.0.0",
31
+ "@systemfsoftware/tsconfig": "^1.3.6",
32
32
  "@types/node": "^24",
33
33
  "oxlint": "^1",
34
34
  "oxlint-tsgolint": "^7",
35
35
  "rimraf": "^6.1.3",
36
36
  "tsdown": "^0.23.0",
37
37
  "typescript": "^7",
38
- "vitest": "^4",
38
+ "vitest": "^5",
39
39
  "@systemfsoftware/tsdown-config": "^0.1.0",
40
40
  "@systemfsoftware/vitest-config": "^0.1.0"
41
41
  },