@powerlines/engine 0.43.29 → 0.43.31

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 (39) hide show
  1. package/dist/_internal/worker.cjs +112 -42
  2. package/dist/_internal/worker.mjs +112 -42
  3. package/dist/_internal/worker.mjs.map +1 -1
  4. package/dist/api.cjs +9 -7
  5. package/dist/api.d.cts.map +1 -1
  6. package/dist/api.d.mts.map +1 -1
  7. package/dist/api.mjs +9 -7
  8. package/dist/api.mjs.map +1 -1
  9. package/dist/{base-context-B9AROf66.cjs → base-context-CPoqO4io.cjs} +9 -8
  10. package/dist/{base-context-D8a2XGIK.mjs → base-context-SmQ6OfXm.mjs} +10 -9
  11. package/dist/base-context-SmQ6OfXm.mjs.map +1 -0
  12. package/dist/context/index.cjs +3 -3
  13. package/dist/context/index.d.cts +37 -20
  14. package/dist/context/index.d.cts.map +1 -1
  15. package/dist/context/index.d.mts +37 -20
  16. package/dist/context/index.d.mts.map +1 -1
  17. package/dist/context/index.mjs +3 -3
  18. package/dist/{engine-context-qCVw66U_.cjs → engine-context-CEu21ZZf.cjs} +36 -10
  19. package/dist/{engine-context-DsA9XGVb.mjs → engine-context-D7CWyTsr.mjs} +36 -11
  20. package/dist/engine-context-D7CWyTsr.mjs.map +1 -0
  21. package/dist/{execution-context-CBJxP2B2.mjs → execution-context-C_7IC8er.mjs} +110 -40
  22. package/dist/execution-context-C_7IC8er.mjs.map +1 -0
  23. package/dist/{execution-context-CprxWvYn.cjs → execution-context-DsT6s1du.cjs} +108 -38
  24. package/dist/index.cjs +135 -54
  25. package/dist/index.d.cts.map +1 -1
  26. package/dist/index.d.mts.map +1 -1
  27. package/dist/index.mjs +135 -54
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/storage/index.cjs +1 -1
  30. package/dist/storage/index.d.mts +1 -1
  31. package/dist/storage/index.mjs +1 -1
  32. package/dist/typescript/index.d.mts +1 -1
  33. package/dist/{virtual-BNdKVkRw.cjs → virtual-1hYa9zCy.cjs} +1 -1
  34. package/dist/{virtual-gIlTc3Lj.mjs → virtual-CUgOdyIa.mjs} +2 -2
  35. package/dist/{virtual-gIlTc3Lj.mjs.map → virtual-CUgOdyIa.mjs.map} +1 -1
  36. package/package.json +3 -3
  37. package/dist/base-context-D8a2XGIK.mjs.map +0 -1
  38. package/dist/engine-context-DsA9XGVb.mjs.map +0 -1
  39. package/dist/execution-context-CBJxP2B2.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,23 +1,67 @@
1
- import { t as PowerlinesEngineContext } from "./engine-context-DsA9XGVb.mjs";
1
+ import { t as PowerlinesEngineContext } from "./engine-context-D7CWyTsr.mjs";
2
2
  import { POWERLINES_API_FUNCTIONS } from "@powerlines/core/constants";
3
- import { PQueue } from "@stryke/async/node";
4
3
  import { resolvePackage } from "@stryke/fs/resolve";
5
4
  import { joinPaths } from "@stryke/path/join";
6
5
  import { LogLevelLabel } from "@storm-software/config-tools/types";
7
6
  import { isSet } from "@stryke/type-checks/is-set";
7
+ import { isSetObject } from "@stryke/type-checks/is-set-object";
8
8
  import { isString } from "@stryke/type-checks/is-string";
9
+ import { formatDuration } from "date-fns/formatDuration";
9
10
  import { Worker } from "jest-worker";
11
+ import { cpus } from "node:os";
10
12
  import { Transform } from "node:stream";
11
13
  import { parseArgs } from "node:util";
14
+ import { toArray } from "@stryke/convert/to-array";
15
+ import { isSetString } from "@stryke/type-checks/is-set-string";
12
16
 
17
+ //#region src/_internal/ipc/helpers.ts
18
+ function parseIpcMessage(data) {
19
+ let message;
20
+ if (isSetObject(data)) message = data;
21
+ else if (isString(data)) try {
22
+ const parsed = JSON.parse(data);
23
+ if (isSetObject(parsed)) message = parsed;
24
+ } catch {}
25
+ if (message && isSetString(message.id) && isSetString(message.type) && isSetString(message.executionId) && Number.isInteger(message.executionIndex) && !Number.isNaN(message.timestamp)) return message;
26
+ }
27
+ function parseWriteLogMessagePayload(data) {
28
+ if (isSetString(data?.level) && data?.args) return {
29
+ level: data.level,
30
+ source: isSet(data.source) ? String(data.source) : void 0,
31
+ environment: isSet(data.environment) ? String(data.environment) : void 0,
32
+ plugin: isSet(data.plugin) ? String(data.plugin) : void 0,
33
+ args: toArray(data.args).filter(Boolean)
34
+ };
35
+ throw new Error("Invalid \"write-log\" message payload.");
36
+ }
37
+ function parseUpdateCommandMessagePayload(data) {
38
+ if (isSetString(data?.command)) return { command: data.command };
39
+ throw new Error("Invalid \"update-command\" message payload.");
40
+ }
41
+ function parseUpdateHookMessagePayload(data) {
42
+ if (isSetString(data?.hook) && [
43
+ "pre",
44
+ "post",
45
+ "normal"
46
+ ].includes(data.order)) return {
47
+ hook: data.hook,
48
+ order: data.order
49
+ };
50
+ throw new Error("Invalid \"update-hook\" message payload.");
51
+ }
52
+ function parseUpdatePluginMessagePayload(data) {
53
+ if (isSetString(data?.plugin)) return { plugin: data.plugin };
54
+ throw new Error("Invalid \"update-plugin\" message payload.");
55
+ }
56
+
57
+ //#endregion
13
58
  //#region src/_internal/helpers/worker.ts
14
59
  const RESTARTED = Symbol("powerlines-worker:restarted");
15
60
  /**
16
61
  * Formats the debug address into a string.
17
62
  */
18
63
  const formatDebugAddress = ({ host, port }) => {
19
- if (host) return `${host}:${port}`;
20
- return `${port}`;
64
+ return host ? `${host}:${port}` : `${port}`;
21
65
  };
22
66
  /**
23
67
  * Node.js CLI flags that are not allowed in NODE_OPTIONS and must be
@@ -211,6 +255,22 @@ var Worker$1 = class {
211
255
  delete nodeOptions.max_old_space_size;
212
256
  }
213
257
  const { nodeOptions: formattedNodeOptions, execArgv } = formatNodeOptions(nodeOptions);
258
+ const onHanging = () => {
259
+ const worker = this.#worker;
260
+ if (!worker) return;
261
+ const resolve = resolveRestartPromise;
262
+ createWorker();
263
+ logger(LogLevelLabel.WARN, `Sending SIGTERM signal to static worker due to timeout${timeout ? ` of ${formatDuration({ seconds: timeout / 1e3 })}` : ""}. Subsequent errors may be a result of the worker exiting.`);
264
+ worker.end().then(() => {
265
+ resolve(RESTARTED);
266
+ });
267
+ };
268
+ let hangingTimer = false;
269
+ const onActivity = () => {
270
+ if (hangingTimer) clearTimeout(hangingTimer);
271
+ if (this.options.onActivity) this.options.onActivity();
272
+ hangingTimer = activeTasks > 0 && setTimeout(onHanging, timeout);
273
+ };
214
274
  const createWorker = () => {
215
275
  const workerEnv = {
216
276
  ...process.env,
@@ -222,13 +282,14 @@ var Worker$1 = class {
222
282
  if (!workerEnv.NO_COLOR && !workerEnv.CI && workerEnv.TERM !== "dumb" && (process.stdout.isTTY || process.stderr?.isTTY)) workerEnv.FORCE_COLOR = "1";
223
283
  }
224
284
  this.#worker = new Worker(workerPath, {
285
+ maxRetries: 0,
286
+ numWorkers: cpus().length ?? 3,
225
287
  ...rest,
226
288
  forkOptions: {
227
289
  ...rest.forkOptions,
228
290
  execArgv: [...execArgv, ...rest.forkOptions?.execArgv ?? []],
229
291
  env: workerEnv
230
- },
231
- maxRetries: 0
292
+ }
232
293
  });
233
294
  restartPromise = new Promise((resolve) => {
234
295
  resolveRestartPromise = resolve;
@@ -249,8 +310,47 @@ var Worker$1 = class {
249
310
  process.exit(code ?? 1);
250
311
  }
251
312
  });
252
- worker._child?.on("message", ([, data]) => {
253
- if (data && typeof data === "object" && "type" in data && data.type === "activity") onActivity();
313
+ worker._child?.on("message", (data) => {
314
+ if (isSetObject(data) && data.type === "activity") onActivity();
315
+ else {
316
+ const message = parseIpcMessage(data);
317
+ if (message) {
318
+ logger(LogLevelLabel.TRACE, `Received IPC message from worker: ${JSON.stringify(message)}`);
319
+ switch (message.type) {
320
+ case "write-log":
321
+ if (options.onWriteLog) Promise.resolve(options.onWriteLog({
322
+ ...message,
323
+ type: "write-log",
324
+ payload: parseWriteLogMessagePayload(message.payload)
325
+ }));
326
+ break;
327
+ case "update-command":
328
+ if (options.onUpdateCommand) Promise.resolve(options.onUpdateCommand({
329
+ ...message,
330
+ type: "update-command",
331
+ payload: parseUpdateCommandMessagePayload(message.payload)
332
+ }));
333
+ break;
334
+ case "update-hook":
335
+ if (options.onUpdateHook) Promise.resolve(options.onUpdateHook({
336
+ ...message,
337
+ type: "update-hook",
338
+ payload: parseUpdateHookMessagePayload(message.payload)
339
+ }));
340
+ break;
341
+ case "update-plugin":
342
+ if (options.onUpdatePlugin) Promise.resolve(options.onUpdatePlugin({
343
+ ...message,
344
+ type: "update-plugin",
345
+ payload: parseUpdatePluginMessagePayload(message.payload)
346
+ }));
347
+ break;
348
+ case "activity":
349
+ case void 0:
350
+ default: break;
351
+ }
352
+ }
353
+ }
254
354
  });
255
355
  }
256
356
  let aborted = false;
@@ -270,22 +370,6 @@ var Worker$1 = class {
270
370
  this.#worker.getStderr().pipe(process.stderr);
271
371
  };
272
372
  createWorker();
273
- const onHanging = () => {
274
- const worker = this.#worker;
275
- if (!worker) return;
276
- const resolve = resolveRestartPromise;
277
- createWorker();
278
- logger(LogLevelLabel.WARN, `Sending SIGTERM signal to static worker due to timeout${timeout ? ` of ${timeout / 1e3} seconds` : ""}. Subsequent errors may be a result of the worker exiting.`);
279
- worker.end().then(() => {
280
- resolve(RESTARTED);
281
- });
282
- };
283
- let hangingTimer = false;
284
- const onActivity = () => {
285
- if (hangingTimer) clearTimeout(hangingTimer);
286
- if (this.options.onActivity) this.options.onActivity();
287
- hangingTimer = activeTasks > 0 && setTimeout(onHanging, timeout);
288
- };
289
373
  for (const method of rest.exposedMethods) {
290
374
  if (method.startsWith("_")) continue;
291
375
  this[method] = timeout ? async (...args) => {
@@ -343,10 +427,6 @@ var PowerlinesEngine = class PowerlinesEngine {
343
427
  */
