@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,16 @@
1
+ import { r as PluginCreator } from "./index-CyOSz6LC.mjs";
2
+ import { t as CheckerResource } from "./checker-resource-DTYEKXdg.mjs";
3
+ import { Mutant, StrykerOptions } from "@systemfsoftware/stryker-js-plugin-api/core";
4
+ import { CheckResult } from "@systemfsoftware/stryker-js-plugin-api/check";
5
+ //#region src/checker/checker-worker.d.ts
6
+ declare class CheckerWorker implements CheckerResource {
7
+ private readonly innerCheckers;
8
+ static inject: ["options", "pluginCreator"];
9
+ constructor(options: StrykerOptions, pluginCreator: PluginCreator);
10
+ init(): Promise<void>;
11
+ check(checkerName: string, mutants: Mutant[]): Promise<Record<string, CheckResult>>;
12
+ group(checkerName: string, mutants: Mutant[]): Promise<string[][]>;
13
+ private perform;
14
+ }
15
+ //#endregion
16
+ export { CheckerWorker };
@@ -0,0 +1,2 @@
1
+ import { n as CheckerWorker } from "./checker-C4tGiXtZ.mjs";
2
+ export { CheckerWorker };
@@ -0,0 +1,567 @@
1
+ import { D as loggingServer, E as loggerShowColors, I as pluginsByKind, O as loggingServerAddress, P as pluginCreator, T as loggerConsoleOut, k as loggingSink, p as PluginCreator, t as PluginLoader, w as loggerActiveLevel } from "./plugins-Nx86IJQW.mjs";
2
+ import { StrykerOptionsSchema } from "@systemfsoftware/stryker-js-plugin-api/core";
3
+ import { Scope, commonTokens } from "@systemfsoftware/stryker-js-plugin-api/plugin";
4
+ import "typed-inject";
5
+ import { errorToString } from "@stryker-mutator/util";
6
+ import fs from "fs";
7
+ import util, { promisify } from "util";
8
+ import path from "path";
9
+ import { Exit, Schema } from "effect";
10
+ import "@systemfsoftware/stryker-js-plugin-api/logging";
11
+ import net from "net";
12
+ import net$1 from "node:net";
13
+ import { promisify as promisify$1 } from "node:util";
14
+ //#region src/logging/log-level.ts
15
+ /**
16
+ * Re-export of @systemfsoftware/stryker-js-plugin-api/core's LogLevel const enum as a local runtime object.
17
+ * The upstream uses `const enum` which rolldown/oxc doesn't inline at bundle time,
18
+ * and which has no runtime emit.
19
+ *
20
+ * Using a const object + type pattern instead of an enum keeps the type structurally
21
+ * compatible with the upstream's LogLevel (both are the same string literal union),
22
+ * so values from @systemfsoftware/stryker-js-plugin-api/core types are assignable without casting.
23
+ */
24
+ const LogLevel = {
25
+ Trace: "trace",
26
+ Debug: "debug",
27
+ Information: "info",
28
+ Warning: "warn",
29
+ Error: "error",
30
+ Fatal: "fatal",
31
+ Off: "off"
32
+ };
33
+ //#endregion
34
+ //#region src/logging/logging-event.schema.ts
35
+ /**
36
+ * The wire format of a {@link LoggingEvent}; worker processes serialize
37
+ * events over the logging socket, the server deserializes them.
38
+ */
39
+ const SerializedLoggingEventSchema = Schema.Struct({
40
+ startTime: Schema.String,
41
+ categoryName: Schema.String,
42
+ message: Schema.String,
43
+ level: Schema.Literals([
44
+ LogLevel.Trace,
45
+ LogLevel.Debug,
46
+ LogLevel.Information,
47
+ LogLevel.Warning,
48
+ LogLevel.Error,
49
+ LogLevel.Fatal,
50
+ LogLevel.Off
51
+ ]),
52
+ pid: Schema.Finite
53
+ });
54
+ //#endregion
55
+ //#region src/logging/logging-event.ts
56
+ const pattern = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");
57
+ const ansiRegex = new RegExp(pattern, "g");
58
+ var LoggingEvent = class LoggingEvent {
59
+ startTime;
60
+ categoryName;
61
+ data;
62
+ level;
63
+ pid;
64
+ constructor(categoryName, level, data, startTime, pid) {
65
+ this.startTime = startTime;
66
+ this.categoryName = categoryName;
67
+ this.data = data;
68
+ this.level = level;
69
+ this.pid = pid;
70
+ }
71
+ static create(categoryName, level, data) {
72
+ return new LoggingEvent(categoryName, level, data, /* @__PURE__ */ new Date(), process.pid);
73
+ }
74
+ format() {
75
+ return `${this.#formatPrefix()} ${this.#formatMessage().replace(ansiRegex, "")}`;
76
+ }
77
+ formatColorized() {
78
+ return `${this.#colorizedStart()}${this.#formatPrefix()}${this.#colorizedEnd()} ${this.#formatMessage()}`;
79
+ }
80
+ #formatPrefix() {
81
+ return `${this.startTime.toTimeString().slice(0, 8)} (${this.pid}) ${this.level.toUpperCase()} ${this.categoryName}`;
82
+ }
83
+ #formatMessage() {
84
+ return util.format(...this.data);
85
+ }
86
+ #colorizedStart() {
87
+ return `\x1B[${styles[this.level]}m`;
88
+ }
89
+ #colorizedEnd() {
90
+ return "\x1B[39m";
91
+ }
92
+ static deserialize(ser) {
93
+ return new LoggingEvent(ser.categoryName, ser.level, [ser.message], new Date(ser.startTime), ser.pid);
94
+ }
95
+ serialize() {
96
+ return {
97
+ startTime: this.startTime.toJSON(),
98
+ categoryName: this.categoryName,
99
+ message: this.#formatMessage(),
100
+ level: this.level,
101
+ pid: this.pid
102
+ };
103
+ }
104
+ };
105
+ const styles = Object.freeze({
106
+ trace: 34,
107
+ debug: 36,
108
+ info: 32,
109
+ warn: 33,
110
+ error: 91,
111
+ fatal: 35,
112
+ off: 90
113
+ });
114
+ //#endregion
115
+ //#region src/logging/priority.ts
116
+ const logLevelPriority = Object.freeze({
117
+ [LogLevel.Trace]: 0,
118
+ [LogLevel.Debug]: 1,
119
+ [LogLevel.Information]: 2,
120
+ [LogLevel.Warning]: 3,
121
+ [LogLevel.Error]: 4,
122
+ [LogLevel.Fatal]: 5,
123
+ [LogLevel.Off]: 6
124
+ });
125
+ function minPriority(a, b) {
126
+ return logLevelPriority[a] < logLevelPriority[b] ? a : b;
127
+ }
128
+ //#endregion
129
+ //#region src/logging/logging-backend.ts
130
+ const LOG_FILE_NAME = "stryker.log";
131
+ /**
132
+ * The logging backend that handles the actual logging. So to both a file and the stdout, stderr.
133
+ */
134
+ var LoggingBackend = class {
135
+ activeStdoutLevel = LogLevel.Information;
136
+ activeFileLevel = LogLevel.Off;
137
+ showColors;
138
+ #consoleOut;
139
+ static inject = [loggerConsoleOut, loggerShowColors];
140
+ constructor(consoleOut, showColors) {
141
+ this.#consoleOut = consoleOut;
142
+ this.showColors = showColors;
143
+ }
144
+ log(event) {
145
+ const eventPriority = logLevelPriority[event.level];
146
+ if (eventPriority >= logLevelPriority[this.activeStdoutLevel]) this.#consoleOut.write(`${this.showColors ? event.formatColorized() : event.format()}\n`);
147
+ if (eventPriority >= logLevelPriority[this.activeFileLevel] && !this.#fileStream.errored) this.#fileStream.write(`${event.format()}\n`);
148
+ }
149
+ isEnabled(level) {
150
+ return logLevelPriority[level] >= this.priority;
151
+ }
152
+ get activeLogLevel() {
153
+ return minPriority(this.activeStdoutLevel, this.activeFileLevel);
154
+ }
155
+ get priority() {
156
+ return logLevelPriority[this.activeLogLevel];
157
+ }
158
+ /**
159
+ * `allowConsoleColors` is deliberately not read here (R8). It defaults to
160
+ * `true` in the schema, so honouring it would re-enable colour on every run
161
+ * and defeat the machine-mode contract; colour is decided once, from the
162
+ * resolved mode and `NO_COLOR`, and injected at construction.
163
+ */
164
+ configure({ logLevel, fileLogLevel }) {
165
+ if (logLevel) this.activeStdoutLevel = logLevel;
166
+ if (fileLogLevel) this.activeFileLevel = fileLogLevel;
167
+ }
168
+ #_fileStream;
169
+ get #fileStream() {
170
+ if (!this.#_fileStream) {
171
+ this.#_fileStream = fs.createWriteStream(LOG_FILE_NAME, { flags: "a" });
172
+ this.#_fileStream.on("error", (error) => {
173
+ console.error(`An error occurred while writing to "${LOG_FILE_NAME}"`, error);
174
+ });
175
+ }
176
+ return this.#_fileStream;
177
+ }
178
+ async dispose() {
179
+ if (this.#_fileStream) await promisify(this.#_fileStream.end.bind(this.#_fileStream))();
180
+ }
181
+ };
182
+ //#endregion
183
+ //#region src/logging/logger-impl.ts
184
+ var LoggerImpl = class {
185
+ #categoryName;
186
+ #loggingBackend;
187
+ constructor(categoryName, loggingBackend) {
188
+ this.#categoryName = categoryName;
189
+ this.#loggingBackend = loggingBackend;
190
+ }
191
+ isTraceEnabled() {
192
+ return this.#loggingBackend.isEnabled(LogLevel.Trace);
193
+ }
194
+ isDebugEnabled() {
195
+ return this.#loggingBackend.isEnabled(LogLevel.Debug);
196
+ }
197
+ isInfoEnabled() {
198
+ return this.#loggingBackend.isEnabled(LogLevel.Information);
199
+ }
200
+ isWarnEnabled() {
201
+ return this.#loggingBackend.isEnabled(LogLevel.Warning);
202
+ }
203
+ isErrorEnabled() {
204
+ return this.#loggingBackend.isEnabled(LogLevel.Error);
205
+ }
206
+ isFatalEnabled() {
207
+ return this.#loggingBackend.isEnabled(LogLevel.Fatal);
208
+ }
209
+ trace(message, ...args) {
210
+ this.#loggingBackend.log(LoggingEvent.create(this.#categoryName, LogLevel.Trace, [message, ...args]));
211
+ }
212
+ debug(message, ...args) {
213
+ this.#loggingBackend.log(LoggingEvent.create(this.#categoryName, LogLevel.Debug, [message, ...args]));
214
+ }
215
+ info(message, ...args) {
216
+ this.#loggingBackend.log(LoggingEvent.create(this.#categoryName, LogLevel.Information, [message, ...args]));
217
+ }
218
+ warn(message, ...args) {
219
+ this.#loggingBackend.log(LoggingEvent.create(this.#categoryName, LogLevel.Warning, [message, ...args]));
220
+ }
221
+ error(message, ...args) {
222
+ this.#loggingBackend.log(LoggingEvent.create(this.#categoryName, LogLevel.Error, [message, ...args]));
223
+ }
224
+ fatal(message, ...args) {
225
+ this.#loggingBackend.log(LoggingEvent.create(this.#categoryName, LogLevel.Fatal, [message, ...args]));
226
+ }
227
+ };
228
+ //#endregion
229
+ //#region src/logging/logging-server.ts
230
+ const DELIMITER = "__STRYKER_CORE__";
231
+ var LoggingServer = class LoggingServer {
232
+ loggingSink;
233
+ static inject = [loggingSink];
234
+ #server;
235
+ constructor(loggingSink) {
236
+ this.loggingSink = loggingSink;
237
+ this.#server = net$1.createServer((socket) => {
238
+ socket.setEncoding("utf-8");
239
+ let dataSoFar = "";
240
+ socket.on("data", (data) => {
241
+ dataSoFar += data;
242
+ let index;
243
+ while ((index = dataSoFar.indexOf(DELIMITER)) !== -1) {
244
+ const serialized = JSON.parse(dataSoFar.substring(0, index));
245
+ const logEvent = Schema.decodeUnknownSync(SerializedLoggingEventSchema)(serialized);
246
+ dataSoFar = dataSoFar.substring(index + 16);
247
+ this.loggingSink.log(LoggingEvent.deserialize(logEvent));
248
+ }
249
+ });
250
+ socket.on("error", (error) => {
251
+ this.loggingSink.log(LoggingEvent.create(LoggingServer.name, LogLevel.Debug, ["An worker log process hung up unexpectedly", error]));
252
+ });
253
+ });
254
+ }
255
+ listen() {
256
+ const { promise, resolve } = Promise.withResolvers();
257
+ this.#server.listen(() => {
258
+ const address = this.#server.address();
259
+ if (address === null || typeof address === "string") throw new Error(`Address of the logging server is not an AddressInfo: ${typeof address}`);
260
+ resolve({ port: address.port });
261
+ });
262
+ return promise;
263
+ }
264
+ async dispose() {
265
+ await promisify$1(this.#server.close.bind(this.#server))();
266
+ }
267
+ };
268
+ //#endregion
269
+ //#region src/logging/logging-client.ts
270
+ var LoggingClient = class LoggingClient {
271
+ logLevel;
272
+ loggingServerAddress;
273
+ #socket;
274
+ static inject = [loggerActiveLevel, loggingServerAddress];
275
+ constructor(logLevel, loggingServerAddress) {
276
+ this.logLevel = logLevel;
277
+ this.loggingServerAddress = loggingServerAddress;
278
+ }
279
+ openConnection() {
280
+ return new Promise((res, rej) => {
281
+ this.#socket = net.createConnection(this.loggingServerAddress.port, "localhost", res);
282
+ this.#socket.on("error", (error) => {
283
+ console.error("Error occurred in logging client", error);
284
+ rej(error);
285
+ });
286
+ });
287
+ }
288
+ log(event) {
289
+ if (!this.#socket) throw new Error(`Cannot use the logging client before it is connected, please call '${LoggingClient.name}.prototype.${LoggingClient.prototype.openConnection.name}' first`);
290
+ if (this.isEnabled(event.level) && this.#socket.writable) this.#socket.write(JSON.stringify(event.serialize()) + DELIMITER);
291
+ }
292
+ isEnabled(level) {
293
+ return logLevelPriority[level] >= logLevelPriority[this.logLevel];
294
+ }
295
+ async dispose() {
296
+ if (this.#socket) await promisify(this.#socket.end.bind(this.#socket))();
297
+ }
298
+ };
299
+ //#endregion
300
+ //#region src/logging/provide-logging.ts
301
+ function getLoggerFactory(loggingSink) {
302
+ return (categoryName) => new LoggerImpl(categoryName ?? "UNKNOWN", loggingSink);
303
+ }
304
+ getLoggerFactory.inject = [loggingSink];
305
+ function loggerFactory(getLogger, target) {
306
+ return getLogger(target?.name);
307
+ }
308
+ loggerFactory.inject = [commonTokens.getLogger, commonTokens.target];
309
+ function provideLogging(injector) {
310
+ return injector.provideFactory(commonTokens.getLogger, getLoggerFactory).provideFactory(commonTokens.logger, loggerFactory, Scope.Transient).provideClass("loggingServer", LoggingServer);
311
+ }
312
+ provideLogging.inject = [loggingSink, commonTokens.injector];
313
+ async function provideLoggingBackend(injector, loggerConsoleOut$1, showColors) {
314
+ const out = injector.provideValue(loggerConsoleOut, loggerConsoleOut$1).provideValue(loggerShowColors, showColors).provideClass(loggingSink, LoggingBackend).provideClass(loggingServer, LoggingServer);
315
+ const loggingServerAddress$2 = await out.resolve(loggingServer).listen();
316
+ return out.provideValue(loggingServerAddress, loggingServerAddress$2);
317
+ }
318
+ provideLoggingBackend.inject = [commonTokens.injector];
319
+ async function provideLoggingClient(injector, loggingServerAddress$1, activeLogLevel) {
320
+ const out = injector.provideValue(loggingServerAddress, loggingServerAddress$1).provideValue(loggerActiveLevel, activeLogLevel).provideClass(loggingSink, LoggingClient);
321
+ await out.resolve(loggingSink).openConnection();
322
+ return out;
323
+ }
324
+ //#endregion
325
+ //#region src/worker-pool/message-protocol.schema.ts
326
+ const LoggingServerAddressSchema = Schema.Struct({ port: Schema.Finite });
327
+ const PositionSchema = Schema.Struct({
328
+ line: Schema.Finite,
329
+ column: Schema.Finite
330
+ });
331
+ const MutationRangeSchema = Schema.Struct({
332
+ start: PositionSchema,
333
+ end: PositionSchema
334
+ });
335
+ const FileDescriptionSchema = Schema.Struct({ mutate: Schema.Union([Schema.mutable(Schema.Array(MutationRangeSchema)), Schema.Boolean]) });
336
+ const FileDescriptionsSchema = Schema.Record(Schema.String, FileDescriptionSchema);
337
+ const InitMessageSchema = Schema.Struct({
338
+ kind: Schema.Literal(0),
339
+ loggingServerAddress: LoggingServerAddressSchema,
340
+ options: StrykerOptionsSchema,
341
+ fileDescriptions: FileDescriptionsSchema,
342
+ pluginModulePaths: Schema.Array(Schema.String),
343
+ workingDirectory: Schema.String,
344
+ namedExport: Schema.String,
345
+ modulePath: Schema.String
346
+ });
347
+ const CallMessageSchema = Schema.Struct({
348
+ correlationId: Schema.Finite,
349
+ kind: Schema.Literal(1),
350
+ args: Schema.mutable(Schema.Array(Schema.Any)),
351
+ methodName: Schema.String
352
+ });
353
+ const DisposeMessageSchema = Schema.Struct({ kind: Schema.Literal(2) });
354
+ /** Messages sent from the parent process to the child process. */
355
+ const WorkerMessageSchema = Schema.Union([
356
+ CallMessageSchema,
357
+ DisposeMessageSchema,
358
+ InitMessageSchema
359
+ ]);
360
+ const ReadyMessageSchema = Schema.Struct({ kind: Schema.Literals([
361
+ 5,
362
+ 1,
363
+ 0
364
+ ]) });
365
+ const WorkResultSchema = Schema.Struct({
366
+ correlationId: Schema.Finite,
367
+ kind: Schema.Literal(3),
368
+ result: Schema.Any
369
+ });
370
+ const RejectionResultSchema = Schema.Struct({
371
+ correlationId: Schema.Finite,
372
+ kind: Schema.Literal(4),
373
+ error: Schema.String
374
+ });
375
+ const InitRejectionResultSchema = Schema.Struct({
376
+ kind: Schema.Literal(2),
377
+ error: Schema.String
378
+ });
379
+ /** Messages sent from the child process back to the parent process. */
380
+ const ParentMessageSchema = Schema.Union([
381
+ ReadyMessageSchema,
382
+ WorkResultSchema,
383
+ RejectionResultSchema,
384
+ InitRejectionResultSchema
385
+ ]);
386
+ /**
387
+ * Both wire schemas are declared with `S.fromJsonString` applied at the point of
388
+ * use, never here: a const initialized to `S.encodeSync(...)` is a *use* of a
389
+ * schema, not a declaration of one, and this file declares. Keeping the uses out
390
+ * also keeps them out of the generated law suite, which reads every exported
391
+ * schema in the package and cannot build an arbitrary from a function.
392
+ */
393
+ //#endregion
394
+ //#region src/worker-pool/subject-module.schema.ts
395
+ /**
396
+ * The child worker was pointed at a module that carries no constructable value
397
+ * under the requested export name. It is a tagged error rather than a bare
398
+ * `throw` so the failure has a name in the type and survives the process
399
+ * boundary as data: the parent reads it back off the `InitError` reply.
400
+ */
401
+ var SubjectModuleError = class extends Schema.TaggedError()("SubjectModuleError", {
402
+ modulePath: Schema.String,
403
+ namedExport: Schema.String
404
+ }) {};
405
+ /**
406
+ * This half produced a message its own schema refuses to encode. Unlike a decode
407
+ * failure there is no honest way to answer it on the wire - the reply itself is
408
+ * what is broken - so it stays a defect this process raises rather than a value
409
+ * it sends.
410
+ */
411
+ var ProtocolEncodeError = class extends Schema.TaggedError()("ProtocolEncodeError", { reason: Schema.String }) {};
412
+ //#endregion
413
+ //#region src/worker-pool/child-process-proxy-worker.ts
414
+ /**
415
+ * This half's two directions, built once from the declared schemas. Three
416
+ * properties matter and each is load-bearing:
417
+ *
418
+ * - The JSON boundary belongs to the schema. A hand-written `JSON.stringify`
419
+ * step is not schema-aware, so it drops a member the decoder then demands and
420
+ * the two halves of one format disagree.
421
+ * - They return an `Exit`, never throwing. A decode failure on a process
422
+ * boundary is an expected outcome, so it is a value this code must answer for
423
+ * rather than an exception that leaves the type unmarked.
424
+ * - They take `unknown`, so the envelope codec performs the only narrowing this
425
+ * half needs. A separate `S.Json` check on the payload would guard the same
426
+ * bytes twice: `args` and `result` are declared `S.Json`, so these already
427
+ * reject anything the wire cannot carry.
428
+ */
429
+ const decodeWorkerMessage = Schema.decodeUnknownExit(Schema.fromJsonString(WorkerMessageSchema));
430
+ const encodeParentMessage = Schema.encodeUnknownExit(Schema.fromJsonString(ParentMessageSchema));
431
+ /**
432
+ * The two runtime narrowings this worker cannot derive statically, because both
433
+ * subjects arrive from a path decided at runtime. They are type guards rather
434
+ * than schemas on purpose: a `Schema.declare` whose predicate only asks
435
+ * `typeof x === 'function'` states far more than it decides, and it cannot be
436
+ * generated, round-tripped or held to any law - the schema law suite refuses it.
437
+ */
438
+ const isCallableMember = (input) => typeof input === "function";
439
+ const isSubjectClass = (input) => typeof input === "function";
440
+ var ChildProcessProxyWorker = class ChildProcessProxyWorker {
441
+ injectorFactory;
442
+ log;
443
+ injector;
444
+ realSubject;
445
+ constructor(injectorFactory) {
446
+ this.injectorFactory = injectorFactory;
447
+ process.on("message", this.handleMessage);
448
+ this.send({ kind: 0 });
449
+ this.injector = this.injectorFactory();
450
+ }
451
+ send(value) {
452
+ const encoded = encodeParentMessage(value);
453
+ if (Exit.isFailure(encoded)) throw new ProtocolEncodeError({ reason: String(encoded.cause) });
454
+ if (process.send) process.send(encoded.value);
455
+ }
456
+ handleMessage = (serializedMessage) => {
457
+ const decoded = decodeWorkerMessage(serializedMessage);
458
+ if (Exit.isFailure(decoded)) {
459
+ this.send({
460
+ error: String(decoded.cause),
461
+ kind: 2
462
+ });
463
+ return;
464
+ }
465
+ const message = decoded.value;
466
+ switch (message.kind) {
467
+ case 0:
468
+ this.handleInit(message);
469
+ this.removeAnyAdditionalMessageListeners(this.handleMessage);
470
+ break;
471
+ case 1:
472
+ this.handleCall(message);
473
+ this.removeAnyAdditionalMessageListeners(this.handleMessage);
474
+ break;
475
+ case 2: {
476
+ const sendCompleted = () => {
477
+ this.send({ kind: 5 });
478
+ };
479
+ this.injector.dispose().then(sendCompleted).catch(sendCompleted);
480
+ break;
481
+ }
482
+ }
483
+ };
484
+ async handleInit(message) {
485
+ try {
486
+ this.handlePromiseRejections();
487
+ const pluginInjector = provideLogging(await provideLoggingClient(this.injector, message.loggingServerAddress, minPriority(message.options.logLevel, message.options.fileLogLevel))).provideValue(commonTokens.options, message.options).provideValue(commonTokens.fileDescriptions, message.fileDescriptions);
488
+ this.log = pluginInjector.resolve(commonTokens.getLogger)(ChildProcessProxyWorker.name);
489
+ const { pluginsByKind: pluginsByKind$1 } = await pluginInjector.injectClass(PluginLoader).load(message.pluginModulePaths);
490
+ const workingDir = path.resolve(message.workingDirectory);
491
+ const injector = pluginInjector.provideValue(pluginsByKind, pluginsByKind$1).provideValue(commonTokens.sandboxDirectory, workingDir).provideClass(pluginCreator, PluginCreator);
492
+ const childModule = await import(message.modulePath);
493
+ const namedExport = Schema.decodeUnknownSync(Schema.Record(Schema.String, Schema.Unknown))(childModule)[message.namedExport];
494
+ if (!isSubjectClass(namedExport)) throw new SubjectModuleError({
495
+ modulePath: message.modulePath,
496
+ namedExport: message.namedExport
497
+ });
498
+ const RealSubjectClass = namedExport;
499
+ if (process.cwd() !== workingDir) {
500
+ this.log.debug(`Changing current working directory for this process to ${workingDir}`);
501
+ process.chdir(workingDir);
502
+ }
503
+ this.realSubject = injector.injectClass(RealSubjectClass);
504
+ this.send({ kind: 1 });
505
+ } catch (err) {
506
+ this.send({
507
+ error: errorToString(err),
508
+ kind: 2
509
+ });
510
+ }
511
+ }
512
+ async handleCall(message) {
513
+ try {
514
+ const result = await this.doCall(message);
515
+ this.send({
516
+ correlationId: message.correlationId,
517
+ kind: 3,
518
+ result: result ?? null
519
+ });
520
+ } catch (err) {
521
+ this.send({
522
+ correlationId: message.correlationId,
523
+ error: errorToString(err),
524
+ kind: 4
525
+ });
526
+ }
527
+ }
528
+ doCall(message) {
529
+ const realSubject = this.realSubject;
530
+ if (realSubject === void 0) throw new Error("Cannot call methods on the real subject before the child process is initialized.");
531
+ const subjectMember = realSubject[message.methodName];
532
+ if (isCallableMember(subjectMember)) return Reflect.apply(subjectMember, realSubject, message.args);
533
+ else return subjectMember;
534
+ }
535
+ /**
536
+ * Remove any addition message listeners that might me eavesdropping.
537
+ * the @ngtools/webpack plugin listens to messages and throws an error whenever it could not handle a message
538
+ * @see https://github.com/angular/angular-cli/blob/f776d3cf7982b64734c57fe4407434e9f4ec09f7/packages/%40ngtools/webpack/src/type_checker.ts#L79
539
+ * @param exceptListener The listener that should remain
540
+ */
541
+ removeAnyAdditionalMessageListeners(exceptListener) {
542
+ process.listeners("message").forEach((listener) => {
543
+ if (listener !== exceptListener) {
544
+ this.log?.debug("Removing an additional message listener, we don't want eavesdropping on our inter-process communication: %s", listener.toString());
545
+ process.removeListener("message", listener);
546
+ }
547
+ });
548
+ }
549
+ /**
550
+ * During mutation testing, it's to be expected that promise rejections are not handled synchronously anymore (or not at all)
551
+ * Let's handle those events so future versions of node don't crash
552
+ * See issue 350: https://github.com/stryker-mutator/stryker-js/issues/350
553
+ */
554
+ handlePromiseRejections() {
555
+ const unhandledRejections = [];
556
+ process.on("unhandledRejection", (reason, promise) => {
557
+ const unhandledPromiseId = unhandledRejections.push(promise);
558
+ this.log?.debug(`UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: ${unhandledPromiseId}): ${errorToString(reason)}`);
559
+ });
560
+ process.on("rejectionHandled", (promise) => {
561
+ const unhandledPromiseId = unhandledRejections.indexOf(promise) + 1;
562
+ this.log?.debug(`PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: ${unhandledPromiseId})`);
563
+ });
564
+ }
565
+ };
566
+ //#endregion
567
+ export { provideLogging as a, WorkerMessageSchema as i, ProtocolEncodeError as n, provideLoggingBackend as o, ParentMessageSchema as r, ChildProcessProxyWorker as t };
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,6 @@
1
+ import { t as ChildProcessProxyWorker } from "./child-process-proxy-worker-lx1M5Mz3.mjs";
2
+ import { createInjector } from "typed-inject";
3
+ //#region src/worker-pool/child-process-proxy-worker-main.ts
4
+ new ChildProcessProxyWorker(createInjector);
5
+ //#endregion
6
+ export {};
@@ -0,0 +1,50 @@
1
+ import { P as pluginCreator } from "./plugins-Nx86IJQW.mjs";
2
+ import "@systemfsoftware/stryker-js-plugin-api/core";
3
+ import { PluginKind, commonTokens, tokens } from "@systemfsoftware/stryker-js-plugin-api/plugin";
4
+ import { errorToString } from "@stryker-mutator/util";
5
+ import * as S from "effect/Schema";
6
+ import { DryRunStatus, MutantRunStatus } from "@systemfsoftware/stryker-js-plugin-api/test-runner";
7
+ //#region src/test-runner/mutant-coverage.schema.ts
8
+ /**
9
+ * The coverage document the instrumented test bundle accumulates:
10
+ * hit counts per mutant id, both statically (once per test file) and per
11
+ * test id.
12
+ */
13
+ const MutantCoverageSchema = S.Struct({
14
+ static: S.Record(S.String, S.Finite),
15
+ perTest: S.Record(S.String, S.Record(S.String, S.Finite))
16
+ });
17
+ //#endregion
18
+ //#region src/test-runner/child-process-test-runner-worker.ts
19
+ var ChildProcessTestRunnerWorker = class {
20
+ underlyingTestRunner;
21
+ static inject = tokens(commonTokens.options, pluginCreator);
22
+ constructor({ testRunner }, pluginCreator) {
23
+ this.underlyingTestRunner = pluginCreator.create(PluginKind.TestRunner, testRunner);
24
+ }
25
+ async capabilities() {
26
+ return this.underlyingTestRunner.capabilities();
27
+ }
28
+ async init() {
29
+ if (this.underlyingTestRunner.init) await this.underlyingTestRunner.init();
30
+ }
31
+ async dispose() {
32
+ if (this.underlyingTestRunner.dispose) await this.underlyingTestRunner.dispose();
33
+ }
34
+ async dryRun(options) {
35
+ const dryRunResult = await this.underlyingTestRunner.dryRun(options);
36
+ if (dryRunResult.status === DryRunStatus.Complete && !dryRunResult.mutantCoverage && options.coverageAnalysis !== "off") {
37
+ const mutantCoverage = S.decodeUnknownSync(S.optional(MutantCoverageSchema))(globalThis.__mutantCoverage__);
38
+ if (mutantCoverage !== void 0) dryRunResult.mutantCoverage = mutantCoverage;
39
+ }
40
+ if (dryRunResult.status === DryRunStatus.Error) dryRunResult.errorMessage = errorToString(dryRunResult.errorMessage);
41
+ return dryRunResult;
42
+ }
43
+ async mutantRun(options) {
44
+ const result = await this.underlyingTestRunner.mutantRun(options);
45
+ if (result.status === MutantRunStatus.Error) result.errorMessage = errorToString(result.errorMessage);
46
+ return result;
47
+ }
48
+ };
49
+ //#endregion
50
+ export { ChildProcessTestRunnerWorker as t };
@@ -0,0 +1,16 @@
1
+ import { r as PluginCreator } from "./index-CyOSz6LC.mjs";
2
+ import { StrykerOptions } from "@systemfsoftware/stryker-js-plugin-api/core";
3
+ import { DryRunOptions, DryRunResult, MutantRunOptions, MutantRunResult, TestRunner, TestRunnerCapabilities } from "@systemfsoftware/stryker-js-plugin-api/test-runner";
4
+ //#region src/test-runner/child-process-test-runner-worker.d.ts
5
+ declare class ChildProcessTestRunnerWorker implements TestRunner {
6
+ private readonly underlyingTestRunner;
7
+ static inject: ["options", "pluginCreator"];
8
+ constructor({ testRunner }: StrykerOptions, pluginCreator: PluginCreator);
9
+ capabilities(): Promise<TestRunnerCapabilities>;
10
+ init(): Promise<void>;
11
+ dispose(): Promise<void>;
12
+ dryRun(options: DryRunOptions): Promise<DryRunResult>;
13
+ mutantRun(options: MutantRunOptions): Promise<MutantRunResult>;
14
+ }
15
+ //#endregion
16
+ export { ChildProcessTestRunnerWorker };
@@ -0,0 +1,2 @@
1
+ import { t as ChildProcessTestRunnerWorker } from "./child-process-test-runner-worker-BTWRYb8V.mjs";
2
+ export { ChildProcessTestRunnerWorker };
@@ -0,0 +1,21 @@
1
+ import { StrykerOptionsSchema } from "@systemfsoftware/stryker-js-plugin-api/core";
2
+ import * as S from "effect/Schema";
3
+ //#region src/config/base-preset.d.ts
4
+ /**
5
+ * The document a config file holds: the schema's INPUT side, before
6
+ * defaults are applied. Typed against the schema instead of the decoded
7
+ * `StrykerOptions` because this file is a template for user config files,
8
+ * not a resolved option set — and the deep-partial of the decoded type
9
+ * collapses array fields (`never[]`) that this document legitimately sets.
10
+ */
11
+ type BasePreset = S.Codec.Encoded<typeof StrykerOptionsSchema>;
12
+ /**
13
+ * Modal Stryker options, inherited via
14
+ * `"extends": "@systemfsoftware/stryker-js-mutation-run/config/base"`.
15
+ *
16
+ * Relative paths below resolve against the working directory of the run that
17
+ * reads them — the consuming package — not against this file.
18
+ */
19
+ declare const basePreset: BasePreset;
20
+ //#endregion
21
+ export { basePreset as default };