@systemfsoftware/stryker-js-plugin-interface 7.0.0 → 7.1.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @systemfsoftware/stryker-js-plugin-interface
2
2
 
3
+ ## 7.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 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>`.
8
+
9
+ ## 7.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - A checker that fails now fails mutation testing with that checker's cause, instead of crashing with an empty error. The TypeScript checker type-checks each mutant, so compile errors appear in the report. Verdict counts are non-negative integers; `Metrics` is a class you can build from mutant statuses; a threshold `low` may not exceed `high`.
14
+
3
15
  ## 7.0.0
4
16
 
5
17
  ### Major Changes
package/dist/index.d.mts CHANGED
@@ -192,6 +192,8 @@ export declare type Dependencies = typeof DependenciesSchema.Type;
192
192
 
193
193
  export declare const DependenciesSchema: S.$Record<S.String, S.String>;
194
194
 
195
+ export declare const DetectedStatus: S.Union<readonly [S.Literal<"Killed">, S.Literal<"Timeout">]>;
196
+
195
197
  export declare class DryRunCompleted extends DryRunCompleted_base {}
196
198
 
197
199
  declare const DryRunCompleted_base: S.Class<DryRunCompleted, S.TaggedStruct<"dryRunCompleted", {
@@ -202,7 +204,7 @@ declare const DryRunCompleted_base: S.Class<DryRunCompleted, S.TaggedStruct<"dry
202
204
  readonly capabilities: S.Struct<{
203
205
  readonly reloadEnvironment: S.Boolean;
204
206
  }>;
205
- readonly testCount: S.Finite;
207
+ readonly testCount: S.Int;
206
208
  readonly tests: S.$Array<S.Union<readonly [S.Struct<{
207
209
  readonly id: S.String;
208
210
  readonly name: S.String;
@@ -370,7 +372,7 @@ export declare const FileResultDictionarySchema: S.$Record<S.String, S.Struct<{
370
372
  readonly static: S.optional<S.Boolean>;
371
373
  readonly coveredBy: S.optional<S.$Array<S.String>>;
372
374
  readonly killedBy: S.optional<S.$Array<S.String>>;
373
- readonly testsCompleted: S.optional<S.Finite>;
375
+ readonly testsCompleted: S.optional<S.Int>;
374
376
  readonly duration: S.optional<S.Finite>;
375
377
  }>>;
376
378
  }>>;
@@ -398,7 +400,7 @@ export declare const FileResultSchema: S.Struct<{
398
400
  readonly static: S.optional<S.Boolean>;
399
401
  readonly coveredBy: S.optional<S.$Array<S.String>>;
400
402
  readonly killedBy: S.optional<S.$Array<S.String>>;
401
- readonly testsCompleted: S.optional<S.Finite>;
403
+ readonly testsCompleted: S.optional<S.Int>;
402
404
  readonly duration: S.optional<S.Finite>;
403
405
  }>>;
404
406
  }>;
@@ -417,6 +419,8 @@ export declare const FrameworkInformationSchema: S.Struct<{
417
419
  readonly dependencies: S.optional<S.$Record<S.String, S.String>>;
418
420
  }>;
419
421
 
422
+ export declare const InvalidStatus: S.Union<readonly [S.Literal<"CompileError">, S.Literal<"RuntimeError">]>;
423
+
420
424
  export declare const isCustomTestRunner: (value: TestRunnerConfig) => value is TestRunnerCustomConfig;
421
425
 
422
426
  export declare interface KilledMutantRunResult {
@@ -443,7 +447,30 @@ declare type LogLevel = typeof LogLevel.Type;
443
447
  export { LogLevel }
444
448
  export { LogLevel as LogLevelType }
445
449
 
446
- export declare type Metrics = typeof MetricsSchema.Type;
450
+ export declare class Metrics extends Metrics_base {
451
+ get totalDetected(): number;
452
+ get totalUndetected(): number;
453
+ get totalCovered(): number;
454
+ get totalValid(): number;
455
+ get totalInvalid(): number;
456
+ get totalMutants(): number;
457
+ get mutationScore(): number;
458
+ get mutationScoreBasedOnCoveredCode(): number;
459
+ static fromMutants(mutants: readonly {
460
+ readonly status: string;
461
+ }[]): Metrics;
462
+ }
463
+
464
+ declare const Metrics_base: S.Class<Metrics, S.Struct<{
465
+ readonly pending: S.Int;
466
+ readonly killed: S.Int;
467
+ readonly timeout: S.Int;
468
+ readonly survived: S.Int;
469
+ readonly noCoverage: S.Int;
470
+ readonly runtimeErrors: S.Int;
471
+ readonly compileErrors: S.Int;
472
+ readonly ignored: S.Int;
473
+ }>, {}>;
447
474
 
448
475
  export declare interface MetricsResult {
449
476
  readonly name: string;
@@ -451,47 +478,15 @@ export declare interface MetricsResult {
451
478
  readonly childResults: readonly MetricsResult[];
452
479
  }
453
480
 
454
- export declare const MetricsResultSchema: S.Struct<{
455
- readonly name: S.String;
456
- readonly metrics: S.Struct<{
457
- readonly pending: S.Finite;
458
- readonly killed: S.Finite;
459
- readonly timeout: S.Finite;
460
- readonly survived: S.Finite;
461
- readonly noCoverage: S.Finite;
462
- readonly runtimeErrors: S.Finite;
463
- readonly compileErrors: S.Finite;
464
- readonly ignored: S.Finite;
465
- readonly totalDetected: S.Finite;
466
- readonly totalUndetected: S.Finite;
467
- readonly totalInvalid: S.Finite;
468
- readonly totalValid: S.Finite;
469
- readonly totalMutants: S.Finite;
470
- readonly totalCovered: S.Finite;
471
- readonly mutationScore: S.Finite;
472
- readonly mutationScoreBasedOnCoveredCode: S.Finite;
473
- }>;
474
- readonly childResults: S.$Array<S.suspend<S.Codec<MetricsResult, MetricsResult, never, never>>>;
475
- }>;
481
+ export declare interface MetricsResultEncoded {
482
+ readonly name: string;
483
+ readonly metrics: typeof Metrics.Encoded;
484
+ readonly childResults: readonly MetricsResultEncoded[];
485
+ }
476
486
 
477
- export declare const MetricsSchema: S.Struct<{
478
- readonly pending: S.Finite;
479
- readonly killed: S.Finite;
480
- readonly timeout: S.Finite;
481
- readonly survived: S.Finite;
482
- readonly noCoverage: S.Finite;
483
- readonly runtimeErrors: S.Finite;
484
- readonly compileErrors: S.Finite;
485
- readonly ignored: S.Finite;
486
- readonly totalDetected: S.Finite;
487
- readonly totalUndetected: S.Finite;
488
- readonly totalInvalid: S.Finite;
489
- readonly totalValid: S.Finite;
490
- readonly totalMutants: S.Finite;
491
- readonly totalCovered: S.Finite;
492
- readonly mutationScore: S.Finite;
493
- readonly mutationScoreBasedOnCoveredCode: S.Finite;
494
- }>;
487
+ export declare const MetricsResultSchema: S.Codec<MetricsResult, MetricsResultEncoded>;
488
+
489
+ export declare const MetricsSchema: typeof Metrics;
495
490
 
496
491
  export { MutantActivation }
497
492
 
@@ -526,7 +521,7 @@ export declare const MutantResultSchema: S.Struct<{
526
521
  readonly static: S.optional<S.Boolean>;
527
522
  readonly coveredBy: S.optional<S.$Array<S.String>>;
528
523
  readonly killedBy: S.optional<S.$Array<S.String>>;
529
- readonly testsCompleted: S.optional<S.Finite>;
524
+ readonly testsCompleted: S.optional<S.Int>;
530
525
  readonly duration: S.optional<S.Finite>;
531
526
  }>;
532
527
 
@@ -578,22 +573,30 @@ declare const MutantTested_base: S.Class<MutantTested, S.TaggedStruct<"mutantTes
578
573
  }>;
579
574
  readonly mutator: S.String;
580
575
  readonly replacement: S.NullOr<S.String>;
581
- readonly completed: S.Finite;
582
- readonly total: S.Finite;
576
+ readonly completed: S.Int;
577
+ readonly total: S.Int;
583
578
  }>, {}>;
584
579
 
585
580
  export declare type MutationScoreThresholds = typeof MutationScoreThresholdsSchema.Type;
586
581
 
587
- export declare const MutationScoreThresholdsSchema: S.Struct<{
582
+ export declare const MutationScoreThresholdsSchema: S.decodeTo<S.declare<{
583
+ readonly high: number;
584
+ readonly low: number;
585
+ readonly break: number | null;
586
+ }, {
587
+ readonly high: number;
588
+ readonly low: number;
589
+ readonly break: number | null;
590
+ }>, S.Struct<{
588
591
  readonly high: S.withDecodingDefaultKey<S.Finite, never>;
589
592
  readonly low: S.withDecodingDefaultKey<S.Finite, never>;
590
593
  readonly break: S.withDecodingDefaultKey<S.NullOr<S.Finite>, never>;
591
- }>;
594
+ }>, never, never>;
592
595
 
593
596
  export declare class MutationTestingPlanReady extends MutationTestingPlanReady_base {}
594
597
 
595
598
  declare const MutationTestingPlanReady_base: S.Class<MutationTestingPlanReady, S.TaggedStruct<"mutationTestingPlanReady", {
596
- readonly total: S.Finite;
599
+ readonly total: S.Int;
597
600
  readonly plans: S.$Array<S.Struct<{
598
601
  readonly mutantId: S.String;
599
602
  readonly plan: S.Literals<readonly ["EarlyResult", "Run"]>;
@@ -630,14 +633,20 @@ declare const MutationTestReportReady_base: S.Class<MutationTestReportReady, S.T
630
633
  readonly static: S.optional<S.Boolean>;
631
634
  readonly coveredBy: S.optional<S.$Array<S.String>>;
632
635
  readonly killedBy: S.optional<S.$Array<S.String>>;
633
- readonly testsCompleted: S.optional<S.Finite>;
636
+ readonly testsCompleted: S.optional<S.Int>;
634
637
  readonly duration: S.optional<S.Finite>;
635
638
  }>>;
636
639
  }>>;
637
- readonly thresholds: S.Struct<{
640
+ readonly thresholds: S.decodeTo<S.declare<{
641
+ readonly high: number;
642
+ readonly low: number;
643
+ }, {
644
+ readonly high: number;
645
+ readonly low: number;
646
+ }>, S.Struct<{
638
647
  readonly high: S.Finite;
639
648
  readonly low: S.Finite;
640
- }>;
649
+ }>, never, never>;
641
650
  readonly config: S.optional<S.$Record<S.String, S.Unknown>>;
642
651
  readonly testFiles: S.optional<S.$Record<S.String, S.Struct<{
643
652
  readonly source: S.optional<S.String>;
@@ -667,28 +676,7 @@ declare const MutationTestReportReady_base: S.Class<MutationTestReportReady, S.T
667
676
  readonly dependencies: S.optional<S.$Record<S.String, S.String>>;
668
677
  }>>;
669
678
  }>;