344
428
  #worker;
345
429
  /**
346
- * The queue for managing concurrent execution of Powerlines commands, ensuring that commands are executed in a controlled manner to prevent resource exhaustion and ensure optimal performance.
347
- */
348
- #queue = new PQueue();
349
- /**
350
430
  * Create a new Powerlines Engine instance
351
431
  *
352
432
  * @param options - The options to initialize the context with
@@ -357,6 +437,7 @@ var PowerlinesEngine = class PowerlinesEngine {
357
437
  const packagePath = await resolvePackage("@powerlines/engine");
358
438
  if (!packagePath) throw new Error("Could not resolve `@powerlines/engine` package location.");
359
439
  api.#worker = new Worker$1(joinPaths(packagePath, "./_internal/worker.mjs"), {
440
+ enableSourceMaps: options.mode === "development",
360
441
  exposedMethods: POWERLINES_API_FUNCTIONS,
361
442
  logger: api.context.createLog(null)
362
443
  });
@@ -389,8 +470,8 @@ var PowerlinesEngine = class PowerlinesEngine {
389
470
  this.context.info(" 🏗️ Generating typescript declarations for the Powerlines project");
390
471
  this.context.debug(" Aggregating configuration options for the Powerlines project");
391
472
  inlineConfig.command ??= "types";
392
- await Promise.all(this.#context.executions.map(async (options) => this.#worker.types({
393
- options,
473
+ await Promise.all(this.#context.executions.map(async (execution) => this.#worker.types({
474
+ options: execution.options,
394
475
  config: inlineConfig
395
476
  })));
396
477
  this.context.debug("✔ Powerlines types generation has completed successfully");
@@ -409,10 +490,10 @@ var PowerlinesEngine = class PowerlinesEngine {
409
490
  this.context.info(" 🏗️ Preparing the Powerlines project");
410
491
  this.context.debug("Aggregating configuration options for the Powerlines project");
411
492
  inlineConfig.command ??= "prepare";
412
- await Promise.all(this.#context.executions.map(async (options) => this.#queue.add(async () => this.#worker.prepare({
413
- options,
493
+ await Promise.all(this.#context.executions.map(async (execution) => this.#worker.prepare({
494
+ options: execution.options,
414
495
  config: inlineConfig
415
- }))));
496
+ })));
416
497
  this.context.debug("✔ Powerlines preparation has completed successfully");
417
498
  timer();
418
499
  }
@@ -429,10 +510,10 @@ var PowerlinesEngine = class PowerlinesEngine {
429
510
  const timer = this.context.timer("New");
430
511
  this.context.info(" 🆕 Creating a new Powerlines project");
431
512
  inlineConfig.command ??= "new";
432
- await Promise.all(this.#context.executions.map(async (options) => this.#queue.add(async () => this.#worker.new({
433
- options,
513
+ await Promise.all(this.#context.executions.map(async (execution) => this.#worker.new({
514
+ options: execution.options,
434
515
  config: inlineConfig
435
- }))));
516
+ })));
436
517
  this.context.debug("✔ Powerlines new command completed successfully");
437
518
  timer();
438
519
  }
@@ -449,10 +530,10 @@ var PowerlinesEngine = class PowerlinesEngine {
449
530
  const timer = this.context.timer("Clean");
450
531
  this.context.info(" 🧹 Cleaning the previous Powerlines artifacts");
451
532
  inlineConfig.command ??= "clean";
452
- await Promise.all(this.#context.executions.map(async (options) => this.#queue.add(async () => this.#worker.clean({
453
- options,
533
+ await Promise.all(this.#context.executions.map(async (execution) => this.#worker.clean({
534
+ options: execution.options,
454
535
  config: inlineConfig
455
- }))));
536
+ })));
456
537
  this.context.debug("✔ Powerlines cleaning completed successfully");
457
538
  timer();
458
539
  }
@@ -466,10 +547,10 @@ var PowerlinesEngine = class PowerlinesEngine {
466
547
  const timer = this.context.timer("Lint");
467
548
  this.context.info(" 📝 Linting the Powerlines project");
468
549
  inlineConfig.command ??= "lint";
469
- await Promise.all(this.#context.executions.map(async (options) => this.#queue.add(async () => this.#worker.lint({
470
- options,
550
+ await Promise.all(this.#context.executions.map(async (execution) => this.#worker.lint({
551
+ options: execution.options,
471
552
  config: inlineConfig
472
- }))));
553
+ })));
473
554
  this.context.debug("✔ Powerlines linting completed successfully");
474
555
  timer();
475
556
  }
@@ -486,10 +567,10 @@ var PowerlinesEngine = class PowerlinesEngine {
486
567
  const timer = this.context.timer("Test");
487
568
  this.context.info(" 🧪 Running tests for the Powerlines project");
488
569
  inlineConfig.command ??= "test";
489
- await Promise.all(this.#context.executions.map(async (options) => this.#queue.add(async () => this.#worker.test({
490
- options,
570
+ await Promise.all(this.#context.executions.map(async (execution) => this.#worker.test({
571
+ options: execution.options,
491
572
  config: inlineConfig
492
- }))));
573
+ })));
493
574
  this.context.debug("✔ Powerlines testing completed successfully");
494
575
  timer();
495
576
  }
@@ -505,10 +586,10 @@ var PowerlinesEngine = class PowerlinesEngine {
505
586
  async build(inlineConfig = { command: "build" }) {
506
587
  const timer = this.context.timer("Build");
507
588
  this.context.info(" 📦 Building the Powerlines project");
508
- await Promise.all(this.#context.executions.map(async (options) => this.#queue.add(async () => this.#worker.build({
509
- options,
589
+ await Promise.all(this.#context.executions.map(async (execution) => this.#worker.build({
590
+ options: execution.options,
510
591
  config: inlineConfig
511
- }))));
592
+ })));
512
593
  this.context.debug("✔ Powerlines build completed successfully");
513
594
  timer();
514
595
  }
@@ -522,10 +603,10 @@ var PowerlinesEngine = class PowerlinesEngine {
522
603
  const timer = this.context.timer("Docs");
523
604
  this.context.info(" 📓 Generating documentation for the Powerlines project");
524
605
  inlineConfig.command ??= "docs";
525
- await Promise.all(this.#context.executions.map(async (options) => this.#queue.add(async () => this.#worker.docs({
526
- options,
606
+ await Promise.all(this.#context.executions.map(async (execution) => this.#worker.docs({
607
+ options: execution.options,
527
608
  config: inlineConfig
528
- }))));
609
+ })));
529
610
  this.context.debug("✔ Powerlines documentation generation completed successfully");
530
611
  timer();
531
612
  }
@@ -541,10 +622,10 @@ var PowerlinesEngine = class PowerlinesEngine {
541
622
  const timer = this.context.timer("Deploy");
542
623
  this.context.info(" 🚀 Deploying the Powerlines project");
543
624
  inlineConfig.command ??= "deploy";
544
- await Promise.all(this.#context.executions.map(async (options) => this.#queue.add(async () => this.#worker.deploy({
545
- options,
625
+ await Promise.all(this.#context.executions.map(async (execution) => this.#worker.deploy({
626
+ options: execution.options,
546
627
  config: inlineConfig
547
- }))));
628
+ })));
548
629
  this.context.debug("✔ Powerlines deploy completed successfully");
549
630
  timer();
550
631
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["Worker","#worker","JestWorker","#worker","Worker","#context","#queue"],"sources":["../src/_internal/helpers/worker.ts","../src/index.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type { LogFn } from \"@powerlines/core\";\nimport { LogLevelLabel } from \"@storm-software/config-tools/types\";\nimport { isSet } from \"@stryke/type-checks/is-set\";\nimport { isString } from \"@stryke/type-checks/is-string\";\nimport { Worker as JestWorker } from \"jest-worker\";\nimport type { ChildProcess } from \"node:child_process\";\nimport { Transform } from \"node:stream\";\nimport { parseArgs } from \"node:util\";\n\nconst RESTARTED = Symbol(\"powerlines-worker:restarted\");\n\n/**\n * The debug address is in the form of `[host:]port`. The host is optional.\n */\ninterface DebugAddress {\n host: string | undefined;\n port: number;\n}\n\n/**\n * Formats the debug address into a string.\n */\nconst formatDebugAddress = ({ host, port }: DebugAddress): string => {\n if (host) return `${host}:${port}`;\n return `${port}`;\n};\n\n/**\n * Node.js CLI flags that are not allowed in NODE_OPTIONS and must be\n * passed as direct CLI arguments via execArgv.\n * This set is the difference between all Node.js CLI flags and the ones **not**\n * allowed in NODE_OPTIONS, as listed in the Node.js documentation:\n * https://nodejs.org/api/cli.html#node_optionsoptions\n *\n * It is not exhaustive since not all options make sense for Powerlines (e.g. --test)\n */\nconst EXEC_ARGV_ONLY_OPTIONS = new Set([\n \"experimental-network-inspection\",\n \"experimental-storage-inspection\",\n \"experimental-worker-inspection\",\n \"experimental-inspector-network-resource\"\n]);\n\nfunction formatArg(\n key: string,\n value: string | boolean | undefined\n): string | null {\n if (value === true) {\n return `--${key}`;\n }\n\n if (value) {\n return `--${key}=${\n // Values with spaces need to be quoted. We use JSON.stringify to\n // also escape any nested quotes.\n value.includes(\" \") && !value.startsWith('\"')\n ? JSON.stringify(value)\n : value\n }`;\n }\n\n return null;\n}\n\n/**\n * Tokenizes the arguments string into an array of strings, supporting quoted\n * values and escaped characters.\n * Converted from: https://github.com/nodejs/node/blob/c29d53c5cfc63c5a876084e788d70c9e87bed880/src/node_options.cc#L1401\n *\n * @param input - The arguments string to be tokenized.\n * @returns An array of strings with the tokenized arguments.\n */\nconst tokenizeArgs = (input: string): string[] => {\n const args: string[] = [];\n let isInString = false;\n let willStartNewArg = true;\n\n for (let i = 0; i < input.length; i++) {\n let char = input[i];\n if (char) {\n // Skip any escaped characters in strings.\n if (char === \"\\\\\" && isInString) {\n // Ensure we don't have an escape character at the end.\n if (input.length === i + 1) {\n throw new Error(\"Invalid escape character at the end.\");\n }\n\n // Skip the next character.\n char = input[++i];\n if (!char) {\n continue;\n }\n }\n // If we find a space outside of a string, we should start a new argument.\n else if (char === \" \" && !isInString) {\n willStartNewArg = true;\n continue;\n }\n\n // If we find a quote, we should toggle the string flag.\n else if (char === '\"') {\n isInString = !isInString;\n continue;\n }\n\n // If we're starting a new argument, we should add it to the array.\n if (willStartNewArg) {\n args.push(char);\n willStartNewArg = false;\n }\n // Otherwise, add it to the last argument.\n else {\n args[args.length - 1] += char;\n }\n }\n }\n\n if (isInString) {\n throw new Error(\"Unterminated string\");\n }\n\n return args;\n};\n\n/**\n * Get the node options from the environment variable `NODE_OPTIONS` and returns\n * them as an array of strings.\n *\n * @returns An array of strings with the node options.\n */\nconst getNodeOptionsArgs = () => {\n if (!process.env.NODE_OPTIONS) return [];\n\n return tokenizeArgs(process.env.NODE_OPTIONS);\n};\n\n/**\n * Stringify the arguments to be used in a command line. It will ignore any\n * argument that has a value of `undefined`. Options that are not allowed in\n * NODE_OPTIONS are returned separately as execArgv.\n *\n * @param args - The arguments to be stringified.\n * @returns An object with `nodeOptions` string and `execArgv` array.\n */\nfunction formatNodeOptions(\n args: Record<string, string | boolean | undefined>\n): { nodeOptions: string; execArgv: string[] } {\n const nodeOptionsParts: string[] = [];\n const execArgv: string[] = [];\n\n for (const [key, value] of Object.entries(args)) {\n const formatted = formatArg(key, value);\n if (formatted === null) continue;\n\n if (EXEC_ARGV_ONLY_OPTIONS.has(key)) {\n execArgv.push(formatted);\n } else {\n nodeOptionsParts.push(formatted);\n }\n }\n\n return { nodeOptions: nodeOptionsParts.join(\" \"), execArgv };\n}\n\nexport type NodeOptions = Record<string, string | boolean | undefined>;\n\nconst parseNodeArgs = (args: string[]): NodeOptions => {\n const { values, tokens } = parseArgs({ args, strict: false, tokens: true });\n\n // For the `NODE_OPTIONS`, we support arguments with values without the `=`\n // sign. We need to parse them manually.\n let orphan = null;\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n if (!token) continue;\n\n if (token.kind === \"option-terminator\") {\n break;\n }\n\n // When we encounter an option, if it's value is undefined, we should check\n // to see if the following tokens are positional parameters. If they are,\n // then the option is orphaned, and we can assign it.\n if (token.kind === \"option\") {\n orphan = !isSet(token.value) ? token : null;\n continue;\n }\n\n // If the token isn't a positional one, then we can't assign it to the found\n // orphaned option.\n if (token.kind !== \"positional\") {\n orphan = null;\n continue;\n }\n\n // If we don't have an orphan, then we can skip this token.\n if (!orphan) {\n continue;\n }\n\n // If the token is a positional one, and it has a value, so add it to the\n // values object. If it already exists, append it with a space.\n if (orphan.name in values && isString(values[orphan.name])) {\n values[orphan.name] += ` ${token.value}`;\n } else {\n values[orphan.name] = token.value;\n }\n }\n\n return values;\n};\n\nfunction getParsedNodeOptions(): Record<string, string | boolean | undefined> {\n const args = [...process.execArgv, ...getNodeOptionsArgs()];\n if (args.length === 0) return {};\n\n return parseNodeArgs(args);\n}\n\n/**\n * Get's the debug address from the `NODE_OPTIONS` environment variable. If the\n * address is not found, it returns the default host (`undefined`) and port\n * (`9229`).\n *\n * @returns An object with the host and port of the debug address.\n */\nconst getParsedDebugAddress = (\n address: string | boolean | undefined\n): DebugAddress => {\n if (!address || !isString(address)) {\n return { host: undefined, port: 9229 };\n }\n\n // The address is in the form of `[host:]port`. Let's parse the address.\n if (address.includes(\":\")) {\n const [host, port] = address.split(\":\");\n if (!host || !port) {\n throw new Error(`Invalid debug address: ${address}`);\n }\n\n return { host, port: Number.parseInt(port, 10) };\n }\n\n return { host: undefined, port: Number.parseInt(address, 10) };\n};\n\ntype NodeInspectType = \"inspect\" | \"inspect-brk\" | undefined;\n\n/**\n * Get the debug type from the `NODE_OPTIONS` environment variable.\n */\nfunction getNodeDebugType(nodeOptions: NodeOptions): NodeInspectType {\n if (nodeOptions.inspect) {\n return \"inspect\";\n }\n if (nodeOptions[\"inspect-brk\"] || nodeOptions.inspect_brk) {\n return \"inspect-brk\";\n }\n\n return undefined;\n}\n\nconst cleanupWorkers = (worker: JestWorker) => {\n for (const curWorker of ((worker as any)._workerPool?._workers || []) as {\n _child?: ChildProcess;\n }[]) {\n curWorker._child?.kill(\"SIGINT\");\n }\n};\n\nexport type WorkerOptions = ConstructorParameters<typeof JestWorker>[1] & {\n /**\n * `-1` if not inspectable\n */\n debuggerPortOffset?: number;\n\n /**\n * Whether to enable source maps support in the worker, which can improve the quality of stack traces at the cost of increased memory usage and slower performance. Defaults to `false`.\n */\n enableSourceMaps?: boolean;\n\n /**\n * True if `--max-old-space-size` should not be forwarded to the worker.\n */\n isolatedMemory?: boolean;\n\n /**\n * The maximum time in milliseconds a worker can run before being terminated. Defaults to `0` (no timeout).\n */\n timeout?: number;\n\n /**\n * A callback function that is called when the worker is active.\n */\n onActivity?: () => void;\n\n /**\n * A callback function that is called when the worker activity is aborted.\n */\n onActivityAbort?: () => void;\n\n /**\n * A callback function that is called when the worker is restarted.\n */\n onRestart?: (method: string, args: any[], attempts: number) => void;\n\n /**\n * An array of method names that the worker exposes. These methods will be available on the Worker instance and can be called to execute tasks in the worker process.\n */\n exposedMethods: ReadonlyArray<string>;\n\n /**\n * Whether to use worker threads instead of child processes for the worker implementation. This is an experimental feature and may not be suitable for all use cases. Defaults to `false`.\n */\n enableWorkerThreads?: boolean;\n\n /**\n * A custom logger function that can be used to log messages from the worker. This can be useful for debugging and monitoring the worker's activity. The function should accept a string message as its argument.\n */\n logger: LogFn;\n};\n\nexport class Worker {\n #worker: JestWorker | undefined;\n\n /**\n * Create a new worker instance.\n *\n * @param workerPath - The path to the worker file.\n * @param options - The options for the worker, including exposed methods, timeout, and hooks for activity and restart.\n */\n public constructor(\n protected workerPath: string,\n protected options: WorkerOptions\n ) {\n const {\n timeout,\n onRestart,\n debuggerPortOffset = -1,\n enableSourceMaps = false,\n isolatedMemory = false,\n logger,\n ...rest\n } = this.options;\n\n let restartPromise: Promise<typeof RESTARTED>;\n let resolveRestartPromise: (arg: typeof RESTARTED) => void;\n let activeTasks = 0;\n\n this.#worker = undefined;\n\n // ensure we end workers if they weren't before exit\n process.on(\"exit\", () => {\n this.close();\n });\n\n const nodeOptions = getParsedNodeOptions();\n const originalOptions = { ...nodeOptions };\n delete nodeOptions.inspect;\n delete nodeOptions[\"inspect-brk\"];\n delete nodeOptions.inspect_brk;\n if (debuggerPortOffset !== -1) {\n const nodeDebugType = getNodeDebugType(originalOptions);\n if (nodeDebugType) {\n const debuggerAddress = getParsedDebugAddress(\n originalOptions[nodeDebugType]\n );\n const address: DebugAddress = {\n host: debuggerAddress.host,\n // current process runs on `address.port`\n port:\n debuggerAddress.port === 0\n ? 0\n : debuggerAddress.port + 1 + debuggerPortOffset\n };\n nodeOptions[nodeDebugType] = formatDebugAddress(address);\n }\n }\n\n if (enableSourceMaps) {\n nodeOptions[\"enable-source-maps\"] = true;\n }\n\n if (isolatedMemory) {\n delete nodeOptions[\"max-old-space-size\"];\n delete nodeOptions.max_old_space_size;\n }\n\n const { nodeOptions: formattedNodeOptions, execArgv } =\n formatNodeOptions(nodeOptions);\n\n const createWorker = () => {\n const workerEnv: NodeJS.ProcessEnv = {\n ...process.env,\n ...((rest.forkOptions?.env ?? {}) as any),\n POWERLINES_WORKER: \"true\",\n NODE_OPTIONS: formattedNodeOptions\n };\n\n if (workerEnv.FORCE_COLOR === undefined) {\n // Mirror the enablement heuristic from picocolors (see https://github.com/vercel/next.js/blob/6a40da0345939fe4f7b1ae519b296a86dd103432/packages/next/src/lib/picocolors.ts#L21-L24).\n // Picocolors snapshots `process.env`/`stdout.isTTY` at module load time, so when the worker\n // process bootstraps with piped stdio its own check would disable colors. Re-evaluating the\n // same conditions here lets us opt the worker into color output only when the parent would\n // have seen colors, while still respecting explicit opt-outs like NO_COLOR.\n const supportsColors =\n !workerEnv.NO_COLOR &&\n !workerEnv.CI &&\n workerEnv.TERM !== \"dumb\" &&\n (process.stdout.isTTY || process.stderr?.isTTY);\n\n if (supportsColors) {\n workerEnv.FORCE_COLOR = \"1\";\n }\n }\n\n this.#worker = new JestWorker(workerPath, {\n ...rest,\n forkOptions: {\n ...rest.forkOptions,\n execArgv: [...execArgv, ...(rest.forkOptions?.execArgv ?? [])],\n env: workerEnv\n },\n maxRetries: 0\n });\n restartPromise = new Promise(resolve => {\n resolveRestartPromise = resolve;\n });\n\n /**\n * Jest Worker has two worker types, ChildProcessWorker (uses child_process) and NodeThreadWorker (uses worker_threads)\n * Powerlines uses ChildProcessWorker by default, but it can be switched to NodeThreadWorker with an experimental flag\n *\n * We only want to handle ChildProcessWorker's orphan process issue, so we access the private property \"_child\":\n * https://github.com/facebook/jest/blob/b38d7d345a81d97d1dc3b68b8458b1837fbf19be/packages/jest-worker/src/workers/ChildProcessWorker.ts\n *\n * But this property is not available in NodeThreadWorker, so we need to check if we are using ChildProcessWorker\n */\n if (!rest.enableWorkerThreads) {\n for (const worker of ((this.#worker as any)._workerPool?._workers ||\n []) as {\n _child?: ChildProcess;\n }[]) {\n worker._child?.on(\"exit\", (code, signal) => {\n if ((code || (signal && signal !== \"SIGINT\")) && this.#worker) {\n logger(\n LogLevelLabel.ERROR,\n `Worker exited with code: ${code} and signal: ${signal}`\n );\n\n // if a child process doesn't exit gracefully, we want to bubble up the exit code to the parent process\n process.exit(code ?? 1);\n }\n });\n\n // if a child process emits a particular message, we track that as activity\n // so the parent process can keep track of progress\n worker._child?.on(\"message\", ([, data]: [number, unknown]) => {\n if (\n data &&\n typeof data === \"object\" &&\n \"type\" in data &&\n data.type === \"activity\"\n ) {\n // eslint-disable-next-line ts/no-use-before-define\n onActivity();\n }\n });\n }\n }\n\n let aborted = false;\n const onActivityAbort = () => {\n if (!aborted) {\n this.options.onActivityAbort?.();\n aborted = true;\n }\n };\n\n // Listen to the worker's stdout and stderr, if there's any thing logged, abort the activity first\n const abortActivityStreamOnLog = new Transform({\n transform(_chunk, _encoding, callback) {\n onActivityAbort();\n callback();\n }\n });\n // Stop the activity if there's any output from the worker\n this.#worker.getStdout().pipe(abortActivityStreamOnLog);\n this.#worker.getStderr().pipe(abortActivityStreamOnLog);\n\n // Pipe the worker's stdout and stderr to the parent process\n this.#worker.getStdout().pipe(process.stdout);\n this.#worker.getStderr().pipe(process.stderr);\n };\n createWorker();\n\n const onHanging = () => {\n const worker = this.#worker;\n if (!worker) {\n return;\n }\n\n const resolve = resolveRestartPromise;\n createWorker();\n\n logger(\n LogLevelLabel.WARN,\n `Sending SIGTERM signal to static worker due to timeout${\n timeout ? ` of ${timeout / 1000} seconds` : \"\"\n }. Subsequent errors may be a result of the worker exiting.`\n );\n\n void worker.end().then(() => {\n resolve(RESTARTED);\n });\n };\n\n let hangingTimer: NodeJS.Timeout | false = false;\n\n const onActivity = () => {\n if (hangingTimer) {\n clearTimeout(hangingTimer);\n }\n if (this.options.onActivity) {\n this.options.onActivity();\n }\n\n hangingTimer = activeTasks > 0 && setTimeout(onHanging, timeout);\n };\n\n for (const method of rest.exposedMethods) {\n if (method.startsWith(\"_\")) {\n continue;\n }\n\n (this as any)[method] = timeout\n ? async (...args: any[]) => {\n activeTasks++;\n try {\n let attempts = 0;\n for (;;) {\n onActivity();\n\n const result = await Promise.race([\n // eslint-disable-next-line ts/no-unsafe-call\n (this.#worker as any)[method](\n args.length > 0 && args[0] ? args[0] : {}\n ),\n restartPromise\n ]);\n if (result !== RESTARTED) {\n return result;\n }\n if (onRestart) {\n onRestart(method, args, ++attempts);\n }\n }\n } finally {\n activeTasks--;\n onActivity();\n }\n }\n : // eslint-disable-next-line ts/no-unsafe-call\n (this.#worker as any)[method].bind(this.#worker);\n }\n }\n\n public async end(): ReturnType<JestWorker[\"end\"]> {\n const worker = this.#worker;\n if (!worker) {\n throw new Error(\"Farm is ended, no more calls can be done to it\");\n }\n\n cleanupWorkers(worker);\n this.#worker = undefined;\n return worker.end();\n }\n\n /**\n * Quietly end the worker if it exists\n */\n public close(): void {\n if (this.#worker) {\n cleanupWorkers(this.#worker);\n void this.#worker.end();\n }\n }\n}\n","/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type {\n BuildInlineConfig,\n CleanInlineConfig,\n DeployInlineConfig,\n DocsInlineConfig,\n Engine,\n EngineContext,\n EngineOptions,\n ExecutionWorkerProcess,\n LintInlineConfig,\n NewInlineConfig,\n PrepareInlineConfig,\n TestInlineConfig,\n TypesInlineConfig\n} from \"@powerlines/core\";\nimport { POWERLINES_API_FUNCTIONS } from \"@powerlines/core/constants\";\nimport { PQueue } from \"@stryke/async/node\";\nimport { resolvePackage } from \"@stryke/fs/resolve\";\nimport { joinPaths } from \"@stryke/path/join\";\nimport { PartialKeys } from \"@stryke/types/base\";\nimport { Worker } from \"./_internal/helpers/worker\";\nimport { PowerlinesEngineContext } from \"./context/engine-context\";\n\n/**\n * The Powerlines Engine class\n *\n * @remarks\n * This class is responsible for managing the Powerlines project lifecycle, including initialization, building, and finalization.\n *\n * @public\n */\nexport class PowerlinesEngine implements Engine, AsyncDisposable {\n /**\n * The Powerlines context\n */\n #context: EngineContext;\n\n /**\n * The worker pool for managing child threads\n */\n #worker!: ExecutionWorkerProcess;\n\n /**\n * The queue for managing concurrent execution of Powerlines commands, ensuring that commands are executed in a controlled manner to prevent resource exhaustion and ensure optimal performance.\n */\n #queue = new PQueue();\n\n /**\n * Create a new Powerlines Engine instance\n *\n * @param options - The options to initialize the context with\n * @returns A new instance of the Powerlines Engine\n */\n public static async fromOptions(\n options: EngineOptions\n ): Promise<PowerlinesEngine> {\n const api = new PowerlinesEngine(\n await PowerlinesEngineContext.fromOptions(options)\n );\n\n const packagePath = await resolvePackage(\"@powerlines/engine\");\n if (!packagePath) {\n throw new Error(\n \"Could not resolve `@powerlines/engine` package location.\"\n );\n }\n\n api.#worker = new Worker(joinPaths(packagePath, \"./_internal/worker.mjs\"), {\n exposedMethods: POWERLINES_API_FUNCTIONS,\n logger: api.context.createLog(null)\n }) as unknown as ExecutionWorkerProcess;\n\n return api;\n }\n\n /**\n * The Powerlines context\n */\n public get context(): EngineContext {\n return this.#context;\n }\n\n /**\n * Create a new Powerlines Engine instance\n *\n * @param context - The Powerlines context\n */\n protected constructor(context: EngineContext) {\n this.#context = context;\n }\n\n /**\n * Generate the Powerlines typescript declaration file\n *\n * @remarks\n * This method will only generate the typescript declaration file for the Powerlines project. It is generally recommended to run the full `prepare` command, which will run this method as part of its process.\n *\n * @param inlineConfig - The inline configuration for the types command\n */\n public async types(\n inlineConfig: PartialKeys<\n Omit<TypesInlineConfig, \"configFile\">,\n \"command\"\n > = {\n command: \"types\"\n }\n ) {\n const timer = this.context.timer(\"Types\");\n this.context.info(\n \" 🏗️ Generating typescript declarations for the Powerlines project\"\n );\n\n this.context.debug(\n \" Aggregating configuration options for the Powerlines project\"\n );\n\n inlineConfig.command ??= \"types\";\n await Promise.all(\n this.#context.executions.map(async options =>\n this.#worker.types({\n options,\n config: inlineConfig as TypesInlineConfig\n })\n )\n );\n\n this.context.debug(\n \"✔ Powerlines types generation has completed successfully\"\n );\n timer();\n }\n\n /**\n * Prepare the Powerlines API\n *\n * @remarks\n * This method will prepare the Powerlines API for use, initializing any necessary resources.\n *\n * @param inlineConfig - The inline configuration for the prepare command\n */\n public async prepare(\n inlineConfig:\n | PartialKeys<Omit<PrepareInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<TypesInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<NewInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<CleanInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<BuildInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<LintInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<DocsInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<DeployInlineConfig, \"configFile\">, \"command\"> = {\n command: \"prepare\"\n }\n ) {\n const timer = this.context.timer(\"Prepare\");\n this.context.info(\" 🏗️ Preparing the Powerlines project\");\n\n this.context.debug(\n \"Aggregating configuration options for the Powerlines project\"\n );\n\n inlineConfig.command ??= \"prepare\";\n await Promise.all(\n this.#context.executions.map(async options =>\n this.#queue.add(async () =>\n this.#worker.prepare({\n options,\n config: inlineConfig as PrepareInlineConfig\n })\n )\n )\n );\n\n this.context.debug(\"✔ Powerlines preparation has completed successfully\");\n timer();\n }\n\n /**\n * Create a new Powerlines project\n *\n * @remarks\n * This method will create a new Powerlines project in the current directory.\n *\n * @param inlineConfig - The inline configuration for the new command\n * @returns A promise that resolves when the project has been created\n */\n public async new(inlineConfig: PartialKeys<NewInlineConfig, \"command\">) {\n const timer = this.context.timer(\"New\");\n this.context.info(\" 🆕 Creating a new Powerlines project\");\n\n inlineConfig.command ??= \"new\";\n await Promise.all(\n this.#context.executions.map(async options =>\n this.#queue.add(async () =>\n this.#worker.new({\n options,\n config: inlineConfig as NewInlineConfig\n })\n )\n )\n );\n\n this.context.debug(\"✔ Powerlines new command completed successfully\");\n timer();\n }\n\n /**\n * Clean any previously prepared artifacts\n *\n * @remarks\n * This method will remove the previous Powerlines artifacts from the project.\n *\n * @param inlineConfig - The inline configuration for the clean command\n * @returns A promise that resolves when the clean command has completed\n */\n public async clean(\n inlineConfig:\n | PartialKeys<Omit<CleanInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<PrepareInlineConfig, \"configFile\">, \"command\"> = {\n command: \"clean\"\n }\n ) {\n const timer = this.context.timer(\"Clean\");\n this.context.info(\" 🧹 Cleaning the previous Powerlines artifacts\");\n\n inlineConfig.command ??= \"clean\";\n await Promise.all(\n this.#context.executions.map(async options =>\n this.#queue.add(async () =>\n this.#worker.clean({\n options,\n config: inlineConfig as CleanInlineConfig\n })\n )\n )\n );\n\n this.context.debug(\"✔ Powerlines cleaning completed successfully\");\n timer();\n }\n\n /**\n * Lint the project\n *\n * @param inlineConfig - The inline configuration for the lint command\n * @returns A promise that resolves when the lint command has completed\n */\n public async lint(\n inlineConfig:\n | PartialKeys<Omit<LintInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<BuildInlineConfig, \"configFile\">, \"command\"> = {\n command: \"lint\"\n }\n ) {\n const timer = this.context.timer(\"Lint\");\n this.context.info(\" 📝 Linting the Powerlines project\");\n\n inlineConfig.command ??= \"lint\";\n await Promise.all(\n this.#context.executions.map(async options =>\n this.#queue.add(async () =>\n this.#worker.lint({\n options,\n config: inlineConfig as LintInlineConfig\n })\n )\n )\n );\n\n this.context.debug(\"✔ Powerlines linting completed successfully\");\n timer();\n }\n\n /**\n * Test the project\n *\n * @remarks\n * This method will run the tests for the Powerlines project.\n *\n * @param inlineConfig - The inline configuration for the test command\n * @returns A promise that resolves when the test command has completed\n */\n public async test(\n inlineConfig:\n | PartialKeys<Omit<TestInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<BuildInlineConfig, \"configFile\">, \"command\"> = {\n command: \"test\"\n }\n ) {\n const timer = this.context.timer(\"Test\");\n this.context.info(\" 🧪 Running tests for the Powerlines project\");\n\n inlineConfig.command ??= \"test\";\n await Promise.all(\n this.#context.executions.map(async options =>\n this.#queue.add(async () =>\n this.#worker.test({\n options,\n config: inlineConfig as TestInlineConfig\n })\n )\n )\n );\n\n this.context.debug(\"✔ Powerlines testing completed successfully\");\n timer();\n }\n\n /**\n * Build the project\n *\n * @remarks\n * This method will build the Powerlines project, generating the necessary artifacts.\n *\n * @param inlineConfig - The inline configuration for the build command\n * @returns A promise that resolves when the build command has completed\n */\n public async build(\n inlineConfig: PartialKeys<\n Omit<BuildInlineConfig, \"configFile\">,\n \"command\"\n > = {\n command: \"build\"\n }\n ) {\n const timer = this.context.timer(\"Build\");\n this.context.info(\" 📦 Building the Powerlines project\");\n\n await Promise.all(\n this.#context.executions.map(async options =>\n this.#queue.add(async () =>\n this.#worker.build({\n options,\n config: inlineConfig as BuildInlineConfig\n })\n )\n )\n );\n\n this.context.debug(\"✔ Powerlines build completed successfully\");\n timer();\n }\n\n /**\n * Prepare the documentation for the project\n *\n * @param inlineConfig - The inline configuration for the docs command\n * @returns A promise that resolves when the documentation generation has completed\n */\n public async docs(\n inlineConfig: PartialKeys<\n Omit<DocsInlineConfig, \"configFile\">,\n \"command\"\n > = {\n command: \"docs\"\n }\n ) {\n const timer = this.context.timer(\"Docs\");\n this.context.info(\n \" 📓 Generating documentation for the Powerlines project\"\n );\n\n inlineConfig.command ??= \"docs\";\n\n await Promise.all(\n this.#context.executions.map(async options =>\n this.#queue.add(async () =>\n this.#worker.docs({\n options,\n config: inlineConfig as DocsInlineConfig\n })\n )\n )\n );\n\n this.context.debug(\n \"✔ Powerlines documentation generation completed successfully\"\n );\n timer();\n }\n\n /**\n * Deploy the project source code\n *\n * @remarks\n * This method will prepare and build the Powerlines project, generating the necessary artifacts for the deployment.\n *\n * @param inlineConfig - The inline configuration for the deploy command\n */\n public async deploy(\n inlineConfig: PartialKeys<\n Omit<DeployInlineConfig, \"configFile\">,\n \"command\"\n > = {\n command: \"deploy\"\n }\n ) {\n const timer = this.context.timer(\"Deploy\");\n this.context.info(\" 🚀 Deploying the Powerlines project\");\n\n inlineConfig.command ??= \"deploy\";\n\n await Promise.all(\n this.#context.executions.map(async options =>\n this.#queue.add(async () =>\n this.#worker.deploy({\n options,\n config: inlineConfig as DeployInlineConfig\n })\n )\n )\n );\n\n this.context.debug(\"✔ Powerlines deploy completed successfully\");\n timer();\n }\n\n /**\n * Finalization/cleanup processing for the Powerlines API\n *\n * @remarks\n * This step includes any final processes or clean up required by Powerlines. It will be run after each Powerlines command.\n *\n * @returns A promise that resolves when the finalization process has completed\n */\n public async finalize() {\n const timer = this.context.timer(\"Finalization\");\n this.context.info(\" 🏁 Powerlines finalization processes started\");\n\n this.#worker.close();\n\n this.context.debug(\"✔ Powerlines finalization completed successfully\");\n timer();\n }\n\n async [Symbol.asyncDispose]() {\n return this.finalize();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["Worker","#worker","JestWorker","#worker","Worker","#context"],"sources":["../src/_internal/ipc/helpers.ts","../src/_internal/helpers/worker.ts","../src/index.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { LogLevelLabel } from \"@storm-software/config-tools/types\";\nimport { toArray } from \"@stryke/convert/to-array\";\nimport { isSet } from \"@stryke/type-checks/is-set\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport { isString } from \"@stryke/type-checks/is-string\";\nimport { Serializable } from \"node:worker_threads\";\nimport {\n IpcMessage,\n UpdateCommandMessagePayload,\n UpdateHookMessagePayload,\n UpdatePluginMessagePayload,\n WriteLogMessagePayload\n} from \"./messages\";\n\nexport function parseIpcMessage(data: Serializable): IpcMessage | undefined {\n let message: Record<string, any> | undefined;\n if (isSetObject(data)) {\n message = data;\n } else if (isString(data)) {\n try {\n const parsed = JSON.parse(data);\n if (isSetObject(parsed)) {\n message = parsed;\n }\n } catch {\n // Do nothing\n }\n }\n\n if (\n message &&\n isSetString(message.id) &&\n isSetString(message.type) &&\n isSetString(message.executionId) &&\n Number.isInteger(message.executionIndex) &&\n !Number.isNaN(message.timestamp)\n ) {\n return message as IpcMessage;\n }\n\n return undefined;\n}\n\nexport function parseWriteLogMessagePayload(\n data?: Record<string, any>\n): WriteLogMessagePayload {\n if (isSetString(data?.level) && data?.args) {\n return {\n level: data.level as LogLevelLabel,\n source: isSet(data.source) ? String(data.source) : undefined,\n environment: isSet(data.environment)\n ? String(data.environment)\n : undefined,\n plugin: isSet(data.plugin) ? String(data.plugin) : undefined,\n args: toArray(data.args).filter(Boolean)\n };\n }\n\n throw new Error('Invalid \"write-log\" message payload.');\n}\n\nexport function parseUpdateCommandMessagePayload(\n data?: Record<string, any>\n): UpdateCommandMessagePayload {\n if (isSetString(data?.command)) {\n return {\n command: data.command\n };\n }\n\n throw new Error('Invalid \"update-command\" message payload.');\n}\n\nexport function parseUpdateHookMessagePayload(\n data?: Record<string, any>\n): UpdateHookMessagePayload {\n if (\n isSetString(data?.hook) &&\n [\"pre\", \"post\", \"normal\"].includes(data.order)\n ) {\n return {\n hook: data.hook,\n order: data.order\n };\n }\n\n throw new Error('Invalid \"update-hook\" message payload.');\n}\n\nexport function parseUpdatePluginMessagePayload(\n data?: Record<string, any>\n): UpdatePluginMessagePayload {\n if (isSetString(data?.plugin)) {\n return {\n plugin: data.plugin\n };\n }\n\n throw new Error('Invalid \"update-plugin\" message payload.');\n}\n","/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type { LogFn } from \"@powerlines/core\";\nimport { LogLevelLabel } from \"@storm-software/config-tools/types\";\nimport { isSet } from \"@stryke/type-checks/is-set\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport { isString } from \"@stryke/type-checks/is-string\";\nimport { MaybePromise } from \"@stryke/types/base\";\nimport { formatDuration } from \"date-fns/formatDuration\";\nimport { Worker as JestWorker } from \"jest-worker\";\nimport type { ChildProcess } from \"node:child_process\";\nimport { cpus } from \"node:os\";\nimport { Transform } from \"node:stream\";\nimport { parseArgs } from \"node:util\";\nimport {\n parseIpcMessage,\n parseUpdateCommandMessagePayload,\n parseUpdateHookMessagePayload,\n parseUpdatePluginMessagePayload,\n parseWriteLogMessagePayload\n} from \"../ipc/helpers\";\nimport {\n IpcMessage,\n IpcMessageType,\n UpdateCommandIpcMessage,\n UpdateHookIpcMessage,\n UpdatePluginIpcMessage,\n WriteLogIpcMessage\n} from \"../ipc/messages\";\n\nconst RESTARTED = Symbol(\"powerlines-worker:restarted\");\n\n/**\n * The debug address is in the form of `[host:]port`. The host is optional.\n */\ninterface DebugAddress {\n host?: string;\n port: number;\n}\n\n/**\n * Formats the debug address into a string.\n */\nconst formatDebugAddress = ({ host, port }: DebugAddress): string => {\n return host ? `${host}:${port}` : `${port}`;\n};\n\n/**\n * Node.js CLI flags that are not allowed in NODE_OPTIONS and must be\n * passed as direct CLI arguments via execArgv.\n * This set is the difference between all Node.js CLI flags and the ones **not**\n * allowed in NODE_OPTIONS, as listed in the Node.js documentation:\n * https://nodejs.org/api/cli.html#node_optionsoptions\n *\n * It is not exhaustive since not all options make sense for Powerlines (e.g. --test)\n */\nconst EXEC_ARGV_ONLY_OPTIONS = new Set([\n \"experimental-network-inspection\",\n \"experimental-storage-inspection\",\n \"experimental-worker-inspection\",\n \"experimental-inspector-network-resource\"\n]);\n\nfunction formatArg(\n key: string,\n value: string | boolean | undefined\n): string | null {\n if (value === true) {\n return `--${key}`;\n }\n\n if (value) {\n return `--${key}=${\n // Values with spaces need to be quoted. We use JSON.stringify to\n // also escape any nested quotes.\n value.includes(\" \") && !value.startsWith('\"')\n ? JSON.stringify(value)\n : value\n }`;\n }\n\n return null;\n}\n\n/**\n * Tokenizes the arguments string into an array of strings, supporting quoted\n * values and escaped characters.\n * Converted from: https://github.com/nodejs/node/blob/c29d53c5cfc63c5a876084e788d70c9e87bed880/src/node_options.cc#L1401\n *\n * @param input - The arguments string to be tokenized.\n * @returns An array of strings with the tokenized arguments.\n */\nconst tokenizeArgs = (input: string): string[] => {\n const args: string[] = [];\n let isInString = false;\n let willStartNewArg = true;\n\n for (let i = 0; i < input.length; i++) {\n let char = input[i];\n if (char) {\n // Skip any escaped characters in strings.\n if (char === \"\\\\\" && isInString) {\n // Ensure we don't have an escape character at the end.\n if (input.length === i + 1) {\n throw new Error(\"Invalid escape character at the end.\");\n }\n\n // Skip the next character.\n char = input[++i];\n if (!char) {\n continue;\n }\n }\n // If we find a space outside of a string, we should start a new argument.\n else if (char === \" \" && !isInString) {\n willStartNewArg = true;\n continue;\n }\n\n // If we find a quote, we should toggle the string flag.\n else if (char === '\"') {\n isInString = !isInString;\n continue;\n }\n\n // If we're starting a new argument, we should add it to the array.\n if (willStartNewArg) {\n args.push(char);\n willStartNewArg = false;\n }\n // Otherwise, add it to the last argument.\n else {\n args[args.length - 1] += char;\n }\n }\n }\n\n if (isInString) {\n throw new Error(\"Unterminated string\");\n }\n\n return args;\n};\n\n/**\n * Get the node options from the environment variable `NODE_OPTIONS` and returns\n * them as an array of strings.\n *\n * @returns An array of strings with the node options.\n */\nconst getNodeOptionsArgs = () => {\n if (!process.env.NODE_OPTIONS) return [];\n\n return tokenizeArgs(process.env.NODE_OPTIONS);\n};\n\n/**\n * Stringify the arguments to be used in a command line. It will ignore any\n * argument that has a value of `undefined`. Options that are not allowed in\n * NODE_OPTIONS are returned separately as execArgv.\n *\n * @param args - The arguments to be stringified.\n * @returns An object with `nodeOptions` string and `execArgv` array.\n */\nfunction formatNodeOptions(\n args: Record<string, string | boolean | undefined>\n): { nodeOptions: string; execArgv: string[] } {\n const nodeOptionsParts: string[] = [];\n const execArgv: string[] = [];\n\n for (const [key, value] of Object.entries(args)) {\n const formatted = formatArg(key, value);\n if (formatted === null) continue;\n\n if (EXEC_ARGV_ONLY_OPTIONS.has(key)) {\n execArgv.push(formatted);\n } else {\n nodeOptionsParts.push(formatted);\n }\n }\n\n return { nodeOptions: nodeOptionsParts.join(\" \"), execArgv };\n}\n\nexport type NodeOptions = Record<string, string | boolean | undefined>;\n\nconst parseNodeArgs = (args: string[]): NodeOptions => {\n const { values, tokens } = parseArgs({ args, strict: false, tokens: true });\n\n // For the `NODE_OPTIONS`, we support arguments with values without the `=`\n // sign. We need to parse them manually.\n let orphan = null;\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n if (!token) continue;\n\n if (token.kind === \"option-terminator\") {\n break;\n }\n\n // When we encounter an option, if it's value is undefined, we should check\n // to see if the following tokens are positional parameters. If they are,\n // then the option is orphaned, and we can assign it.\n if (token.kind === \"option\") {\n orphan = !isSet(token.value) ? token : null;\n continue;\n }\n\n // If the token isn't a positional one, then we can't assign it to the found\n // orphaned option.\n if (token.kind !== \"positional\") {\n orphan = null;\n continue;\n }\n\n // If we don't have an orphan, then we can skip this token.\n if (!orphan) {\n continue;\n }\n\n // If the token is a positional one, and it has a value, so add it to the\n // values object. If it already exists, append it with a space.\n if (orphan.name in values && isString(values[orphan.name])) {\n values[orphan.name] += ` ${token.value}`;\n } else {\n values[orphan.name] = token.value;\n }\n }\n\n return values;\n};\n\nfunction getParsedNodeOptions(): Record<string, string | boolean | undefined> {\n const args = [...process.execArgv, ...getNodeOptionsArgs()];\n if (args.length === 0) return {};\n\n return parseNodeArgs(args);\n}\n\n/**\n * Get's the debug address from the `NODE_OPTIONS` environment variable. If the\n * address is not found, it returns the default host (`undefined`) and port\n * (`9229`).\n *\n * @returns An object with the host and port of the debug address.\n */\nconst getParsedDebugAddress = (\n address: string | boolean | undefined\n): DebugAddress => {\n if (!address || !isString(address)) {\n return { host: undefined, port: 9229 };\n }\n\n // The address is in the form of `[host:]port`. Let's parse the address.\n if (address.includes(\":\")) {\n const [host, port] = address.split(\":\");\n if (!host || !port) {\n throw new Error(`Invalid debug address: ${address}`);\n }\n\n return { host, port: Number.parseInt(port, 10) };\n }\n\n return { host: undefined, port: Number.parseInt(address, 10) };\n};\n\ntype NodeInspectType = \"inspect\" | \"inspect-brk\" | undefined;\n\n/**\n * Get the debug type from the `NODE_OPTIONS` environment variable.\n */\nfunction getNodeDebugType(nodeOptions: NodeOptions): NodeInspectType {\n if (nodeOptions.inspect) {\n return \"inspect\";\n }\n if (nodeOptions[\"inspect-brk\"] || nodeOptions.inspect_brk) {\n return \"inspect-brk\";\n }\n\n return undefined;\n}\n\nconst cleanupWorkers = (worker: JestWorker) => {\n for (const curWorker of ((worker as any)._workerPool?._workers || []) as {\n _child?: ChildProcess;\n }[]) {\n curWorker._child?.kill(\"SIGINT\");\n }\n};\n\nexport type WorkerOptions = ConstructorParameters<typeof JestWorker>[1] & {\n /**\n * `-1` if not inspectable\n */\n debuggerPortOffset?: number;\n\n /**\n * Whether to enable source maps support in the worker, which can improve the quality of stack traces at the cost of increased memory usage and slower performance. Defaults to `false`.\n */\n enableSourceMaps?: boolean;\n\n /**\n * True if `--max-old-space-size` should not be forwarded to the worker.\n */\n isolatedMemory?: boolean;\n\n /**\n * The maximum time in milliseconds a worker can run before being terminated. Defaults to `0` (no timeout).\n */\n timeout?: number;\n\n /**\n * A callback function that is called when the worker is active.\n */\n onActivity?: () => void;\n\n /**\n * A callback function that is called when the worker activity is aborted.\n */\n onActivityAbort?: () => void;\n\n /**\n * A callback function that is called when the worker is restarted.\n */\n onRestart?: (method: string, args: any[], attempts: number) => void;\n\n /**\n * An array of method names that the worker exposes. These methods will be available on the Worker instance and can be called to execute tasks in the worker process.\n */\n exposedMethods: ReadonlyArray<string>;\n\n /**\n * Whether to use worker threads instead of child processes for the worker implementation. This is an experimental feature and may not be suitable for all use cases. Defaults to `false`.\n */\n enableWorkerThreads?: boolean;\n\n /**\n * A custom logger function that can be used to log messages from the worker. This can be useful for debugging and monitoring the worker's activity. The function should accept a string message as its argument.\n */\n logger: LogFn;\n\n /**\n * A callback function that is called when the worker sends a log message.\n */\n onWriteLog?: (payload: WriteLogIpcMessage) => MaybePromise<void>;\n\n /**\n * A callback function that is called when the worker sends an update command message.\n */\n onUpdateCommand?: (payload: UpdateCommandIpcMessage) => MaybePromise<void>;\n\n /**\n * A callback function that is called when the worker sends an update hook message.\n */\n onUpdateHook?: (payload: UpdateHookIpcMessage) => MaybePromise<void>;\n\n /**\n * A callback function that is called when the worker sends an update plugin message.\n */\n onUpdatePlugin?: (payload: UpdatePluginIpcMessage) => MaybePromise<void>;\n};\n\nexport class Worker {\n #worker: JestWorker | undefined;\n\n /**\n * Create a new worker instance.\n *\n * @param workerPath - The path to the worker file.\n * @param options - The options for the worker, including exposed methods, timeout, and hooks for activity and restart.\n */\n public constructor(\n protected workerPath: string,\n protected options: WorkerOptions\n ) {\n const {\n timeout,\n onRestart,\n debuggerPortOffset = -1,\n enableSourceMaps = false,\n isolatedMemory = false,\n logger,\n ...rest\n } = this.options;\n\n let restartPromise: Promise<typeof RESTARTED>;\n let resolveRestartPromise: (arg: typeof RESTARTED) => void;\n let activeTasks = 0;\n\n this.#worker = undefined;\n\n // ensure we end workers if they weren't before exit\n process.on(\"exit\", () => {\n this.close();\n });\n\n const nodeOptions = getParsedNodeOptions();\n const originalOptions = { ...nodeOptions };\n delete nodeOptions.inspect;\n delete nodeOptions[\"inspect-brk\"];\n delete nodeOptions.inspect_brk;\n if (debuggerPortOffset !== -1) {\n const nodeDebugType = getNodeDebugType(originalOptions);\n if (nodeDebugType) {\n const debuggerAddress = getParsedDebugAddress(\n originalOptions[nodeDebugType]\n );\n const address: DebugAddress = {\n host: debuggerAddress.host,\n // current process runs on `address.port`\n port:\n debuggerAddress.port === 0\n ? 0\n : debuggerAddress.port + 1 + debuggerPortOffset\n };\n nodeOptions[nodeDebugType] = formatDebugAddress(address);\n }\n }\n\n if (enableSourceMaps) {\n nodeOptions[\"enable-source-maps\"] = true;\n }\n\n if (isolatedMemory) {\n delete nodeOptions[\"max-old-space-size\"];\n delete nodeOptions.max_old_space_size;\n }\n\n const { nodeOptions: formattedNodeOptions, execArgv } =\n formatNodeOptions(nodeOptions);\n\n const onHanging = () => {\n const worker = this.#worker;\n if (!worker) {\n return;\n }\n\n const resolve = resolveRestartPromise;\n // eslint-disable-next-line ts/no-use-before-define\n createWorker();\n\n logger(\n LogLevelLabel.WARN,\n `Sending SIGTERM signal to static worker due to timeout${\n timeout ? ` of ${formatDuration({ seconds: timeout / 1000 })}` : \"\"\n }. Subsequent errors may be a result of the worker exiting.`\n );\n\n void worker.end().then(() => {\n resolve(RESTARTED);\n });\n };\n\n let hangingTimer: NodeJS.Timeout | false = false;\n\n const onActivity = () => {\n if (hangingTimer) {\n clearTimeout(hangingTimer);\n }\n if (this.options.onActivity) {\n this.options.onActivity();\n }\n\n hangingTimer = activeTasks > 0 && setTimeout(onHanging, timeout);\n };\n\n const createWorker = () => {\n const workerEnv: NodeJS.ProcessEnv = {\n ...process.env,\n ...((rest.forkOptions?.env ?? {}) as any),\n POWERLINES_WORKER: \"true\",\n NODE_OPTIONS: formattedNodeOptions\n };\n\n if (workerEnv.FORCE_COLOR === undefined) {\n // Mirror the enablement heuristic from picocolors (see https://github.com/vercel/next.js/blob/6a40da0345939fe4f7b1ae519b296a86dd103432/packages/next/src/lib/picocolors.ts#L21-L24).\n // Picocolors snapshots `process.env`/`stdout.isTTY` at module load time, so when the worker\n // process bootstraps with piped stdio its own check would disable colors. Re-evaluating the\n // same conditions here lets us opt the worker into color output only when the parent would\n // have seen colors, while still respecting explicit opt-outs like NO_COLOR.\n const supportsColors =\n !workerEnv.NO_COLOR &&\n !workerEnv.CI &&\n workerEnv.TERM !== \"dumb\" &&\n (process.stdout.isTTY || process.stderr?.isTTY);\n\n if (supportsColors) {\n workerEnv.FORCE_COLOR = \"1\";\n }\n }\n\n this.#worker = new JestWorker(workerPath, {\n maxRetries: 0,\n numWorkers: cpus().length ?? 3,\n ...rest,\n forkOptions: {\n ...rest.forkOptions,\n execArgv: [...execArgv, ...(rest.forkOptions?.execArgv ?? [])],\n env: workerEnv\n }\n });\n restartPromise = new Promise(resolve => {\n resolveRestartPromise = resolve;\n });\n\n /**\n * Jest Worker has two worker types, ChildProcessWorker (uses child_process) and NodeThreadWorker (uses worker_threads)\n * Powerlines uses ChildProcessWorker by default, but it can be switched to NodeThreadWorker with an experimental flag\n *\n * We only want to handle ChildProcessWorker's orphan process issue, so we access the private property \"_child\":\n * https://github.com/facebook/jest/blob/b38d7d345a81d97d1dc3b68b8458b1837fbf19be/packages/jest-worker/src/workers/ChildProcessWorker.ts\n *\n * But this property is not available in NodeThreadWorker, so we need to check if we are using ChildProcessWorker\n */\n if (!rest.enableWorkerThreads) {\n for (const worker of ((this.#worker as any)._workerPool?._workers ||\n []) as {\n _child?: ChildProcess;\n }[]) {\n worker._child?.on(\"exit\", (code, signal) => {\n if ((code || (signal && signal !== \"SIGINT\")) && this.#worker) {\n logger(\n LogLevelLabel.ERROR,\n `Worker exited with code: ${code} and signal: ${signal}`\n );\n\n // if a child process doesn't exit gracefully, we want to bubble up the exit code to the parent process\n process.exit(code ?? 1);\n }\n });\n\n // if a child process emits a particular message, we track that as activity\n // so the parent process can keep track of progress\n worker._child?.on(\"message\", data => {\n if (\n isSetObject(data) &&\n (data as IpcMessage).type === IpcMessageType.ACTIVITY\n ) {\n onActivity();\n } else {\n const message = parseIpcMessage(data);\n if (message) {\n logger(\n LogLevelLabel.TRACE,\n `Received IPC message from worker: ${JSON.stringify(message)}`\n );\n\n switch (message.type) {\n case IpcMessageType.WRITE_LOG:\n if (options.onWriteLog) {\n void Promise.resolve(\n options.onWriteLog({\n ...message,\n type: IpcMessageType.WRITE_LOG,\n payload: parseWriteLogMessagePayload(message.payload)\n })\n );\n }\n break;\n\n case IpcMessageType.UPDATE_COMMAND:\n if (options.onUpdateCommand) {\n void Promise.resolve(\n options.onUpdateCommand({\n ...message,\n type: IpcMessageType.UPDATE_COMMAND,\n payload: parseUpdateCommandMessagePayload(\n message.payload\n )\n })\n );\n }\n break;\n\n case IpcMessageType.UPDATE_HOOK:\n if (options.onUpdateHook) {\n void Promise.resolve(\n options.onUpdateHook({\n ...message,\n type: IpcMessageType.UPDATE_HOOK,\n payload: parseUpdateHookMessagePayload(\n message.payload\n )\n })\n );\n }\n break;\n\n case IpcMessageType.UPDATE_PLUGIN:\n if (options.onUpdatePlugin) {\n void Promise.resolve(\n options.onUpdatePlugin({\n ...message,\n type: IpcMessageType.UPDATE_PLUGIN,\n payload: parseUpdatePluginMessagePayload(\n message.payload\n )\n })\n );\n }\n break;\n\n case IpcMessageType.ACTIVITY:\n case undefined:\n default: {\n break;\n }\n }\n }\n }\n });\n }\n }\n\n let aborted = false;\n const onActivityAbort = () => {\n if (!aborted) {\n this.options.onActivityAbort?.();\n aborted = true;\n }\n };\n\n // Listen to the worker's stdout and stderr, if there's any thing logged, abort the activity first\n const abortActivityStreamOnLog = new Transform({\n transform(_chunk, _encoding, callback) {\n onActivityAbort();\n callback();\n }\n });\n // Stop the activity if there's any output from the worker\n this.#worker.getStdout().pipe(abortActivityStreamOnLog);\n this.#worker.getStderr().pipe(abortActivityStreamOnLog);\n\n // Pipe the worker's stdout and stderr to the parent process\n this.#worker.getStdout().pipe(process.stdout);\n this.#worker.getStderr().pipe(process.stderr);\n };\n createWorker();\n\n for (const method of rest.exposedMethods) {\n if (method.startsWith(\"_\")) {\n continue;\n }\n\n (this as any)[method] = timeout\n ? async (...args: any[]) => {\n activeTasks++;\n try {\n let attempts = 0;\n for (;;) {\n onActivity();\n\n const result = await Promise.race([\n // eslint-disable-next-line ts/no-unsafe-call\n (this.#worker as any)[method](\n args.length > 0 && args[0] ? args[0] : {}\n ),\n restartPromise\n ]);\n if (result !== RESTARTED) {\n return result;\n }\n if (onRestart) {\n onRestart(method, args, ++attempts);\n }\n }\n } finally {\n activeTasks--;\n onActivity();\n }\n }\n : // eslint-disable-next-line ts/no-unsafe-call\n (this.#worker as any)[method].bind(this.#worker);\n }\n }\n\n public async end(): ReturnType<JestWorker[\"end\"]> {\n const worker = this.#worker;\n if (!worker) {\n throw new Error(\"Farm is ended, no more calls can be done to it\");\n }\n\n cleanupWorkers(worker);\n this.#worker = undefined;\n return worker.end();\n }\n\n /**\n * Quietly end the worker if it exists\n */\n public close(): void {\n if (this.#worker) {\n cleanupWorkers(this.#worker);\n void this.#worker.end();\n }\n }\n}\n","/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type {\n BuildInlineConfig,\n CleanInlineConfig,\n DeployInlineConfig,\n DocsInlineConfig,\n Engine,\n EngineContext,\n EngineOptions,\n ExecutionWorkerProcess,\n LintInlineConfig,\n NewInlineConfig,\n PrepareInlineConfig,\n TestInlineConfig,\n TypesInlineConfig\n} from \"@powerlines/core\";\nimport { POWERLINES_API_FUNCTIONS } from \"@powerlines/core/constants\";\nimport { resolvePackage } from \"@stryke/fs/resolve\";\nimport { joinPaths } from \"@stryke/path/join\";\nimport { PartialKeys } from \"@stryke/types/base\";\nimport { Worker } from \"./_internal/helpers/worker\";\nimport { PowerlinesEngineContext } from \"./context/engine-context\";\n\n/**\n * The Powerlines Engine class\n *\n * @remarks\n * This class is responsible for managing the Powerlines project lifecycle, including initialization, building, and finalization.\n *\n * @public\n */\nexport class PowerlinesEngine implements Engine, AsyncDisposable {\n /**\n * The Powerlines context\n */\n #context: EngineContext;\n\n /**\n * The worker pool for managing child threads\n */\n #worker!: ExecutionWorkerProcess;\n\n /**\n * Create a new Powerlines Engine instance\n *\n * @param options - The options to initialize the context with\n * @returns A new instance of the Powerlines Engine\n */\n public static async fromOptions(\n options: EngineOptions\n ): Promise<PowerlinesEngine> {\n const api = new PowerlinesEngine(\n await PowerlinesEngineContext.fromOptions(options)\n );\n\n const packagePath = await resolvePackage(\"@powerlines/engine\");\n if (!packagePath) {\n throw new Error(\n \"Could not resolve `@powerlines/engine` package location.\"\n );\n }\n\n api.#worker = new Worker(joinPaths(packagePath, \"./_internal/worker.mjs\"), {\n enableSourceMaps: options.mode === \"development\",\n exposedMethods: POWERLINES_API_FUNCTIONS,\n logger: api.context.createLog(null)\n }) as unknown as ExecutionWorkerProcess;\n\n return api;\n }\n\n /**\n * The Powerlines context\n */\n public get context(): EngineContext {\n return this.#context;\n }\n\n /**\n * Create a new Powerlines Engine instance\n *\n * @param context - The Powerlines context\n */\n protected constructor(context: EngineContext) {\n this.#context = context;\n }\n\n /**\n * Generate the Powerlines typescript declaration file\n *\n * @remarks\n * This method will only generate the typescript declaration file for the Powerlines project. It is generally recommended to run the full `prepare` command, which will run this method as part of its process.\n *\n * @param inlineConfig - The inline configuration for the types command\n */\n public async types(\n inlineConfig: PartialKeys<\n Omit<TypesInlineConfig, \"configFile\">,\n \"command\"\n > = {\n command: \"types\"\n }\n ) {\n const timer = this.context.timer(\"Types\");\n this.context.info(\n \" 🏗️ Generating typescript declarations for the Powerlines project\"\n );\n\n this.context.debug(\n \" Aggregating configuration options for the Powerlines project\"\n );\n\n inlineConfig.command ??= \"types\";\n await Promise.all(\n this.#context.executions.map(async execution =>\n this.#worker.types({\n options: execution.options,\n config: inlineConfig as TypesInlineConfig\n })\n )\n );\n\n this.context.debug(\n \"✔ Powerlines types generation has completed successfully\"\n );\n timer();\n }\n\n /**\n * Prepare the Powerlines API\n *\n * @remarks\n * This method will prepare the Powerlines API for use, initializing any necessary resources.\n *\n * @param inlineConfig - The inline configuration for the prepare command\n */\n public async prepare(\n inlineConfig:\n | PartialKeys<Omit<PrepareInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<TypesInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<NewInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<CleanInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<BuildInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<LintInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<DocsInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<DeployInlineConfig, \"configFile\">, \"command\"> = {\n command: \"prepare\"\n }\n ) {\n const timer = this.context.timer(\"Prepare\");\n this.context.info(\" 🏗️ Preparing the Powerlines project\");\n\n this.context.debug(\n \"Aggregating configuration options for the Powerlines project\"\n );\n\n inlineConfig.command ??= \"prepare\";\n await Promise.all(\n this.#context.executions.map(async execution =>\n this.#worker.prepare({\n options: execution.options,\n config: inlineConfig as PrepareInlineConfig\n })\n )\n );\n\n this.context.debug(\"✔ Powerlines preparation has completed successfully\");\n timer();\n }\n\n /**\n * Create a new Powerlines project\n *\n * @remarks\n * This method will create a new Powerlines project in the current directory.\n *\n * @param inlineConfig - The inline configuration for the new command\n * @returns A promise that resolves when the project has been created\n */\n public async new(inlineConfig: PartialKeys<NewInlineConfig, \"command\">) {\n const timer = this.context.timer(\"New\");\n this.context.info(\" 🆕 Creating a new Powerlines project\");\n\n inlineConfig.command ??= \"new\";\n await Promise.all(\n this.#context.executions.map(async execution =>\n this.#worker.new({\n options: execution.options,\n config: inlineConfig as NewInlineConfig\n })\n )\n );\n\n this.context.debug(\"✔ Powerlines new command completed successfully\");\n timer();\n }\n\n /**\n * Clean any previously prepared artifacts\n *\n * @remarks\n * This method will remove the previous Powerlines artifacts from the project.\n *\n * @param inlineConfig - The inline configuration for the clean command\n * @returns A promise that resolves when the clean command has completed\n */\n public async clean(\n inlineConfig:\n | PartialKeys<Omit<CleanInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<PrepareInlineConfig, \"configFile\">, \"command\"> = {\n command: \"clean\"\n }\n ) {\n const timer = this.context.timer(\"Clean\");\n this.context.info(\" 🧹 Cleaning the previous Powerlines artifacts\");\n\n inlineConfig.command ??= \"clean\";\n await Promise.all(\n this.#context.executions.map(async execution =>\n this.#worker.clean({\n options: execution.options,\n config: inlineConfig as CleanInlineConfig\n })\n )\n );\n\n this.context.debug(\"✔ Powerlines cleaning completed successfully\");\n timer();\n }\n\n /**\n * Lint the project\n *\n * @param inlineConfig - The inline configuration for the lint command\n * @returns A promise that resolves when the lint command has completed\n */\n public async lint(\n inlineConfig:\n | PartialKeys<Omit<LintInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<BuildInlineConfig, \"configFile\">, \"command\"> = {\n command: \"lint\"\n }\n ) {\n const timer = this.context.timer(\"Lint\");\n this.context.info(\" 📝 Linting the Powerlines project\");\n\n inlineConfig.command ??= \"lint\";\n await Promise.all(\n this.#context.executions.map(async execution =>\n this.#worker.lint({\n options: execution.options,\n config: inlineConfig as LintInlineConfig\n })\n )\n );\n\n this.context.debug(\"✔ Powerlines linting completed successfully\");\n timer();\n }\n\n /**\n * Test the project\n *\n * @remarks\n * This method will run the tests for the Powerlines project.\n *\n * @param inlineConfig - The inline configuration for the test command\n * @returns A promise that resolves when the test command has completed\n */\n public async test(\n inlineConfig:\n | PartialKeys<Omit<TestInlineConfig, \"configFile\">, \"command\">\n | PartialKeys<Omit<BuildInlineConfig, \"configFile\">, \"command\"> = {\n command: \"test\"\n }\n ) {\n const timer = this.context.timer(\"Test\");\n this.context.info(\" 🧪 Running tests for the Powerlines project\");\n\n inlineConfig.command ??= \"test\";\n await Promise.all(\n this.#context.executions.map(async execution =>\n this.#worker.test({\n options: execution.options,\n config: inlineConfig as TestInlineConfig\n })\n )\n );\n\n this.context.debug(\"✔ Powerlines testing completed successfully\");\n timer();\n }\n\n /**\n * Build the project\n *\n * @remarks\n * This method will build the Powerlines project, generating the necessary artifacts.\n *\n * @param inlineConfig - The inline configuration for the build command\n * @returns A promise that resolves when the build command has completed\n */\n public async build(\n inlineConfig: PartialKeys<\n Omit<BuildInlineConfig, \"configFile\">,\n \"command\"\n > = {\n command: \"build\"\n }\n ) {\n const timer = this.context.timer(\"Build\");\n this.context.info(\" 📦 Building the Powerlines project\");\n\n await Promise.all(\n this.#context.executions.map(async execution =>\n this.#worker.build({\n options: execution.options,\n config: inlineConfig as BuildInlineConfig\n })\n )\n );\n\n this.context.debug(\"✔ Powerlines build completed successfully\");\n timer();\n }\n\n /**\n * Prepare the documentation for the project\n *\n * @param inlineConfig - The inline configuration for the docs command\n * @returns A promise that resolves when the documentation generation has completed\n */\n public async docs(\n inlineConfig: PartialKeys<\n Omit<DocsInlineConfig, \"configFile\">,\n \"command\"\n > = {\n command: \"docs\"\n }\n ) {\n const timer = this.context.timer(\"Docs\");\n this.context.info(\n \" 📓 Generating documentation for the Powerlines project\"\n );\n\n inlineConfig.command ??= \"docs\";\n\n await Promise.all(\n this.#context.executions.map(async execution =>\n this.#worker.docs({\n options: execution.options,\n config: inlineConfig as DocsInlineConfig\n })\n )\n );\n\n this.context.debug(\n \"✔ Powerlines documentation generation completed successfully\"\n );\n timer();\n }\n\n /**\n * Deploy the project source code\n *\n * @remarks\n * This method will prepare and build the Powerlines project, generating the necessary artifacts for the deployment.\n *\n * @param inlineConfig - The inline configuration for the deploy command\n */\n public async deploy(\n inlineConfig: PartialKeys<\n Omit<DeployInlineConfig, \"configFile\">,\n \"command\"\n > = {\n command: \"deploy\"\n }\n ) {\n const timer = this.context.timer(\"Deploy\");\n this.context.info(\" 🚀 Deploying the Powerlines project\");\n\n inlineConfig.command ??= \"deploy\";\n\n await Promise.all(\n this.#context.executions.map(async execution =>\n this.#worker.deploy({\n options: execution.options,\n config: inlineConfig as DeployInlineConfig\n })\n )\n );\n\n this.context.debug(\"✔ Powerlines deploy completed successfully\");\n timer();\n }\n\n /**\n * Finalization/cleanup processing for the Powerlines API\n *\n * @remarks\n * This step includes any final processes or clean up required by Powerlines. It will be run after each Powerlines command.\n *\n * @returns A promise that resolves when the finalization process has completed\n */\n public async finalize() {\n const timer = this.context.timer(\"Finalization\");\n this.context.info(\" 🏁 Powerlines finalization processes started\");\n\n this.#worker.close();\n\n this.context.debug(\"✔ Powerlines finalization completed successfully\");\n timer();\n }\n\n async [Symbol.asyncDispose]() {\n return this.finalize();\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_virtual = require('../virtual-BNdKVkRw.cjs');
2
+ const require_virtual = require('../virtual-1hYa9zCy.cjs');
3
3
 
4
4
  exports.BaseStorageAdapter = require_virtual.BaseStorageAdapter;
5
5
  exports.FileSystemStorageAdapter = require_virtual.FileSystemStorageAdapter;
@@ -1,5 +1,5 @@
1
- import { writeFile, writeFileSync } from "@stryke/fs/write-file";
2
1
  import { Context, StorageAdapter, StoragePreset } from "@powerlines/core";
2
+ import { writeFile, writeFileSync } from "@stryke/fs/write-file";
3
3
  import { MaybePromise } from "@stryke/types/base";
4
4
 
5
5
  //#region src/storage/base.d.ts
@@ -1,3 +1,3 @@
1
- import { a as isFileError, i as ignoreNotfound, n as FileSystemStorageAdapter, o as BaseStorageAdapter, r as ignoreExists, t as VirtualStorageAdapter } from "../virtual-gIlTc3Lj.mjs";
1
+ import { a as isFileError, i as ignoreNotfound, n as FileSystemStorageAdapter, o as BaseStorageAdapter, r as ignoreExists, t as VirtualStorageAdapter } from "../virtual-CUgOdyIa.mjs";
2
2
 
3
3
  export { BaseStorageAdapter, FileSystemStorageAdapter, VirtualStorageAdapter, ignoreExists, ignoreNotfound, isFileError };
@@ -1,6 +1,6 @@
1
+ import { Context, ParsedTypeScriptConfig, TSConfig } from "@powerlines/core";
1
2
  import ts from "typescript";
2
3
  import { FileSystemHost, InMemoryFileSystemHost, Project, ProjectOptions, RuntimeDirEntry } from "ts-morph";
3
- import { Context, ParsedTypeScriptConfig, TSConfig } from "@powerlines/core";
4
4
  import { FilterPattern } from "@stryke/types/file";
5
5
 
6
6
  //#region src/typescript/ts-morph.d.ts
@@ -1,5 +1,6 @@
1
1
  const require_chunk = require('./chunk-C0xms8kb.cjs');
2
2
  let _stryke_path_join = require("@stryke/path/join");
3
+ let _stryke_type_checks_is_set_string = require("@stryke/type-checks/is-set-string");
3
4
  let _powerlines_core_lib_utilities_file_header = require("@powerlines/core/lib/utilities/file-header");
4
5
  let _stryke_fs_exists = require("@stryke/fs/exists");
5
6
  let _stryke_fs_helpers = require("@stryke/fs/helpers");
@@ -7,7 +8,6 @@ let _stryke_fs_list_files = require("@stryke/fs/list-files");
7
8
  let _stryke_path_append = require("@stryke/path/append");
8
9
  let _stryke_path_is_parent_path = require("@stryke/path/is-parent-path");
9
10
  let _stryke_type_checks_is_error = require("@stryke/type-checks/is-error");
10
- let _stryke_type_checks_is_set_string = require("@stryke/type-checks/is-set-string");
11
11
  let _stryke_path_correct_path = require("@stryke/path/correct-path");
12
12
  let _stryke_fs_is_file = require("@stryke/fs/is-file");
13
13
  let _stryke_fs_read_file = require("@stryke/fs/read-file");
@@ -1,4 +1,5 @@
1
1
  import { joinPaths } from "@stryke/path/join";
2
+ import { isSetString } from "@stryke/type-checks/is-set-string";
2
3
  import { getFileHeaderWarningText } from "@powerlines/core/lib/utilities/file-header";
3
4
  import { exists, existsSync } from "@stryke/fs/exists";
4
5
  import { createDirectory, createDirectorySync } from "@stryke/fs/helpers";
@@ -6,7 +7,6 @@ import { listFiles, listFilesSync } from "@stryke/fs/list-files";
6
7
  import { appendPath } from "@stryke/path/append";
7
8
  import { isParentPath } from "@stryke/path/is-parent-path";
8
9
  import { isError } from "@stryke/type-checks/is-error";
9
- import { isSetString } from "@stryke/type-checks/is-set-string";
10
10
  import { correctPath } from "@stryke/path/correct-path";
11
11
  import { isDirectory, isFile } from "@stryke/fs/is-file";
12
12
  import { readFile, readFileSync } from "@stryke/fs/read-file";
@@ -510,4 +510,4 @@ var VirtualStorageAdapter = class extends BaseStorageAdapter {
510
510
 
511
511
  //#endregion
512
512
  export { isFileError as a, ignoreNotfound as i, FileSystemStorageAdapter as n, BaseStorageAdapter as o, ignoreExists as r, VirtualStorageAdapter as t };
513
- //# sourceMappingURL=virtual-gIlTc3Lj.mjs.map
513
+ //# sourceMappingURL=virtual-CUgOdyIa.mjs.map