@systemfsoftware/stryker-js-typescript-checker 3.0.3 → 4.0.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 +12 -0
- package/dist/index.mjs +99 -99
- package/package.json +7 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @systemfsoftware/stryker-js-typescript-checker
|
|
2
2
|
|
|
3
|
+
## 4.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- CheckMutantsDecision is now a branded tagged union CheckFinished|RetestRequired instead of a plain record; consumer dispatch is exhaustive over the tags
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies:
|
|
12
|
+
- @systemfsoftware/effect-cell-types@6.0.0
|
|
13
|
+
- @systemfsoftware/stryker-js@1.0.0
|
|
14
|
+
|
|
3
15
|
## 3.0.3
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/index.mjs
CHANGED
|
@@ -8,8 +8,8 @@ import * as S from "effect/Schema";
|
|
|
8
8
|
import { Cell, Wire, Workflow } from "@systemfsoftware/effect-cell-types";
|
|
9
9
|
import { Mutant, errorToString } from "@systemfsoftware/stryker-js/Mutant";
|
|
10
10
|
import { Predicate, Result, Schema } from "effect";
|
|
11
|
-
import { pipe } from "effect/Function";
|
|
12
11
|
import * as HashMap from "effect/HashMap";
|
|
12
|
+
import * as Match from "effect/Match";
|
|
13
13
|
import * as MutableHashMap from "effect/MutableHashMap";
|
|
14
14
|
import * as Option from "effect/Option";
|
|
15
15
|
import { API, DiagnosticCategory } from "typescript/unstable/sync";
|
|
@@ -39,46 +39,7 @@ var typescript_checker_options_default = {
|
|
|
39
39
|
} }
|
|
40
40
|
};
|
|
41
41
|
//#endregion
|
|
42
|
-
//#region src/
|
|
43
|
-
/**
|
|
44
|
-
* Checker — declarations for the TypeScript checker.
|
|
45
|
-
*
|
|
46
|
-
* Houses the wire types and error variants shared by the capability and its
|
|
47
|
-
* workflow. Decoded at the checker boundary; no I/O.
|
|
48
|
-
*/
|
|
49
|
-
var CheckMutantsCommand = class extends S.TaggedClass()("CheckMutantsCommand", { mutants: S.Array(Mutant) }) {};
|
|
50
|
-
/**
|
|
51
|
-
* Every way the TypeScript compiler can fail while serving a check.
|
|
52
|
-
* One tagged error — callers branch only on failure itself; `reason` keeps
|
|
53
|
-
* cases distinguishable in reports.
|
|
54
|
-
*/
|
|
55
|
-
var CompilerFailed = class extends S.TaggedError()("CompilerFailed", {
|
|
56
|
-
reason: S.Literals([
|
|
57
|
-
"not-initialized",
|
|
58
|
-
"no-projects",
|
|
59
|
-
"unknown-file-node",
|
|
60
|
-
"file-not-in-project"
|
|
61
|
-
]),
|
|
62
|
-
subject: S.optional(S.String)
|
|
63
|
-
}) {
|
|
64
|
-
get message() {
|
|
65
|
-
switch (this.reason) {
|
|
66
|
-
case "not-initialized": return "The TypeScript compiler was used before it was initialized";
|
|
67
|
-
case "no-projects": return `No projects were found for ${this.subject ?? "the tsconfig"}`;
|
|
68
|
-
case "unknown-file-node": return `The file graph has no node for '${this.subject ?? "a file"}', which should not happen`;
|
|
69
|
-
case "file-not-in-project": return `'${this.subject ?? "a file"}' is part of your TypeScript project but could not be found on disk`;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
//#endregion
|
|
74
|
-
//#region src/Checker.workflow.ts
|
|
75
|
-
/**
|
|
76
|
-
* Checker — pure check decision.
|
|
77
|
-
*
|
|
78
|
-
* `Workflow.make` lives here and only here. The workflow receives a fully
|
|
79
|
-
* decoded input (mutants + diagnostics + file graph) and produces results plus
|
|
80
|
-
* `needsRetest` without touching I/O.
|
|
81
|
-
*/
|
|
42
|
+
//#region src/check-mutants.workflow.ts
|
|
82
43
|
var DiagnosticWithoutFileError = class extends S.TaggedError()("DiagnosticWithoutFileError", { text: Wire.mint(S.String) }) {};
|
|
83
44
|
var DiagnosticInUnrelatedFileError = class extends S.TaggedError()("DiagnosticInUnrelatedFileError", {
|
|
84
45
|
text: Wire.mint(S.String),
|
|
@@ -98,6 +59,20 @@ var CheckMutantsInput = class extends S.TaggedClass()("CheckMutantsInput", {
|
|
|
98
59
|
diagnostics: S.Array(DiagnosticSchema),
|
|
99
60
|
nodes: Wire.mint(S.Record(Wire.mint(S.String), TSFileNodeSchema))
|
|
100
61
|
}) {};
|
|
62
|
+
const CheckMutantsTypeId = Symbol.for("@systemfsoftware/stryker-js-typescript-checker/CheckMutants");
|
|
63
|
+
const MutantCheckStatusSchema = S.Union([S.Struct({ status: S.Literal("passed") }), S.Struct({
|
|
64
|
+
status: S.Literal("compileError"),
|
|
65
|
+
reason: S.String
|
|
66
|
+
})]);
|
|
67
|
+
var CheckFinished = class extends S.TaggedClass()("CheckFinished", { results: S.Record(S.String, MutantCheckStatusSchema) }) {
|
|
68
|
+
[CheckMutantsTypeId] = CheckMutantsTypeId;
|
|
69
|
+
};
|
|
70
|
+
var RetestRequired = class extends S.TaggedClass()("RetestRequired", {
|
|
71
|
+
results: S.Record(S.String, MutantCheckStatusSchema),
|
|
72
|
+
needsRetest: S.Array(Mutant)
|
|
73
|
+
}) {
|
|
74
|
+
[CheckMutantsTypeId] = CheckMutantsTypeId;
|
|
75
|
+
};
|
|
101
76
|
const normalizeFileName$3 = (fileName) => fileName.replace(/\\/g, "/");
|
|
102
77
|
const getMutantsWithReferenceToChildrenOrSelf = (node, mutants, nodesChecked = []) => {
|
|
103
78
|
if (nodesChecked.includes(node.fileName)) return [];
|
|
@@ -148,18 +123,12 @@ const buildResult = (input) => {
|
|
|
148
123
|
const mutants = input.mutants;
|
|
149
124
|
const diagnostics = input.diagnostics;
|
|
150
125
|
const nodes = input.nodes;
|
|
151
|
-
if (mutants.length === 0) return Result$1.succeed({
|
|
152
|
-
results: {},
|
|
153
|
-
needsRetest: []
|
|
154
|
-
});
|
|
126
|
+
if (mutants.length === 0) return Result$1.succeed(CheckFinished.make({ results: {} }));
|
|
155
127
|
const first = mutants[0];
|
|
156
128
|
if (first === void 0 || nodes[normalizeFileName$3(first.fileName)] === void 0) {
|
|
157
129
|
const results = {};
|
|
158
130
|
for (const m of mutants) results[m.id] = { status: "passed" };
|
|
159
|
-
return Result$1.succeed({
|
|
160
|
-
results,
|
|
161
|
-
needsRetest: []
|
|
162
|
-
});
|
|
131
|
+
return Result$1.succeed(CheckFinished.make({ results }));
|
|
163
132
|
}
|
|
164
133
|
const classified = classifyDiagnosticsPure(diagnostics, mutants, nodes);
|
|
165
134
|
if (Result$1.isFailure(classified)) return Result$1.fail(classified.failure);
|
|
@@ -175,13 +144,46 @@ const buildResult = (input) => {
|
|
|
175
144
|
};
|
|
176
145
|
else if (retestIds[m.id] !== true) results[m.id] = { status: "passed" };
|
|
177
146
|
}
|
|
178
|
-
return Result$1.succeed({
|
|
147
|
+
if (needsRetest.length === 0) return Result$1.succeed(CheckFinished.make({ results }));
|
|
148
|
+
return Result$1.succeed(RetestRequired.make({
|
|
179
149
|
results,
|
|
180
|
-
needsRetest
|
|
181
|
-
});
|
|
150
|
+
needsRetest: [...needsRetest]
|
|
151
|
+
}));
|
|
182
152
|
};
|
|
183
153
|
const checkMutants = Workflow.make(CheckMutantsInput, (input) => buildResult(input));
|
|
184
154
|
//#endregion
|
|
155
|
+
//#region src/Checker.schema.ts
|
|
156
|
+
/**
|
|
157
|
+
* Checker — declarations for the TypeScript checker.
|
|
158
|
+
*
|
|
159
|
+
* Houses the wire types and error variants shared by the capability and its
|
|
160
|
+
* workflow. Decoded at the checker boundary; no I/O.
|
|
161
|
+
*/
|
|
162
|
+
var CheckMutantsCommand = class extends S.TaggedClass()("CheckMutantsCommand", { mutants: S.Array(Mutant) }) {};
|
|
163
|
+
/**
|
|
164
|
+
* Every way the TypeScript compiler can fail while serving a check.
|
|
165
|
+
* One tagged error — callers branch only on failure itself; `reason` keeps
|
|
166
|
+
* cases distinguishable in reports.
|
|
167
|
+
*/
|
|
168
|
+
var CompilerFailed = class extends S.TaggedError()("CompilerFailed", {
|
|
169
|
+
reason: S.Literals([
|
|
170
|
+
"not-initialized",
|
|
171
|
+
"no-projects",
|
|
172
|
+
"unknown-file-node",
|
|
173
|
+
"file-not-in-project"
|
|
174
|
+
]),
|
|
175
|
+
subject: S.optional(S.String)
|
|
176
|
+
}) {
|
|
177
|
+
get message() {
|
|
178
|
+
switch (this.reason) {
|
|
179
|
+
case "not-initialized": return "The TypeScript compiler was used before it was initialized";
|
|
180
|
+
case "no-projects": return `No projects were found for ${this.subject ?? "the tsconfig"}`;
|
|
181
|
+
case "unknown-file-node": return `The file graph has no node for '${this.subject ?? "a file"}', which should not happen`;
|
|
182
|
+
case "file-not-in-project": return `'${this.subject ?? "a file"}' is part of your TypeScript project but could not be found on disk`;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
//#endregion
|
|
185
187
|
//#region src/Compiler.schema.ts
|
|
186
188
|
/**
|
|
187
189
|
* Compiler — declarations for the TypeScript compiler and version guard.
|
|
@@ -1102,18 +1104,7 @@ function makeTypescriptCompiler(options, fs, fsService, pathService) {
|
|
|
1102
1104
|
}
|
|
1103
1105
|
//#endregion
|
|
1104
1106
|
//#region src/Checker.ts
|
|
1105
|
-
/**
|
|
1106
|
-
* Checker — capability that validates mutants against the TypeScript compiler.
|
|
1107
|
-
*
|
|
1108
|
-
* Bridges the checker plugin protocol (`@systemfsoftware/stryker-js/Checker`)
|
|
1109
|
-
* to the compiler service and the pure `checkMutants` workflow. Diagnostics
|
|
1110
|
-
* are classified without I/O; the file graph is sourced from the compiler.
|
|
1111
|
-
*/
|
|
1112
1107
|
const normalizeFileName = (fileName) => fileName.replace(/\\/g, "/");
|
|
1113
|
-
/**
|
|
1114
|
-
* Pure grouping decision: separates mutants inside the project graph from
|
|
1115
|
-
* those outside it, honouring `prioritizePerformanceOverAccuracy`.
|
|
1116
|
-
*/
|
|
1117
1108
|
function partitionMutantsForGrouping(mutants, nodes, prioritizePerformanceOverAccuracy) {
|
|
1118
1109
|
if (!prioritizePerformanceOverAccuracy) return {
|
|
1119
1110
|
inside: [],
|
|
@@ -1137,32 +1128,39 @@ function getPrioritize(options) {
|
|
|
1137
1128
|
if (typeof val === "boolean") return val;
|
|
1138
1129
|
return false;
|
|
1139
1130
|
}
|
|
1140
|
-
const
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1131
|
+
const checkCell = Cell.layer({
|
|
1132
|
+
read: (command) => Effect.gen(function* () {
|
|
1133
|
+
const compiler = yield* TypeScriptCompiler;
|
|
1134
|
+
const nodesHm = yield* compiler.nodes.pipe(Effect.mapError((cause) => new CheckerFailed({
|
|
1135
|
+
checkerName: "typescript",
|
|
1136
|
+
mutantIds: command.mutants.map((m) => m.id),
|
|
1137
|
+
cause: errorToString(cause)
|
|
1138
|
+
})));
|
|
1139
|
+
const nodes = {};
|
|
1140
|
+
for (const [k, v] of nodesHm) nodes[k] = v;
|
|
1141
|
+
const diagnostics = yield* compiler.check([...command.mutants]).pipe(Effect.mapError((cause) => new CheckerFailed({
|
|
1142
|
+
checkerName: "typescript",
|
|
1143
|
+
mutantIds: command.mutants.map((m) => m.id),
|
|
1144
|
+
cause: errorToString(cause)
|
|
1145
|
+
})));
|
|
1146
|
+
return new CheckMutantsInput({
|
|
1147
|
+
mutants: [...command.mutants],
|
|
1148
|
+
diagnostics: [...diagnostics],
|
|
1149
|
+
nodes
|
|
1150
|
+
});
|
|
1151
|
+
}),
|
|
1152
|
+
decode: (raw) => Result.succeed(raw),
|
|
1153
|
+
decide: checkMutants,
|
|
1154
|
+
encode: (outcome) => outcome,
|
|
1155
|
+
write: (outcome) => Result.match(outcome, {
|
|
1156
|
+
onFailure: (failure) => Effect.fail(new CheckerFailed({
|
|
1157
|
+
checkerName: "typescript",
|
|
1158
|
+
mutantIds: [],
|
|
1159
|
+
cause: errorToString(failure)
|
|
1160
|
+
})),
|
|
1161
|
+
onSuccess: (decision) => Effect.succeed(decision)
|
|
1162
|
+
})
|
|
1163
|
+
});
|
|
1166
1164
|
function makeCheckerService({ options, compiler }) {
|
|
1167
1165
|
const formatDiagnostic = (error) => Effect.gen(function* () {
|
|
1168
1166
|
let severity;
|
|
@@ -1204,8 +1202,7 @@ function makeCheckerService({ options, compiler }) {
|
|
|
1204
1202
|
}
|
|
1205
1203
|
}),
|
|
1206
1204
|
check: (mutants) => Effect.gen(function* () {
|
|
1207
|
-
const
|
|
1208
|
-
const applyOnce = (group) => Cell.apply(description, new CheckMutantsCommand({ mutants: [...group] }));
|
|
1205
|
+
const applyOnce = (group) => Cell.run(checkCell, new CheckMutantsCommand({ mutants: [...group] })).pipe(Effect.provideService(TypeScriptCompiler, compiler));
|
|
1209
1206
|
const first = yield* applyOnce(mutants);
|
|
1210
1207
|
let map = HashMap.empty();
|
|
1211
1208
|
const mergeResults = (results) => {
|
|
@@ -1216,14 +1213,17 @@ function makeCheckerService({ options, compiler }) {
|
|
|
1216
1213
|
});
|
|
1217
1214
|
};
|
|
1218
1215
|
mergeResults(first.results);
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
const
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1216
|
+
yield* Match.value(first).pipe(Match.tag("CheckFinished", () => Effect.void), Match.tag("RetestRequired", (retest) => Effect.gen(function* () {
|
|
1217
|
+
yield* applyOnce([]);
|
|
1218
|
+
const originals = {};
|
|
1219
|
+
for (const m of mutants) originals[m.id] = m;
|
|
1220
|
+
for (const pending of retest.needsRetest) {
|
|
1221
|
+
const original = originals[pending.id];
|
|
1222
|
+
if (original === void 0) continue;
|
|
1223
|
+
const one = yield* applyOnce([original]);
|
|
1224
|
+
mergeResults(one.results);
|
|
1225
|
+
}
|
|
1226
|
+
})), Match.exhaustive);
|
|
1227
1227
|
return map;
|
|
1228
1228
|
}),
|
|
1229
1229
|
group: (mutants) => Effect.gen(function* () {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@systemfsoftware/stryker-js-typescript-checker",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/systemfsoftware/systemfsoftware.git",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"effect": "^4.0.0-rc.112",
|
|
24
24
|
"typescript": "^7",
|
|
25
|
-
"@systemfsoftware/
|
|
26
|
-
"@systemfsoftware/
|
|
25
|
+
"@systemfsoftware/stryker-js": "^1.0.0",
|
|
26
|
+
"@systemfsoftware/effect-cell-types": "^6.0.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@effect/platform-node": "^4.0.0-rc.112",
|
|
@@ -35,14 +35,13 @@
|
|
|
35
35
|
"rimraf": "^6.1.3",
|
|
36
36
|
"tsdown": "^0.22.14",
|
|
37
37
|
"vitest": "^4",
|
|
38
|
+
"@systemfsoftware/all": "^1.1.2",
|
|
38
39
|
"@systemfsoftware/effect-gherkin-spec": "^4.0.0",
|
|
39
|
-
"@systemfsoftware/effect-schema-vite": "^2.0.2",
|
|
40
40
|
"@systemfsoftware/effect-schema-law": "^2.0.1",
|
|
41
|
-
"@systemfsoftware/all": "^1.1.0",
|
|
42
|
-
"@systemfsoftware/oxlint-config": "^0.1.0",
|
|
43
|
-
"@systemfsoftware/stryker-js-platform-node": "^0.2.0",
|
|
44
41
|
"@systemfsoftware/tsconfig": "^1.3.3",
|
|
45
|
-
"@systemfsoftware/vitest-config": "^0.1.0"
|
|
42
|
+
"@systemfsoftware/vitest-config": "^0.1.0",
|
|
43
|
+
"@systemfsoftware/oxlint-config": "^0.1.0",
|
|
44
|
+
"@systemfsoftware/effect-schema-vite": "^2.0.2"
|
|
46
45
|
},
|
|
47
46
|
"inlinedDependencies": {
|
|
48
47
|
"@jsr/std__jsonc": "1.0.2"
|