670
- readonly metrics: S.Struct<{
671
- readonly name: S.String;
672
- readonly metrics: S.Struct<{
673
- readonly pending: S.Finite;
674
- readonly killed: S.Finite;
675
- readonly timeout: S.Finite;
676
- readonly survived: S.Finite;
677
- readonly noCoverage: S.Finite;
678
- readonly runtimeErrors: S.Finite;
679
- readonly compileErrors: S.Finite;
680
- readonly ignored: S.Finite;
681
- readonly totalDetected: S.Finite;
682
- readonly totalUndetected: S.Finite;
683
- readonly totalInvalid: S.Finite;
684
- readonly totalValid: S.Finite;
685
- readonly totalMutants: S.Finite;
686
- readonly totalCovered: S.Finite;
687
- readonly mutationScore: S.Finite;
688
- readonly mutationScoreBasedOnCoveredCode: S.Finite;
689
- }>;
690
- readonly childResults: S.$Array<S.suspend<S.Codec<MetricsResult, MetricsResult, never, never>>>;
691
- }>;
679
+ readonly metrics: S.Codec<MetricsResult, MetricsResultEncoded, never, never>;
692
680
  }>, {}>;
693
681
 
694
682
  export declare type MutationTestResult = typeof MutationTestResultSchema.Type;
@@ -718,14 +706,20 @@ export declare const MutationTestResultSchema: S.Struct<{
718
706
  readonly static: S.optional<S.Boolean>;
719
707
  readonly coveredBy: S.optional<S.$Array<S.String>>;
720
708
  readonly killedBy: S.optional<S.$Array<S.String>>;
721
- readonly testsCompleted: S.optional<S.Finite>;
709
+ readonly testsCompleted: S.optional<S.Int>;
722
710
  readonly duration: S.optional<S.Finite>;
723
711
  }>>;
724
712
  }>>;
725
- readonly thresholds: S.Struct<{
713
+ readonly thresholds: S.decodeTo<S.declare<{
714
+ readonly high: number;
715
+ readonly low: number;
716
+ }, {
717
+ readonly high: number;
718
+ readonly low: number;
719
+ }>, S.Struct<{
726
720
  readonly high: S.Finite;
727
721
  readonly low: S.Finite;
728
- }>;
722
+ }>, never, never>;
729
723
  readonly config: S.optional<S.$Record<S.String, S.Unknown>>;
730
724
  readonly testFiles: S.optional<S.$Record<S.String, S.Struct<{
731
725
  readonly source: S.optional<S.String>;
@@ -756,6 +750,10 @@ export declare const MutationTestResultSchema: S.Struct<{
756
750
  }>>;
757
751
  }>;
758
752
 
753
+ export declare const NonNegativeFinite: S.Finite;
754
+
755
+ export declare const NonNegativeInt: S.Int;
756
+
759
757
  export declare type OnlyObject<T> = Exclude<T, Primitive>;
760
758
 
761
759
  export { OpenEndLocation }
@@ -780,6 +778,8 @@ export declare interface PassedCheckResult {
780
778
  readonly status: 'passed';
781
779
  }
782
780
 
781
+ export declare const Percentage: S.Finite;
782
+
783
783
  export declare const PluginFileUrl: S.String;
784
784
 
785
785
  export { Position }
@@ -969,11 +969,19 @@ export declare const StrykerOptionsSchema: S.StructWithRest<S.Struct<{
969
969
  readonly options: S.optional<S.$Record<S.String, S.Unknown>>;
970
970
  }>]>, never>;
971
971
  readonly testRunnerNodeArgs: S.withDecodingDefaultKey<S.$Array<S.String>, never>;
972
- readonly thresholds: S.withDecodingDefaultKey<S.Struct<{
972
+ readonly thresholds: S.withDecodingDefaultKey<S.decodeTo<S.declare<{
973
+ readonly high: number;
974
+ readonly low: number;
975
+ readonly break: number | null;
976
+ }, {
977
+ readonly high: number;
978
+ readonly low: number;
979
+ readonly break: number | null;
980
+ }>, S.Struct<{
973
981
  readonly high: S.withDecodingDefaultKey<S.Finite, never>;
974
982
  readonly low: S.withDecodingDefaultKey<S.Finite, never>;
975
983
  readonly break: S.withDecodingDefaultKey<S.NullOr<S.Finite>, never>;
976
- }>, never>;
984
+ }>, never, never>, never>;
977
985
  readonly timeoutFactor: S.withDecodingDefaultKey<S.Finite, never>;
978
986
  readonly timeoutMS: S.withDecodingDefaultKey<S.Finite, never>;
979
987
  readonly dryRunTimeoutMinutes: S.withDecodingDefaultKey<S.Finite, never>;
@@ -1187,10 +1195,16 @@ export declare type TestStatus = typeof TestStatus.Type;
1187
1195
 
1188
1196
  export declare type Thresholds = typeof ThresholdsSchema.Type;
1189
1197
 
1190
- export declare const ThresholdsSchema: S.Struct<{
1198
+ export declare const ThresholdsSchema: S.decodeTo<S.declare<{
1199
+ readonly high: number;
1200
+ readonly low: number;
1201
+ }, {
1202
+ readonly high: number;
1203
+ readonly low: number;
1204
+ }>, S.Struct<{
1191
1205
  readonly high: S.Finite;
1192
1206
  readonly low: S.Finite;
1193
- }>;
1207
+ }>, never, never>;
1194
1208
 
1195
1209
  export declare interface TimeoutDryRunResult {
1196
1210
  readonly status: 'timeout';
@@ -1228,6 +1242,10 @@ export declare const TRACEPARENT_HEADER = "traceparent";
1228
1242
 
1229
1243
  export declare const TRACESTATE_HEADER = "tracestate";
1230
1244
 
1245
+ export declare const UndetectedStatus: S.Union<readonly [S.Literal<"Survived">, S.Literal<"NoCoverage">]>;
1246
+
1247
+ export declare const UntestedStatus: S.Union<readonly [S.Literal<"Ignored">, S.Literal<"Pending">]>;
1248
+
1231
1249
  export declare const WorkerEntryUrl: S.String;
1232
1250
 
1233
1251
  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
@@ -71,27 +71,87 @@ const EXIT_CODE = {
71
71
  };
72
72
  //#endregion
73
73
  //#region src/Metrics.schema.ts
74
- const MetricsSchema = S.Struct({
75
- pending: S.Finite,
76
- killed: S.Finite,
77
- timeout: S.Finite,
78
- survived: S.Finite,
79
- noCoverage: S.Finite,
80
- runtimeErrors: S.Finite,
81
- compileErrors: S.Finite,
82
- ignored: S.Finite,
83
- totalDetected: S.Finite,
84
- totalUndetected: S.Finite,
85
- totalInvalid: S.Finite,
86
- totalValid: S.Finite,
87
- totalMutants: S.Finite,
88
- totalCovered: S.Finite,
89
- mutationScore: S.Finite,
90
- mutationScoreBasedOnCoveredCode: S.Finite
74
+ const DetectedStatus = S.Union([S.Literal("Killed"), S.Literal("Timeout")]);
75
+ const UndetectedStatus = S.Union([S.Literal("Survived"), S.Literal("NoCoverage")]);
76
+ const InvalidStatus = S.Union([S.Literal("CompileError"), S.Literal("RuntimeError")]);
77
+ const UntestedStatus = S.Union([S.Literal("Ignored"), S.Literal("Pending")]);
78
+ const NonNegativeInt = S.Int.pipe(S.check(S.isGreaterThanOrEqualTo(0)));
79
+ const NonNegativeFinite = S.Finite.pipe(S.check(S.isGreaterThanOrEqualTo(0)));
80
+ const Percentage = S.Finite.pipe(S.check(S.isBetween({
81
+ minimum: 0,
82
+ maximum: 100
83
+ })));
84
+ var Metrics = class Metrics extends S.Class("Metrics")({
85
+ pending: NonNegativeInt,
86
+ killed: NonNegativeInt,
87
+ timeout: NonNegativeInt,
88
+ survived: NonNegativeInt,
89
+ noCoverage: NonNegativeInt,
90
+ runtimeErrors: NonNegativeInt,
91
+ compileErrors: NonNegativeInt,
92
+ ignored: NonNegativeInt
93
+ }) {
94
+ get totalDetected() {
95
+ return this.timeout + this.killed;
96
+ }
97
+ get totalUndetected() {
98
+ return this.survived + this.noCoverage;
99
+ }
100
+ get totalCovered() {
101
+ return this.totalDetected + this.survived;
102
+ }
103
+ get totalValid() {
104
+ return this.totalUndetected + this.totalDetected;
105
+ }
106
+ get totalInvalid() {
107
+ return this.runtimeErrors + this.compileErrors;
108
+ }
109
+ get totalMutants() {
110
+ return this.totalValid + this.totalInvalid + this.ignored + this.pending;
111
+ }
112
+ get mutationScore() {
113
+ if (this.totalValid === 0) return NaN;
114
+ return Math.min(100, Math.max(0, this.totalDetected / this.totalValid * 100));
115
+ }
116
+ get mutationScoreBasedOnCoveredCode() {
117
+ if (this.totalCovered === 0) return NaN;
118
+ return Math.min(100, Math.max(0, this.totalDetected / this.totalCovered * 100));
119
+ }
120
+ static fromMutants(mutants) {
121
+ const counts = emptyMetricCounts();
122
+ for (const mutant of mutants) incrementMetricStatus(counts, mutant.status);
123
+ return Metrics.make(counts);
124
+ }
125
+ };
126
+ const emptyMetricCounts = () => ({
127
+ pending: 0,
128
+ killed: 0,
129
+ timeout: 0,
130
+ survived: 0,
131
+ noCoverage: 0,
132
+ runtimeErrors: 0,
133
+ compileErrors: 0,
134
+ ignored: 0
91
135
  });
136
+ const METRIC_STATUS_KEYS = {
137
+ Pending: "pending",
138
+ Killed: "killed",
139
+ Timeout: "timeout",
140
+ Survived: "survived",
141
+ NoCoverage: "noCoverage",
142
+ RuntimeError: "runtimeErrors",
143
+ CompileError: "compileErrors",
144
+ Ignored: "ignored"
145
+ };
146
+ const incrementMetricStatus = (counts, status) => {
147
+ const key = METRIC_STATUS_KEYS[status];
148
+ if (key === void 0) return;
149
+ counts[key] += 1;
150
+ };
151
+ const MetricsSchema = Metrics;
92
152
  const MetricsResultSchema = S.Struct({
93
153
  name: S.String,
94
- metrics: MetricsSchema,
154
+ metrics: Metrics,
95
155
  childResults: S.Array(S.suspend(() => MetricsResultSchema))
96
156
  }).annotate({ identifier: "MetricsResult" });
97
157
  //#endregion
@@ -107,8 +167,8 @@ const MutantResultSchema = S.Struct({
107
167
  static: S.optional(S.Boolean),
108
168
  coveredBy: S.optional(S.Array(S.String)),
109
169
  killedBy: S.optional(S.Array(S.String)),
110
- testsCompleted: S.optional(S.Finite),
111
- duration: S.optional(S.Finite)
170
+ testsCompleted: S.optional(NonNegativeInt),
171
+ duration: S.optional(NonNegativeFinite)
112
172
  });
113
173
  const FileResultSchema = S.Struct({
114
174
  language: S.String,
@@ -126,10 +186,30 @@ const TestFileSchema = S.Struct({
126
186
  tests: S.Array(TestDefinitionSchema)
127
187
  });
128
188
  const TestFileDefinitionDictionarySchema = S.Record(S.String, TestFileSchema);
129
- const ThresholdsSchema = S.Struct({
130
- high: S.Finite,
131
- low: S.Finite
189
+ const ThresholdsValuesSchema = S.Struct({
190
+ high: Percentage,
191
+ low: Percentage
132
192
  });
193
+ const isThresholds = (value) => S.is(ThresholdsValuesSchema)(value) && value.low <= value.high;
194
+ /**
195
+ * The pair is *built* ordered — a drawn pair is sorted — rather than drawn at
196
+ * random and discarded until it happens to be ordered. The invariant lives on
197
+ * the declaration because a filter over the pair cannot express `low <= high`
198
+ * in the generation-constraint vocabulary, and only a declaration carries a
199
+ * `toCodecArbitrary` derivation. `ThresholdsValuesSchema` stays the wire side, so
200
+ * decoding keeps its field paths.
201
+ */
202
+ const OrderedThresholds = S.declare(isThresholds, {
203
+ message: "expected thresholds where low <= high",
204
+ toCodecArbitrary: () => S.link()(ThresholdsValuesSchema, {
205
+ decode: SchemaGetter.transform(({ high, low }) => ({
206
+ high: Math.max(high, low),
207
+ low: Math.min(high, low)
208
+ })),
209
+ encode: SchemaGetter.transform((thresholds) => thresholds)
210
+ })
211
+ });
212
+ const ThresholdsSchema = ThresholdsValuesSchema.pipe(S.decodeTo(OrderedThresholds, SchemaTransformation.passthrough()));
133
213
  const BrandingInformationSchema = S.Struct({
134
214
  homepageUrl: S.String,
135
215
  imageUrl: S.optional(S.String)
@@ -261,24 +341,24 @@ const ReporterEventKind = S.Literals([
261
341
  "mutationTestReportReady"
262
342
  ]);
263
343
  const RunTimingSchema = S.Struct({
264
- net: S.Finite,
265
- overhead: S.Finite
344
+ net: NonNegativeFinite,
345
+ overhead: NonNegativeFinite
266
346
  });
267
347
  const ReporterPlanKind = S.Literals(["EarlyResult", "Run"]);
268
348
  const ReporterPlanDescriptorSchema = S.Struct({
269
349
  mutantId: S.String,
270
350
  plan: ReporterPlanKind,
271
- netTime: S.Finite,
351
+ netTime: NonNegativeFinite,
272
352
  reloadEnvironment: S.Boolean
273
353
  });
274
354
  var DryRunCompleted = class extends S.TaggedClass()("dryRunCompleted", {
275
355
  timing: RunTimingSchema,
276
356
  capabilities: TestRunnerCapabilitiesSchema,
277
- testCount: S.Finite,
357
+ testCount: NonNegativeInt,
278
358
  tests: S.Array(TestResultSchema)
279
359
  }) {};
280
360
  var MutationTestingPlanReady = class extends S.TaggedClass()("mutationTestingPlanReady", {
281
- total: S.Finite,
361
+ total: NonNegativeInt,
282
362
  plans: S.Array(ReporterPlanDescriptorSchema)
283
363
  }) {};
284
364
  var MutantTested = class extends S.TaggedClass()("mutantTested", {
@@ -288,8 +368,8 @@ var MutantTested = class extends S.TaggedClass()("mutantTested", {
288
368
  location: LocationSchema$1,
289
369
  mutator: S.String,
290
370
  replacement: S.NullOr(S.String),
291
- completed: S.Finite,
292
- total: S.Finite
371
+ completed: NonNegativeInt,
372
+ total: NonNegativeInt
293
373
  }) {};
294
374
  var MutationTestReportReady = class extends S.TaggedClass()("mutationTestReportReady", {
295
375
  report: MutationTestResultSchema,
@@ -461,11 +541,6 @@ const PackageManager = S.Literals([
461
541
  "yarn",
462
542
  "pnpm"
463
543
  ]);
464
- /** 0–100 percentage used by the mutation-score thresholds. */
465
- const Percentage = S.Finite.pipe(S.check(S.isBetween({
466
- minimum: 0,
467
- maximum: 100
468
- })));
469
544
  const CommandRunnerOptionsSchema = openStruct({ command: defaulted(S.String, "npm test") });
470
545
  const ClearTextReporterOptions = openStruct({
471
546
  allowColor: defaulted(S.Boolean, true),
@@ -479,11 +554,32 @@ const ClearTextReporterOptions = openStruct({
479
554
  });
480
555
  const HtmlReporterOptions = S.Struct({ fileName: defaulted(S.String, "reports/mutation/mutation.html") });
481
556
  const JsonReporterOptions = S.Struct({ fileName: defaulted(S.String, "reports/mutation/mutation.json") });
482
- const MutationScoreThresholdsSchema = S.Struct({
557
+ const MutationScoreThresholdsValuesSchema = S.Struct({
483
558
  high: defaulted(Percentage, 80),
484
559
  low: defaulted(Percentage, 60),
485
560
  break: defaulted(S.NullOr(Percentage), null)
486
561
  });
562
+ const isMutationScoreThresholds = (value) => S.is(MutationScoreThresholdsValuesSchema)(value) && value.low <= value.high;
563
+ /**
564
+ * The pair is *built* ordered — a drawn pair is sorted — rather than drawn at
565
+ * random and discarded until it happens to be ordered. The invariant lives on
566
+ * the declaration because a filter over the pair cannot express `low <= high`
567
+ * in the generation-constraint vocabulary, and only a declaration carries a
568
+ * `toCodecArbitrary` derivation. The struct stays the wire side, so decoding
569
+ * keeps member defaults and field paths.
570
+ */
571
+ const OrderedMutationScoreThresholds = S.declare(isMutationScoreThresholds, {
572
+ message: "expected thresholds where low <= high",
573
+ toCodecArbitrary: () => S.link()(MutationScoreThresholdsValuesSchema, {
574
+ decode: SchemaGetter.transform(({ break: breaking, high, low }) => ({
575
+ break: breaking,
576
+ high: Math.max(high, low),
577
+ low: Math.min(high, low)
578
+ })),
579
+ encode: SchemaGetter.transform((thresholds) => thresholds)
580
+ })
581
+ });
582
+ const MutationScoreThresholdsSchema = MutationScoreThresholdsValuesSchema.pipe(S.decodeTo(OrderedMutationScoreThresholds, SchemaTransformation.passthrough()));
487
583
  const MutatorDescriptor = S.Struct({ excludedMutations: defaulted(S.Array(S.String), []) });
488
584
  const WarningOptions = openStruct({
489
585
  unknownOptions: defaulted(S.Boolean, true),
@@ -708,4 +804,4 @@ const parseTraceparent = (value) => {
708
804
  };
709
805
  const TraceContextReference = Context.Reference("@systemfsoftware/stryker-js-plugin-interface/TraceContextReference", { defaultValue: () => Option.none() });
710
806
  //#endregion
711
- export { BoundaryErrorSchema, BoundaryPayloadRejected, BoundaryUnrecognizedSignal, BrandingInformationSchema, CheckResultSchema, CheckStatus, Checker, CheckerCheckResult, CheckerCustomConfigSchema, CheckerEntryConfigSchema, CheckerFailed, CheckerGroupResult, CheckerMutantWire, CheckerRequest, CheckerRpcs, CommandRunnerOptionsSchema, CoverageAnalysisMode, CoverageAnalysisSchema, DependenciesSchema, DryRunCompleted, DryRunOptionsSchema, DryRunResultSchema, DryRunStatus, EXIT_CODE, Evaluator, EvaluatorFailed, ExitClass, FileResultDictionarySchema, FileResultSchema, FrameworkInformationSchema, LocationSchema, LogLevel, MetricsResultSchema, MetricsSchema, MutantActivationSchema, MutantCoverageSchema, MutantResultSchema, MutantRunOptionsSchema, MutantRunResultSchema, MutantRunStatus, MutantStatusSchema, MutantTested, MutationScoreThresholdsSchema, MutationTestReportReady, MutationTestResultSchema, MutationTestingPlanReady, OpenEndLocationSchema, PackageManager, 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, WorkerEntryUrl, WorkerPluginKind, WorkerPluginSpawnSchema, formatTraceparent, isCustomTestRunner, parseTraceparent, propertyPath, strykerCoreSchema, strykerReportBugUrl, testFilesProvided, toMutantRunResult };
807
+ 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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@systemfsoftware/stryker-js-plugin-interface",
3
- "version": "7.0.0",
3
+ "version": "7.1.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/systemfsoftware/stryker-js-effect.git",
@@ -18,26 +18,26 @@
18
18
  "node": ">=20.0.0"
19
19
  },
20
20
  "dependencies": {
21
- "effect": "4.0.0-rc.112",
21
+ "effect": "4.0.0-rc.116",
22
22
  "@systemfsoftware/stryker-js-instrumenter": "^8.0.0"
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/all": "^2.1.1",
28
+ "@systemfsoftware/arethetypeswrong-cli": "^4.2.0",
29
+ "@systemfsoftware/effect-schema-law": "^2.2.0",
30
+ "@systemfsoftware/effect-schema-vite": "^2.2.0",
31
+ "@systemfsoftware/tsconfig": "^1.3.5",
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",
39
- "@systemfsoftware/vitest-config": "^0.1.0",
40
- "@systemfsoftware/tsdown-config": "^0.1.0"
38
+ "vitest": "^5",
39
+ "@systemfsoftware/tsdown-config": "^0.1.0",
40
+ "@systemfsoftware/vitest-config": "^0.1.0"
41
41
  },
42
42
  "publishConfig": {
43
43
  "access": "public",