@powerlines/engine 0.44.11 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/_internal/worker.cjs +141 -106
  2. package/dist/_internal/worker.d.cts +16 -8
  3. package/dist/_internal/worker.d.cts.map +1 -1
  4. package/dist/_internal/worker.d.mts +16 -8
  5. package/dist/_internal/worker.d.mts.map +1 -1
  6. package/dist/_internal/worker.mjs +142 -107
  7. package/dist/_internal/worker.mjs.map +1 -1
  8. package/dist/api.cjs +60 -46
  9. package/dist/api.d.cts +18 -13
  10. package/dist/api.d.cts.map +1 -1
  11. package/dist/api.d.mts +18 -13
  12. package/dist/api.d.mts.map +1 -1
  13. package/dist/api.mjs +60 -46
  14. package/dist/api.mjs.map +1 -1
  15. package/dist/{base-context-C6yzgs6K.mjs → base-context-BSAC5sO9.mjs} +21 -15
  16. package/dist/base-context-BSAC5sO9.mjs.map +1 -0
  17. package/dist/{base-context-trNQZNsX.cjs → base-context-Byizvf4F.cjs} +20 -14
  18. package/dist/context/index.cjs +3 -3
  19. package/dist/context/index.d.cts +13 -8
  20. package/dist/context/index.d.cts.map +1 -1
  21. package/dist/context/index.d.mts +13 -8
  22. package/dist/context/index.d.mts.map +1 -1
  23. package/dist/context/index.mjs +3 -3
  24. package/dist/{engine-context-D1_U6xVC.cjs → engine-context-CI_0NWIk.cjs} +5 -3
  25. package/dist/{engine-context-C-11i43N.mjs → engine-context-_RMFwG4J.mjs} +6 -4
  26. package/dist/engine-context-_RMFwG4J.mjs.map +1 -0
  27. package/dist/{execution-context-C-M-Mxse.cjs → execution-context-BFCOc0mH.cjs} +61 -48
  28. package/dist/{execution-context-D9Enw3J5.mjs → execution-context-Cr_VUBrP.mjs} +63 -50
  29. package/dist/execution-context-Cr_VUBrP.mjs.map +1 -0
  30. package/dist/index.cjs +30 -20
  31. package/dist/index.d.cts +9 -8
  32. package/dist/index.d.cts.map +1 -1
  33. package/dist/index.d.mts +9 -8
  34. package/dist/index.d.mts.map +1 -1
  35. package/dist/index.mjs +30 -20
  36. package/dist/index.mjs.map +1 -1
  37. package/package.json +3 -3
  38. package/dist/base-context-C6yzgs6K.mjs.map +0 -1
  39. package/dist/engine-context-C-11i43N.mjs.map +0 -1
  40. package/dist/execution-context-D9Enw3J5.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["Worker","#worker","JestWorker","#worker","Worker","#context"],"sources":["../src/_internal/ipc/parse.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 { LogMeta } from \"@powerlines/core\";\nimport { toArray } from \"@stryke/convert/to-array\";\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 (\n isSetObject(data) &&\n isSetObject(data.meta) &&\n isSetString((data.meta as LogMeta).type) &&\n (isSetString(data.message) || Array.isArray(data.message))\n ) {\n return {\n ...data,\n meta: data.meta as Omit<\n LogMeta,\n \"executionId\" | \"executionIndex\" | \"environment\" | \"timestamp\"\n >,\n message: toArray(data.message).filter(Boolean)\n };\n }\n\n throw new Error(\n `Invalid \"write-log\" message payload: ${JSON.stringify(data)}`\n );\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(\n `Invalid \"update-command\" message payload: ${JSON.stringify(data)}`\n );\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(\n `Invalid \"update-hook\" message payload: ${JSON.stringify(data)}`\n );\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(\n `Invalid \"update-plugin\" message payload: ${JSON.stringify(data)}`\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 { ExecutionWorkerParams, Logger } from \"@powerlines/core\";\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 { IpcMessage, IpcMessageType } from \"../ipc/messages\";\nimport { parseIpcMessage } from \"../ipc/parse\";\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 log 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: Logger;\n\n /**\n * A callback function that is called when the worker sends a log message. This can be used to handle log messages from the worker and integrate them with the parent process's logging system. The function should accept a `WriteLogIpcMessage` object as its argument, which contains the log message and associated metadata.\n */\n onIpcMessage?: (message: IpcMessage) => 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.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 NODE_OPTIONS: formattedNodeOptions,\n POWERLINES_WORKER_THREAD_EXECUTION: \"true\"\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 computeWorkerKey: (method: string, ...args: Array<unknown>) => {\n let executionParams: {\n method?: string;\n executionIndex?: number;\n name?: string;\n } = { method };\n if (args.length > 0 && isSetObject(args[0])) {\n const arg = args[0] as Partial<ExecutionWorkerParams>;\n if (isSetObject(arg.options)) {\n executionParams = {\n method,\n executionIndex: arg.options.executionIndex ?? 0,\n name: arg.options.name\n };\n }\n }\n\n return JSON.stringify(executionParams);\n },\n ...rest,\n forkOptions: {\n ...rest.forkOptions,\n silent: true,\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.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.trace(\n `Received IPC message from worker: ${JSON.stringify(message)}`\n );\n\n void Promise.resolve(this.options.onIpcMessage?.(message));\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 { toArray } from \"@stryke/convert/to-array\";\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 {\n IpcMessage,\n IpcMessageType,\n UpdateCommandIpcMessage,\n UpdateHookIpcMessage,\n UpdatePluginIpcMessage,\n WriteLogIpcMessage\n} from \"./_internal/ipc/messages\";\nimport {\n parseUpdateCommandMessagePayload,\n parseUpdateHookMessagePayload,\n parseUpdatePluginMessagePayload,\n parseWriteLogMessagePayload\n} from \"./_internal/ipc/parse\";\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 onIpcMessage: api.handleIpcMessage.bind(api),\n enableSourceMaps: options.mode === \"development\",\n exposedMethods: POWERLINES_API_FUNCTIONS,\n logger: api.context.extendLogger({ category: \"ipc\" })\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(\"📓 Generating documentation for the Powerlines project\");\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 /**\n * Asynchronous disposal method for the Powerlines Engine, which will call the finalize method to perform any necessary cleanup when the engine is disposed of.\n */\n public async [Symbol.asyncDispose]() {\n return this.finalize();\n }\n\n /**\n * Handle incoming IPC messages from the worker processes, routing them to the appropriate handlers based on the message type.\n *\n * @param message - The IPC message received from a worker process\n */\n private async handleIpcMessage(message: IpcMessage) {\n switch (message.type) {\n case IpcMessageType.WRITE_LOG: {\n const payload = parseWriteLogMessagePayload(message.payload);\n\n this.context.logger.debug({\n meta: {\n category: \"ipc\",\n executionId: message.executionId,\n executionIndex: message.executionIndex,\n environment: message.environment\n },\n message: `Received a \"write-log\" IPC message from worker:\nType: ${payload.meta.type}\nMessage: ${toArray(payload.message).filter(Boolean).join(\"\\n\")}`\n });\n\n await this.handleWriteLog({\n ...message,\n type: IpcMessageType.WRITE_LOG,\n payload\n });\n\n break;\n }\n\n case IpcMessageType.UPDATE_COMMAND:\n this.context.logger.debug({\n meta: {\n category: \"ipc\",\n executionId: message.executionId,\n executionIndex: message.executionIndex,\n environment: message.environment\n },\n message: `Received an \"update-command\" IPC message from worker: \\n${JSON.stringify(\n message,\n null,\n 2\n )}`\n });\n\n await this.handleUpdateCommand({\n ...message,\n type: IpcMessageType.UPDATE_COMMAND,\n payload: parseUpdateCommandMessagePayload(message.payload)\n });\n\n break;\n\n case IpcMessageType.UPDATE_HOOK:\n this.context.logger.debug({\n meta: {\n category: \"ipc\",\n executionId: message.executionId,\n executionIndex: message.executionIndex,\n environment: message.environment\n },\n message: `Received an \"update-hook\" IPC message from worker: \\n${JSON.stringify(\n message,\n null,\n 2\n )}`\n });\n\n await this.handleUpdateHook({\n ...message,\n type: IpcMessageType.UPDATE_HOOK,\n payload: parseUpdateHookMessagePayload(message.payload)\n });\n\n break;\n\n case IpcMessageType.UPDATE_PLUGIN:\n this.context.logger.debug({\n meta: {\n category: \"ipc\",\n executionId: message.executionId,\n executionIndex: message.executionIndex,\n environment: message.environment\n },\n message: `Received an \"update-plugin\" IPC message from worker: \\n${JSON.stringify(\n message,\n null,\n 2\n )}`\n });\n\n await this.handleUpdatePlugin({\n ...message,\n type: IpcMessageType.UPDATE_PLUGIN,\n payload: parseUpdatePluginMessagePayload(message.payload)\n });\n\n break;\n\n case IpcMessageType.ACTIVITY:\n case undefined:\n default: {\n break;\n }\n }\n }\n\n private async handleWriteLog(message: WriteLogIpcMessage) {\n const { payload } = message;\n\n this.context.logger.log(payload.meta.type, {\n message: toArray(payload.message).filter(Boolean).join(\"\\n\"),\n meta: {\n category: payload.meta.category,\n logId: payload.meta.logId,\n name: payload.meta.name,\n executionId: message.executionId,\n executionIndex: message.executionIndex,\n command: payload.meta.command,\n hook: payload.meta.hook,\n environment: message.environment,\n plugin: payload.meta.plugin,\n source: payload.meta.source,\n timestamp: message.timestamp,\n $$ipc: true\n }\n });\n }\n\n private async handleUpdatePlugin(_: UpdatePluginIpcMessage) {}\n\n private async handleUpdateHook(_: UpdateHookIpcMessage) {}\n\n private async handleUpdateCommand(_: UpdateCommandIpcMessage) {}\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgCA,SAAgB,gBAAgB,MAA4C;CAC1E,IAAI;AACJ,KAAI,YAAY,KAAK,CACnB,WAAU;UACD,SAAS,KAAK,CACvB,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,MAAI,YAAY,OAAO,CACrB,WAAU;SAEN;AAKV,KACE,WACA,YAAY,QAAQ,GAAG,IACvB,YAAY,QAAQ,KAAK,IACzB,YAAY,QAAQ,YAAY,IAChC,OAAO,UAAU,QAAQ,eAAe,IACxC,CAAC,OAAO,MAAM,QAAQ,UAAU,CAEhC,QAAO;;AAMX,SAAgB,4BACd,MACwB;AACxB,KACE,YAAY,KAAK,IACjB,YAAY,KAAK,KAAK,IACtB,YAAa,KAAK,KAAiB,KAAK,KACvC,YAAY,KAAK,QAAQ,IAAI,MAAM,QAAQ,KAAK,QAAQ,EAEzD,QAAO;EACL,GAAG;EACH,MAAM,KAAK;EAIX,SAAS,QAAQ,KAAK,QAAQ,CAAC,OAAO,QAAQ;EAC/C;AAGH,OAAM,IAAI,MACR,wCAAwC,KAAK,UAAU,KAAK,GAC7D;;AAGH,SAAgB,iCACd,MAC6B;AAC7B,KAAI,YAAY,MAAM,QAAQ,CAC5B,QAAO,EACL,SAAS,KAAK,SACf;AAGH,OAAM,IAAI,MACR,6CAA6C,KAAK,UAAU,KAAK,GAClE;;AAGH,SAAgB,8BACd,MAC0B;AAC1B,KACE,YAAY,MAAM,KAAK,IACvB;EAAC;EAAO;EAAQ;EAAS,CAAC,SAAS,KAAK,MAAM,CAE9C,QAAO;EACL,MAAM,KAAK;EACX,OAAO,KAAK;EACb;AAGH,OAAM,IAAI,MACR,0CAA0C,KAAK,UAAU,KAAK,GAC/D;;AAGH,SAAgB,gCACd,MAC4B;AAC5B,KAAI,YAAY,MAAM,OAAO,CAC3B,QAAO,EACL,QAAQ,KAAK,QACd;AAGH,OAAM,IAAI,MACR,4CAA4C,KAAK,UAAU,KAAK,GACjE;;;;;AChGH,MAAM,YAAY,OAAO,8BAA8B;;;;AAavD,MAAM,sBAAsB,EAAE,MAAM,WAAiC;AACnE,QAAO,OAAO,GAAG,KAAK,GAAG,SAAS,GAAG;;;;;;;;;;;AAYvC,MAAM,yBAAyB,IAAI,IAAI;CACrC;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAS,UACP,KACA,OACe;AACf,KAAI,UAAU,KACZ,QAAO,KAAK;AAGd,KAAI,MACF,QAAO,KAAK,IAAI,GAGd,MAAM,SAAS,IAAI,IAAI,CAAC,MAAM,WAAW,KAAI,GACzC,KAAK,UAAU,MAAM,GACrB;AAIR,QAAO;;;;;;;;;;AAWT,MAAM,gBAAgB,UAA4B;CAChD,MAAM,OAAiB,EAAE;CACzB,IAAI,aAAa;CACjB,IAAI,kBAAkB;AAEtB,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,IAAI,OAAO,MAAM;AACjB,MAAI,MAAM;AAER,OAAI,SAAS,QAAQ,YAAY;AAE/B,QAAI,MAAM,WAAW,IAAI,EACvB,OAAM,IAAI,MAAM,uCAAuC;AAIzD,WAAO,MAAM,EAAE;AACf,QAAI,CAAC,KACH;cAIK,SAAS,OAAO,CAAC,YAAY;AACpC,sBAAkB;AAClB;cAIO,SAAS,MAAK;AACrB,iBAAa,CAAC;AACd;;AAIF,OAAI,iBAAiB;AACnB,SAAK,KAAK,KAAK;AACf,sBAAkB;SAIlB,MAAK,KAAK,SAAS,MAAM;;;AAK/B,KAAI,WACF,OAAM,IAAI,MAAM,sBAAsB;AAGxC,QAAO;;;;;;;;AAST,MAAM,2BAA2B;AAC/B,KAAI,CAAC,QAAQ,IAAI,aAAc,QAAO,EAAE;AAExC,QAAO,aAAa,QAAQ,IAAI,aAAa;;;;;;;;;;AAW/C,SAAS,kBACP,MAC6C;CAC7C,MAAM,mBAA6B,EAAE;CACrC,MAAM,WAAqB,EAAE;AAE7B,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,EAAE;EAC/C,MAAM,YAAY,UAAU,KAAK,MAAM;AACvC,MAAI,cAAc,KAAM;AAExB,MAAI,uBAAuB,IAAI,IAAI,CACjC,UAAS,KAAK,UAAU;MAExB,kBAAiB,KAAK,UAAU;;AAIpC,QAAO;EAAE,aAAa,iBAAiB,KAAK,IAAI;EAAE;EAAU;;AAK9D,MAAM,iBAAiB,SAAgC;CACrD,MAAM,EAAE,QAAQ,WAAW,UAAU;EAAE;EAAM,QAAQ;EAAO,QAAQ;EAAM,CAAC;CAI3E,IAAI,SAAS;AACb,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,MAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAO;AAEZ,MAAI,MAAM,SAAS,oBACjB;AAMF,MAAI,MAAM,SAAS,UAAU;AAC3B,YAAS,CAAC,MAAM,MAAM,MAAM,GAAG,QAAQ;AACvC;;AAKF,MAAI,MAAM,SAAS,cAAc;AAC/B,YAAS;AACT;;AAIF,MAAI,CAAC,OACH;AAKF,MAAI,OAAO,QAAQ,UAAU,SAAS,OAAO,OAAO,MAAM,CACxD,QAAO,OAAO,SAAS,IAAI,MAAM;MAEjC,QAAO,OAAO,QAAQ,MAAM;;AAIhC,QAAO;;AAGT,SAAS,uBAAqE;CAC5E,MAAM,OAAO,CAAC,GAAG,QAAQ,UAAU,GAAG,oBAAoB,CAAC;AAC3D,KAAI,KAAK,WAAW,EAAG,QAAO,EAAE;AAEhC,QAAO,cAAc,KAAK;;;;;;;;;AAU5B,MAAM,yBACJ,YACiB;AACjB,KAAI,CAAC,WAAW,CAAC,SAAS,QAAQ,CAChC,QAAO;EAAE,MAAM;EAAW,MAAM;EAAM;AAIxC,KAAI,QAAQ,SAAS,IAAI,EAAE;EACzB,MAAM,CAAC,MAAM,QAAQ,QAAQ,MAAM,IAAI;AACvC,MAAI,CAAC,QAAQ,CAAC,KACZ,OAAM,IAAI,MAAM,0BAA0B,UAAU;AAGtD,SAAO;GAAE;GAAM,MAAM,OAAO,SAAS,MAAM,GAAG;GAAE;;AAGlD,QAAO;EAAE,MAAM;EAAW,MAAM,OAAO,SAAS,SAAS,GAAG;EAAE;;;;;AAQhE,SAAS,iBAAiB,aAA2C;AACnE,KAAI,YAAY,QACd,QAAO;AAET,KAAI,YAAY,kBAAkB,YAAY,YAC5C,QAAO;;AAMX,MAAM,kBAAkB,WAAuB;AAC7C,MAAK,MAAM,aAAe,OAAe,aAAa,YAAY,EAAE,CAGlE,WAAU,QAAQ,KAAK,SAAS;;AA6DpC,IAAaA,WAAb,MAAoB;CAClB;;;;;;;CAQA,AAAO,YACL,AAAU,YACV,AAAU,SACV;EAFU;EACA;EAEV,MAAM,EACJ,SACA,WACA,qBAAqB,IACrB,mBAAmB,OACnB,iBAAiB,OACjB,QACA,GAAG,SACD,KAAK;EAET,IAAI;EACJ,IAAI;EACJ,IAAI,cAAc;AAElB,QAAKC,SAAU;AAGf,UAAQ,GAAG,cAAc;AACvB,QAAK,OAAO;IACZ;EAEF,MAAM,cAAc,sBAAsB;EAC1C,MAAM,kBAAkB,EAAE,GAAG,aAAa;AAC1C,SAAO,YAAY;AACnB,SAAO,YAAY;AACnB,SAAO,YAAY;AACnB,MAAI,uBAAuB,IAAI;GAC7B,MAAM,gBAAgB,iBAAiB,gBAAgB;AACvD,OAAI,eAAe;IACjB,MAAM,kBAAkB,sBACtB,gBAAgB,eACjB;AASD,gBAAY,iBAAiB,mBAAmB;KAP9C,MAAM,gBAAgB;KAEtB,MACE,gBAAgB,SAAS,IACrB,IACA,gBAAgB,OAAO,IAAI;KAEoB,CAAC;;;AAI5D,MAAI,iBACF,aAAY,wBAAwB;AAGtC,MAAI,gBAAgB;AAClB,UAAO,YAAY;AACnB,UAAO,YAAY;;EAGrB,MAAM,EAAE,aAAa,sBAAsB,aACzC,kBAAkB,YAAY;EAEhC,MAAM,kBAAkB;GACtB,MAAM,SAAS,MAAKA;AACpB,OAAI,CAAC,OACH;GAGF,MAAM,UAAU;AAEhB,iBAAc;AAEd,UAAO,KACL,yDACE,UAAU,OAAO,eAAe,EAAE,SAAS,UAAU,KAAM,CAAC,KAAK,GAClE,4DACF;AAED,GAAK,OAAO,KAAK,CAAC,WAAW;AAC3B,YAAQ,UAAU;KAClB;;EAGJ,IAAI,eAAuC;EAE3C,MAAM,mBAAmB;AACvB,OAAI,aACF,cAAa,aAAa;AAE5B,OAAI,KAAK,QAAQ,WACf,MAAK,QAAQ,YAAY;AAG3B,kBAAe,cAAc,KAAK,WAAW,WAAW,QAAQ;;EAGlE,MAAM,qBAAqB;GACzB,MAAM,YAA+B;IACnC,GAAG,QAAQ;IACX,GAAK,KAAK,aAAa,OAAO,EAAE;IAChC,cAAc;IACd,oCAAoC;IACrC;AAED,OAAI,UAAU,gBAAgB,QAY5B;QALE,CAAC,UAAU,YACX,CAAC,UAAU,MACX,UAAU,SAAS,WAClB,QAAQ,OAAO,SAAS,QAAQ,QAAQ,OAGzC,WAAU,cAAc;;AAI5B,SAAKA,SAAU,IAAIC,OAAW,YAAY;IACxC,YAAY;IACZ,YAAY,MAAM,CAAC,UAAU;IAC7B,mBAAmB,QAAgB,GAAG,SAAyB;KAC7D,IAAI,kBAIA,EAAE,QAAQ;AACd,SAAI,KAAK,SAAS,KAAK,YAAY,KAAK,GAAG,EAAE;MAC3C,MAAM,MAAM,KAAK;AACjB,UAAI,YAAY,IAAI,QAAQ,CAC1B,mBAAkB;OAChB;OACA,gBAAgB,IAAI,QAAQ,kBAAkB;OAC9C,MAAM,IAAI,QAAQ;OACnB;;AAIL,YAAO,KAAK,UAAU,gBAAgB;;IAExC,GAAG;IACH,aAAa;KACX,GAAG,KAAK;KACR,QAAQ;KACR,UAAU,CAAC,GAAG,UAAU,GAAI,KAAK,aAAa,YAAY,EAAE,CAAE;KAC9D,KAAK;KACN;IACF,CAAC;AACF,oBAAiB,IAAI,SAAQ,YAAW;AACtC,4BAAwB;KACxB;;;;;;;;;;AAWF,OAAI,CAAC,KAAK,oBACR,MAAK,MAAM,UAAY,MAAKD,OAAgB,aAAa,YACvD,EAAE,EAEC;AACH,WAAO,QAAQ,GAAG,SAAS,MAAM,WAAW;AAC1C,UAAK,QAAS,UAAU,WAAW,aAAc,MAAKA,QAAS;AAC7D,aAAO,MACL,4BAA4B,KAAK,eAAe,SACjD;AAGD,cAAQ,KAAK,QAAQ,EAAE;;MAEzB;AAIF,WAAO,QAAQ,GAAG,YAAW,SAAQ;AACnC,SACE,YAAY,KAAK,IAChB,KAAoB,oBAErB,aAAY;UACP;MACL,MAAM,UAAU,gBAAgB,KAAK;AACrC,UAAI,SAAS;AACX,cAAO,MACL,qCAAqC,KAAK,UAAU,QAAQ,GAC7D;AAED,OAAK,QAAQ,QAAQ,KAAK,QAAQ,eAAe,QAAQ,CAAC;;;MAG9D;;GAIN,IAAI,UAAU;GACd,MAAM,wBAAwB;AAC5B,QAAI,CAAC,SAAS;AACZ,UAAK,QAAQ,mBAAmB;AAChC,eAAU;;;GAKd,MAAM,2BAA2B,IAAI,UAAU,EAC7C,UAAU,QAAQ,WAAW,UAAU;AACrC,qBAAiB;AACjB,cAAU;MAEb,CAAC;AAEF,SAAKA,OAAQ,WAAW,CAAC,KAAK,yBAAyB;AACvD,SAAKA,OAAQ,WAAW,CAAC,KAAK,yBAAyB;AAGvD,SAAKA,OAAQ,WAAW,CAAC,KAAK,QAAQ,OAAO;AAC7C,SAAKA,OAAQ,WAAW,CAAC,KAAK,QAAQ,OAAO;;AAE/C,gBAAc;AAEd,OAAK,MAAM,UAAU,KAAK,gBAAgB;AACxC,OAAI,OAAO,WAAW,IAAI,CACxB;AAGF,GAAC,KAAa,UAAU,UACpB,OAAO,GAAG,SAAgB;AACxB;AACA,QAAI;KACF,IAAI,WAAW;AACf,cAAS;AACP,kBAAY;MAEZ,MAAM,SAAS,MAAM,QAAQ,KAAK,CAE/B,MAAKA,OAAgB,QACpB,KAAK,SAAS,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,CAC1C,EACD,eACD,CAAC;AACF,UAAI,WAAW,UACb,QAAO;AAET,UAAI,UACF,WAAU,QAAQ,MAAM,EAAE,SAAS;;cAG/B;AACR;AACA,iBAAY;;OAIf,MAAKA,OAAgB,QAAQ,KAAK,MAAKA,OAAQ;;;CAIxD,MAAa,MAAqC;EAChD,MAAM,SAAS,MAAKA;AACpB,MAAI,CAAC,OACH,OAAM,IAAI,MAAM,iDAAiD;AAGnE,iBAAe,OAAO;AACtB,QAAKA,SAAU;AACf,SAAO,OAAO,KAAK;;;;;CAMrB,AAAO,QAAc;AACnB,MAAI,MAAKA,QAAS;AAChB,kBAAe,MAAKA,OAAQ;AAC5B,GAAK,MAAKA,OAAQ,KAAK;;;;;;;;;;;;;;;AC9jB7B,IAAa,mBAAb,MAAa,iBAAoD;;;;CAI/D;;;;CAKA;;;;;;;CAQA,aAAoB,YAClB,SAC2B;EAC3B,MAAM,MAAM,IAAI,iBACd,MAAM,wBAAwB,YAAY,QAAQ,CACnD;EAED,MAAM,cAAc,MAAM,eAAe,qBAAqB;AAC9D,MAAI,CAAC,YACH,OAAM,IAAI,MACR,2DACD;AAGH,OAAIE,SAAU,IAAIC,SAAO,UAAU,aAAa,yBAAyB,EAAE;GACzE,cAAc,IAAI,iBAAiB,KAAK,IAAI;GAC5C,kBAAkB,QAAQ,SAAS;GACnC,gBAAgB;GAChB,QAAQ,IAAI,QAAQ,aAAa,EAAE,UAAU,OAAO,CAAC;GACtD,CAAC;AAEF,SAAO;;;;;CAMT,IAAW,UAAyB;AAClC,SAAO,MAAKC;;;;;;;CAQd,AAAU,YAAY,SAAwB;AAC5C,QAAKA,UAAW;;;;;;;;;;CAWlB,MAAa,MACX,eAGI,EACF,SAAS,SACV,EACD;EACA,MAAM,QAAQ,KAAK,QAAQ,MAAM,QAAQ;AACzC,OAAK,QAAQ,KACX,qEACD;AAED,OAAK,QAAQ,MACX,gEACD;AAED,eAAa,YAAY;AACzB,QAAM,QAAQ,IACZ,MAAKA,QAAS,WAAW,IAAI,OAAM,cACjC,MAAKF,OAAQ,MAAM;GACjB,SAAS,UAAU;GACnB,QAAQ;GACT,CAAC,CACH,CACF;AAED,OAAK,QAAQ,MACX,2DACD;AACD,SAAO;;;;;;;;;;CAWT,MAAa,QACX,eAQqE,EACnE,SAAS,WACV,EACD;EACA,MAAM,QAAQ,KAAK,QAAQ,MAAM,UAAU;AAC3C,OAAK,QAAQ,KAAK,uCAAuC;AAEzD,OAAK,QAAQ,MACX,+DACD;AAED,eAAa,YAAY;AACzB,QAAM,QAAQ,IACZ,MAAKE,QAAS,WAAW,IAAI,OAAM,cACjC,MAAKF,OAAQ,QAAQ;GACnB,SAAS,UAAU;GACnB,QAAQ;GACT,CAAC,CACH,CACF;AAED,OAAK,QAAQ,MAAM,sDAAsD;AACzE,SAAO;;;;;;;;;;;CAYT,MAAa,IAAI,cAAuD;EACtE,MAAM,QAAQ,KAAK,QAAQ,MAAM,MAAM;AACvC,OAAK,QAAQ,KAAK,uCAAuC;AAEzD,eAAa,YAAY;AACzB,QAAM,QAAQ,IACZ,MAAKE,QAAS,WAAW,IAAI,OAAM,cACjC,MAAKF,OAAQ,IAAI;GACf,SAAS,UAAU;GACnB,QAAQ;GACT,CAAC,CACH,CACF;AAED,OAAK,QAAQ,MAAM,kDAAkD;AACrE,SAAO;;;;;;;;;;;CAYT,MAAa,MACX,eAEsE,EACpE,SAAS,SACV,EACD;EACA,MAAM,QAAQ,KAAK,QAAQ,MAAM,QAAQ;AACzC,OAAK,QAAQ,KAAK,gDAAgD;AAElE,eAAa,YAAY;AACzB,QAAM,QAAQ,IACZ,MAAKE,QAAS,WAAW,IAAI,OAAM,cACjC,MAAKF,OAAQ,MAAM;GACjB,SAAS,UAAU;GACnB,QAAQ;GACT,CAAC,CACH,CACF;AAED,OAAK,QAAQ,MAAM,+CAA+C;AAClE,SAAO;;;;;;;;CAST,MAAa,KACX,eAEoE,EAClE,SAAS,QACV,EACD;EACA,MAAM,QAAQ,KAAK,QAAQ,MAAM,OAAO;AACxC,OAAK,QAAQ,KAAK,oCAAoC;AAEtD,eAAa,YAAY;AACzB,QAAM,QAAQ,IACZ,MAAKE,QAAS,WAAW,IAAI,OAAM,cACjC,MAAKF,OAAQ,KAAK;GAChB,SAAS,UAAU;GACnB,QAAQ;GACT,CAAC,CACH,CACF;AAED,OAAK,QAAQ,MAAM,8CAA8C;AACjE,SAAO;;;;;;;;;;;CAYT,MAAa,KACX,eAEoE,EAClE,SAAS,QACV,EACD;EACA,MAAM,QAAQ,KAAK,QAAQ,MAAM,OAAO;AACxC,OAAK,QAAQ,KAAK,8CAA8C;AAEhE,eAAa,YAAY;AACzB,QAAM,QAAQ,IACZ,MAAKE,QAAS,WAAW,IAAI,OAAM,cACjC,MAAKF,OAAQ,KAAK;GAChB,SAAS,UAAU;GACnB,QAAQ;GACT,CAAC,CACH,CACF;AAED,OAAK,QAAQ,MAAM,8CAA8C;AACjE,SAAO;;;;;;;;;;;CAYT,MAAa,MACX,eAGI,EACF,SAAS,SACV,EACD;EACA,MAAM,QAAQ,KAAK,QAAQ,MAAM,QAAQ;AACzC,OAAK,QAAQ,KAAK,qCAAqC;AAEvD,QAAM,QAAQ,IACZ,MAAKE,QAAS,WAAW,IAAI,OAAM,cACjC,MAAKF,OAAQ,MAAM;GACjB,SAAS,UAAU;GACnB,QAAQ;GACT,CAAC,CACH,CACF;AAED,OAAK,QAAQ,MAAM,4CAA4C;AAC/D,SAAO;;;;;;;;CAST,MAAa,KACX,eAGI,EACF,SAAS,QACV,EACD;EACA,MAAM,QAAQ,KAAK,QAAQ,MAAM,OAAO;AACxC,OAAK,QAAQ,KAAK,yDAAyD;AAE3E,eAAa,YAAY;AAEzB,QAAM,QAAQ,IACZ,MAAKE,QAAS,WAAW,IAAI,OAAM,cACjC,MAAKF,OAAQ,KAAK;GAChB,SAAS,UAAU;GACnB,QAAQ;GACT,CAAC,CACH,CACF;AAED,OAAK,QAAQ,MACX,+DACD;AACD,SAAO;;;;;;;;;;CAWT,MAAa,OACX,eAGI,EACF,SAAS,UACV,EACD;EACA,MAAM,QAAQ,KAAK,QAAQ,MAAM,SAAS;AAC1C,OAAK,QAAQ,KAAK,sCAAsC;AAExD,eAAa,YAAY;AAEzB,QAAM,QAAQ,IACZ,MAAKE,QAAS,WAAW,IAAI,OAAM,cACjC,MAAKF,OAAQ,OAAO;GAClB,SAAS,UAAU;GACnB,QAAQ;GACT,CAAC,CACH,CACF;AAED,OAAK,QAAQ,MAAM,6CAA6C;AAChE,SAAO;;;;;;;;;;CAWT,MAAa,WAAW;EACtB,MAAM,QAAQ,KAAK,QAAQ,MAAM,eAAe;AAChD,OAAK,QAAQ,KAAK,+CAA+C;AAEjE,QAAKA,OAAQ,OAAO;AAEpB,OAAK,QAAQ,MAAM,mDAAmD;AACtE,SAAO;;;;;CAMT,OAAc,OAAO,gBAAgB;AACnC,SAAO,KAAK,UAAU;;;;;;;CAQxB,MAAc,iBAAiB,SAAqB;AAClD,UAAQ,QAAQ,MAAhB;GACE,kBAA+B;IAC7B,MAAM,UAAU,4BAA4B,QAAQ,QAAQ;AAE5D,SAAK,QAAQ,OAAO,MAAM;KACxB,MAAM;MACJ,UAAU;MACV,aAAa,QAAQ;MACrB,gBAAgB,QAAQ;MACxB,aAAa,QAAQ;MACtB;KACD,SAAS;QACX,QAAQ,KAAK,KAAK;WACf,QAAQ,QAAQ,QAAQ,CAAC,OAAO,QAAQ,CAAC,KAAK,KAAK;KACrD,CAAC;AAEF,UAAM,KAAK,eAAe;KACxB,GAAG;KACH;KACA;KACD,CAAC;AAEF;;GAGF;AACE,SAAK,QAAQ,OAAO,MAAM;KACxB,MAAM;MACJ,UAAU;MACV,aAAa,QAAQ;MACrB,gBAAgB,QAAQ;MACxB,aAAa,QAAQ;MACtB;KACD,SAAS,2DAA2D,KAAK,UACvE,SACA,MACA,EACD;KACF,CAAC;AAEF,UAAM,KAAK,oBAAoB;KAC7B,GAAG;KACH;KACA,SAAS,iCAAiC,QAAQ,QAAQ;KAC3D,CAAC;AAEF;GAEF;AACE,SAAK,QAAQ,OAAO,MAAM;KACxB,MAAM;MACJ,UAAU;MACV,aAAa,QAAQ;MACrB,gBAAgB,QAAQ;MACxB,aAAa,QAAQ;MACtB;KACD,SAAS,wDAAwD,KAAK,UACpE,SACA,MACA,EACD;KACF,CAAC;AAEF,UAAM,KAAK,iBAAiB;KAC1B,GAAG;KACH;KACA,SAAS,8BAA8B,QAAQ,QAAQ;KACxD,CAAC;AAEF;GAEF;AACE,SAAK,QAAQ,OAAO,MAAM;KACxB,MAAM;MACJ,UAAU;MACV,aAAa,QAAQ;MACrB,gBAAgB,QAAQ;MACxB,aAAa,QAAQ;MACtB;KACD,SAAS,0DAA0D,KAAK,UACtE,SACA,MACA,EACD;KACF,CAAC;AAEF,UAAM,KAAK,mBAAmB;KAC5B,GAAG;KACH;KACA,SAAS,gCAAgC,QAAQ,QAAQ;KAC1D,CAAC;AAEF;GAEF;GACA,KAAK;GACL,QACE;;;CAKN,MAAc,eAAe,SAA6B;EACxD,MAAM,EAAE,YAAY;AAEpB,OAAK,QAAQ,OAAO,IAAI,QAAQ,KAAK,MAAM;GACzC,SAAS,QAAQ,QAAQ,QAAQ,CAAC,OAAO,QAAQ,CAAC,KAAK,KAAK;GAC5D,MAAM;IACJ,UAAU,QAAQ,KAAK;IACvB,OAAO,QAAQ,KAAK;IACpB,MAAM,QAAQ,KAAK;IACnB,aAAa,QAAQ;IACrB,gBAAgB,QAAQ;IACxB,SAAS,QAAQ,KAAK;IACtB,MAAM,QAAQ,KAAK;IACnB,aAAa,QAAQ;IACrB,QAAQ,QAAQ,KAAK;IACrB,QAAQ,QAAQ,KAAK;IACrB,WAAW,QAAQ;IACnB,OAAO;IACR;GACF,CAAC;;CAGJ,MAAc,mBAAmB,GAA2B;CAE5D,MAAc,iBAAiB,GAAyB;CAExD,MAAc,oBAAoB,GAA4B"}
1
+ {"version":3,"file":"index.mjs","names":["Worker","#worker","JestWorker","#worker","Worker","#context"],"sources":["../src/_internal/ipc/parse.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 { LogMeta } from \"@powerlines/core\";\nimport { toArray } from \"@stryke/convert/to-array\";\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 (\n isSetObject(data) &&\n isSetObject(data.meta) &&\n isSetString((data.meta as LogMeta).type) &&\n (isSetString(data.message) || Array.isArray(data.message))\n ) {\n return {\n ...data,\n meta: data.meta as Omit<\n LogMeta,\n \"executionId\" | \"executionIndex\" | \"environment\" | \"timestamp\"\n >,\n message: toArray(data.message).filter(Boolean)\n };\n }\n\n throw new Error(\n `Invalid \"write-log\" message payload: ${JSON.stringify(data)}`\n );\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(\n `Invalid \"update-command\" message payload: ${JSON.stringify(data)}`\n );\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(\n `Invalid \"update-hook\" message payload: ${JSON.stringify(data)}`\n );\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(\n `Invalid \"update-plugin\" message payload: ${JSON.stringify(data)}`\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 { ExecutionWorkerParams, Logger } from \"@powerlines/core\";\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 { IpcMessage, IpcMessageType } from \"../ipc/messages\";\nimport { parseIpcMessage } from \"../ipc/parse\";\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 log 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: Logger;\n\n /**\n * A callback function that is called when the worker sends a log message. This can be used to handle log messages from the worker and integrate them with the parent process's logging system. The function should accept a `WriteLogIpcMessage` object as its argument, which contains the log message and associated metadata.\n */\n onIpcMessage?: (message: IpcMessage) => 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.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 NODE_OPTIONS: formattedNodeOptions,\n POWERLINES_WORKER_THREAD_EXECUTION: \"true\"\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 computeWorkerKey: (method: string, ...args: Array<unknown>) => {\n let executionParams: {\n method?: string;\n executionIndex?: number;\n name?: string;\n } = { method };\n if (args.length > 0 && isSetObject(args[0])) {\n const arg = args[0] as Partial<ExecutionWorkerParams>;\n if (isSetObject(arg.options)) {\n executionParams = {\n method,\n executionIndex: arg.options.executionIndex ?? 0,\n name: arg.options.name\n };\n }\n }\n\n return JSON.stringify(executionParams);\n },\n ...rest,\n forkOptions: {\n ...rest.forkOptions,\n silent: true,\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.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.trace(\n `Received IPC message from worker: ${JSON.stringify(message)}`\n );\n\n void Promise.resolve(this.options.onIpcMessage?.(message));\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 InitialConfig,\n LintInlineConfig,\n NewInlineConfig,\n PrepareInlineConfig,\n TestInlineConfig,\n TypesInlineConfig\n} from \"@powerlines/core\";\nimport { POWERLINES_API_FUNCTIONS } from \"@powerlines/core/constants\";\nimport { toArray } from \"@stryke/convert/to-array\";\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 {\n IpcMessage,\n IpcMessageType,\n UpdateCommandIpcMessage,\n UpdateHookIpcMessage,\n UpdatePluginIpcMessage,\n WriteLogIpcMessage\n} from \"./_internal/ipc/messages\";\nimport {\n parseUpdateCommandMessagePayload,\n parseUpdateHookMessagePayload,\n parseUpdatePluginMessagePayload,\n parseWriteLogMessagePayload\n} from \"./_internal/ipc/parse\";\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 * @param initialConfig - The initial configuration for the context, which can be used to provide additional context or override certain configuration values during initialization. This is particularly useful when initializing the context from a CLI command, where the CLI flags can be passed as part of the initial configuration to ensure they are properly merged with the configuration file and made available to plugins during their setup and execution.\n * @returns A new instance of the Powerlines Engine\n */\n public static async init(\n options: EngineOptions,\n initialConfig: InitialConfig<any> = {}\n ): Promise<PowerlinesEngine> {\n const api = new PowerlinesEngine(\n await PowerlinesEngineContext.init(options, initialConfig)\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 onIpcMessage: api.handleIpcMessage.bind(api),\n enableSourceMaps: options.mode === \"development\",\n exposedMethods: POWERLINES_API_FUNCTIONS,\n logger: api.context.extendLogger({ category: \"ipc\" })\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 * 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 initialConfig: this.#context.initialConfig,\n inlineConfig: 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 initialConfig: this.#context.initialConfig,\n inlineConfig: 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 initialConfig: this.#context.initialConfig,\n inlineConfig: 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 initialConfig: this.#context.initialConfig,\n inlineConfig: 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 initialConfig: this.#context.initialConfig,\n inlineConfig: 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 initialConfig: this.#context.initialConfig,\n inlineConfig: 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 initialConfig: this.#context.initialConfig,\n inlineConfig: 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(\"📓 Generating documentation for the Powerlines project\");\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 initialConfig: this.#context.initialConfig,\n inlineConfig: 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 initialConfig: this.#context.initialConfig,\n inlineConfig: 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 /**\n * Asynchronous disposal method for the Powerlines Engine, which will call the finalize method to perform any necessary cleanup when the engine is disposed of.\n */\n public async [Symbol.asyncDispose]() {\n return this.finalize();\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 * Handle incoming IPC messages from the worker processes, routing them to the appropriate handlers based on the message type.\n *\n * @param message - The IPC message received from a worker process\n */\n private async handleIpcMessage(message: IpcMessage) {\n switch (message.type) {\n case IpcMessageType.WRITE_LOG: {\n const payload = parseWriteLogMessagePayload(message.payload);\n\n this.context.logger.debug({\n meta: {\n category: \"ipc\",\n executionId: message.executionId,\n executionIndex: message.executionIndex,\n environment: message.environment\n },\n message: `Received a \"write-log\" IPC message from worker:\nType: ${payload.meta.type}\nMessage: ${toArray(payload.message).filter(Boolean).join(\"\\n\")}`\n });\n\n await this.handleWriteLog({\n ...message,\n type: IpcMessageType.WRITE_LOG,\n payload\n });\n\n break;\n }\n\n case IpcMessageType.UPDATE_COMMAND:\n this.context.logger.debug({\n meta: {\n category: \"ipc\",\n executionId: message.executionId,\n executionIndex: message.executionIndex,\n environment: message.environment\n },\n message: `Received an \"update-command\" IPC message from worker: \\n${JSON.stringify(\n message,\n null,\n 2\n )}`\n });\n\n await this.handleUpdateCommand({\n ...message,\n type: IpcMessageType.UPDATE_COMMAND,\n payload: parseUpdateCommandMessagePayload(message.payload)\n });\n\n break;\n\n case IpcMessageType.UPDATE_HOOK:\n this.context.logger.debug({\n meta: {\n category: \"ipc\",\n executionId: message.executionId,\n executionIndex: message.executionIndex,\n environment: message.environment\n },\n message: `Received an \"update-hook\" IPC message from worker: \\n${JSON.stringify(\n message,\n null,\n 2\n )}`\n });\n\n await this.handleUpdateHook({\n ...message,\n type: IpcMessageType.UPDATE_HOOK,\n payload: parseUpdateHookMessagePayload(message.payload)\n });\n\n break;\n\n case IpcMessageType.UPDATE_PLUGIN:\n this.context.logger.debug({\n meta: {\n category: \"ipc\",\n executionId: message.executionId,\n executionIndex: message.executionIndex,\n environment: message.environment\n },\n message: `Received an \"update-plugin\" IPC message from worker: \\n${JSON.stringify(\n message,\n null,\n 2\n )}`\n });\n\n await this.handleUpdatePlugin({\n ...message,\n type: IpcMessageType.UPDATE_PLUGIN,\n payload: parseUpdatePluginMessagePayload(message.payload)\n });\n\n break;\n\n case IpcMessageType.ACTIVITY:\n case undefined:\n default: {\n break;\n }\n }\n }\n\n private async handleWriteLog(message: WriteLogIpcMessage) {\n const { payload } = message;\n\n this.context.logger.log(payload.meta.type, {\n message: toArray(payload.message).filter(Boolean).join(\"\\n\"),\n meta: {\n category: payload.meta.category,\n logId: payload.meta.logId,\n name: payload.meta.name,\n executionId: message.executionId,\n executionIndex: message.executionIndex,\n command: payload.meta.command,\n hook: payload.meta.hook,\n environment: message.environment,\n plugin: payload.meta.plugin,\n source: payload.meta.source,\n timestamp: message.timestamp,\n $$ipc: true\n }\n });\n }\n\n private async handleUpdatePlugin(_: UpdatePluginIpcMessage) {}\n\n private async handleUpdateHook(_: UpdateHookIpcMessage) {}\n\n private async handleUpdateCommand(_: UpdateCommandIpcMessage) {}\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powerlines/engine",
3
- "version": "0.44.11",
3
+ "version": "0.45.0",
4
4
  "private": false,
5
5
  "description": "An internal package containing the core engine modules for Powerlines.",
6
6
  "homepage": "https://stormsoftware.com",
@@ -137,7 +137,7 @@
137
137
  "@cacheable/memory": "^2.0.8",
138
138
  "@donedeal0/superdiff": "^3.2.0",
139
139
  "@jridgewell/sourcemap-codec": "^1.5.5",
140
- "@powerlines/core": "^0.44.11",
140
+ "@powerlines/core": "^0.45.0",
141
141
  "@storm-software/config": "^1.137.34",
142
142
  "@storm-software/config-tools": "^1.190.1",
143
143
  "@stryke/async": "^0.1.0",
@@ -180,5 +180,5 @@
180
180
  "typescript": "^6.0.3",
181
181
  "undici-types": "^7.25.0"
182
182
  },
183
- "gitHead": "3068780d15828be90a57de9532ed00bd33187340"
183
+ "gitHead": "8a559d0939f118a77d189638644589ce33e56a7e"
184
184
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"base-context-C6yzgs6K.mjs","names":["joinPaths","#timestamp","createLogger"],"sources":["../src/_internal/helpers/resolver.ts","../src/context/base-context.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 { ResolvedConfig, Resolver } from \"@powerlines/core\";\nimport { joinPaths } from \"@stryke/path/join-paths\";\nimport defu from \"defu\";\nimport { JitiOptions, createJiti } from \"jiti\";\n\nexport type CreateResolverOptions = Omit<\n JitiOptions,\n \"fsCache\" | \"moduleCache\" | \"interopDefault\"\n> &\n Partial<Pick<ResolvedConfig, \"mode\" | \"skipCache\">> & {\n workspaceRoot: string;\n root: string;\n cacheDir: string;\n };\n\n/**\n * Create a Jiti resolver for the given workspace and project root.\n *\n * @param options - The options for creating the resolver.\n * @returns A Jiti instance configured for the specified workspace and project root.\n */\nfunction resolveOptions(options: CreateResolverOptions): JitiOptions {\n return defu(options, {\n interopDefault: true,\n fsCache:\n options.mode !== \"development\"\n ? joinPaths(options.cacheDir, \"jiti\")\n : false,\n moduleCache: options.mode !== \"development\"\n });\n}\n\n/**\n * Create a Jiti resolver for the given workspace and project root.\n *\n * @param options - The options for creating the resolver.\n * @returns A Jiti instance configured for the specified workspace and project root.\n */\nexport function createResolver(options: CreateResolverOptions): Resolver {\n const baseResolver = createJiti(\n joinPaths(options.workspaceRoot, options.root),\n resolveOptions(options)\n ) as Resolver;\n baseResolver.plugin = createJiti(\n joinPaths(options.workspaceRoot, options.root),\n resolveOptions(options)\n );\n\n return baseResolver;\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 BaseContext,\n EngineOptions,\n LogFn,\n Logger,\n LoggerOptions,\n LogLevelResolvedConfig,\n LogMessage,\n Mode,\n ParsedUserConfig,\n Resolver,\n WorkspaceConfig\n} from \"@powerlines/core\";\nimport { loadUserConfigFile } from \"@powerlines/core/lib/config\";\nimport { resolveLogLevel } from \"@powerlines/core/plugin-utils\";\nimport {\n createLogger,\n extendLogger\n} from \"@powerlines/core/plugin-utils/logging\";\nimport { tryGetWorkspaceConfig } from \"@storm-software/config-tools/get-config\";\nimport {\n isDevelopment,\n isProduction,\n isTest\n} from \"@stryke/env/environment-checks\";\nimport { EnvPaths, getEnvPaths } from \"@stryke/env/get-env-paths\";\nimport { readJsonFile } from \"@stryke/fs\";\nimport { resolvePackage } from \"@stryke/fs/resolve\";\nimport { joinPaths } from \"@stryke/path\";\nimport { appendPath } from \"@stryke/path/append\";\nimport { isEqual } from \"@stryke/path/is-equal\";\nimport { replacePath } from \"@stryke/path/replace\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport { isSetString } from \"@stryke/type-checks/is-set-string\";\nimport chalk from \"chalk\";\nimport { formatDistanceToNowStrict } from \"date-fns/formatDistanceToNowStrict\";\nimport defu from \"defu\";\nimport { existsSync } from \"node:fs\";\nimport { UserConfig } from \"tsdown/config\";\nimport { createResolver } from \"../_internal/helpers/resolver\";\n\nexport class PowerlinesBaseContext implements BaseContext {\n #timestamp: number = Date.now();\n\n /**\n * The path to the Powerlines package\n */\n public powerlinesPath!: string;\n\n /**\n * The module resolver for the project\n */\n public resolver!: Resolver;\n\n /**\n * The options provided to the Powerlines process\n */\n public options!: EngineOptions;\n\n /**\n * The input options used to initialize the context, which may be used when cloning the context to ensure the same configuration is applied to the new context\n */\n public inputOptions: Partial<EngineOptions> = {};\n\n /**\n * The parsed configuration file for the project\n */\n public configFile!: ParsedUserConfig;\n\n /**\n * The logger instance for the context, which can be used to create log messages with consistent formatting and metadata. This logger is extended by plugin contexts to include additional metadata such as the plugin name and category, which can be used to filter and format log messages in a more granular way.\n */\n public get logger(): Logger {\n return this.createLogger({});\n }\n\n /**\n * A timestamp representing when the context was initialized\n */\n public get timestamp(): number {\n return this.#timestamp;\n }\n\n public get logLevel(): LogLevelResolvedConfig {\n return resolveLogLevel(this.options.logLevel, this.options.mode);\n }\n\n /**\n * The environment paths for the project\n */\n public get envPaths(): EnvPaths {\n return getEnvPaths({\n orgId: this.options.organization,\n appId: this.options.framework || \"powerlines\",\n workspaceRoot: this.options.cwd\n });\n }\n\n /**\n * Creates a clone of the current context with the same configuration and workspace settings. This can be useful for running multiple builds in parallel or for creating isolated contexts for different parts of the build process.\n *\n * @remarks\n * The cloned context will have the same configuration and workspace settings as the original context, but will have a different build ID, release ID, and timestamp. The virtual file system and caches will also be separate between the original and cloned contexts.\n *\n * @returns A promise that resolves to the cloned context.\n */\n public async clone(): Promise<BaseContext> {\n const clone = new PowerlinesBaseContext();\n await clone.init(this.options);\n\n return clone;\n }\n\n /**\n * A logging function for fatal messages\n *\n * @param message - The message to log.\n */\n public fatal(message: string | LogMessage) {\n this.logger.error(message);\n }\n\n /**\n * A logging function for error messages\n *\n * @param message - The message to log.\n */\n public error(message: string | LogMessage) {\n this.logger.error(message);\n }\n\n /**\n * A logging function for warning messages\n *\n * @param message - The message to log.\n */\n public warn(message: string | LogMessage) {\n this.logger.warn(message);\n }\n\n /**\n * A logging function for informational messages\n *\n * @param message - The message to log.\n */\n public info(message: string | LogMessage) {\n this.logger.info(message);\n }\n\n /**\n * A logging function for debug messages\n *\n * @param message - The message to log.\n */\n public debug(message: string | LogMessage) {\n this.logger.debug(message);\n }\n\n /**\n * A logging function for trace messages\n *\n * @param message - The message to log.\n */\n public trace(message: string | LogMessage) {\n this.logger.trace(message);\n }\n\n /**\n * A function to create a timer for measuring the duration of asynchronous operations\n *\n * @example\n * ```ts\n * const stopTimer = context.timer(\"Your Async Operation\");\n * await performAsyncOperation();\n * stopTimer(); // \"Your Async Operation completed in 123.45 milliseconds\"\n * ```\n *\n * @param name - The name of the timer.\n * @returns A function that, when called, stops the timer and logs the duration.\n */\n public timer(name: string): () => void {\n const startDate = Date.now();\n const startDuration = performance.now();\n\n return () => {\n const duration = performance.now() - startDuration;\n this.logger.info({\n meta: {\n category: \"performance\"\n },\n message: `${chalk.bold.cyanBright(name)} completed in ${chalk.bold.cyanBright(\n duration < 1000\n ? `${duration.toFixed(2)} milliseconds`\n : formatDistanceToNowStrict(startDate)\n )}`\n });\n };\n }\n\n /**\n * Create a new logger instance\n *\n * @param options - The configuration options to use for the logger instance, which can be used to customize the appearance and behavior of the log messages generated by the logger. This is typically the name of the plugin or module that is creating the logger instance.\n * @param logFn - The custom logging function to use for logging messages, which can be used to override the default logging behavior of the original logger.\n * @returns A logger client instance that can be used to generate log messages with consistent formatting and metadata.\n */\n public createLogger(options: LoggerOptions, logFn?: LogFn): Logger {\n return createLogger(\n this.options.name || this.options.root,\n { ...this.configFile.config, ...this.options, ...options },\n logFn\n );\n }\n\n /**\n * Extend the base logger with additional configuration options\n *\n * @param options - The configuration options to extend the base logger with, which can be used to add additional metadata or customize the appearance of log messages generated by the logger. This is typically the name of the plugin or module that is creating the logger instance, as well as any additional metadata such as the plugin category or environment.\n * @returns A new logger client instance that extends the base logger with the provided configuration options.\n */\n public extendLogger(options: LoggerOptions): Logger {\n return extendLogger(this.logger, options);\n }\n\n /**\n * Retrieve the workspace configuration for the current project, if it exists. This function will look for a configuration file in the project root and return its contents as a JavaScript object. If no configuration file is found, it will return undefined.\n *\n * @returns A promise that resolves to the workspace configuration object, or undefined if no configuration file is found.\n */\n protected async getWorkspaceConfig(): Promise<WorkspaceConfig | undefined> {\n return tryGetWorkspaceConfig(\n false,\n this.options || this.inputOptions\n ? {\n cwd:\n this.options?.root || this.inputOptions?.root\n ? appendPath(\n this.options?.root || this.inputOptions?.root || \".\",\n this.options?.cwd || this.inputOptions?.cwd\n )\n : undefined,\n workspaceRoot: this.options?.cwd || this.inputOptions?.cwd\n }\n : undefined\n );\n }\n\n /**\n * Determine the default mode for the current execution based on the environment and workspace configuration. This function will check the `NODE_ENV` environment variable to determine if the current environment is development, production, or test. If `NODE_ENV` is not set, it will look for a `mode` property in the workspace configuration file. If no mode is specified in the workspace configuration, it will default to \"production\".\n *\n * @returns A promise that resolves to the default mode for the current execution, which can be \"development\", \"production\", or \"test\".\n */\n protected async getDefaultMode(): Promise<Mode> {\n const workspaceConfig = await this.getWorkspaceConfig();\n\n return isProduction\n ? \"production\"\n : isDevelopment\n ? \"development\"\n : isTest\n ? \"test\"\n : workspaceConfig?.mode || \"production\";\n }\n\n /**\n * Determine the default log level for the current execution based on the environment and workspace configuration. This function will check the `logLevel` property in the workspace configuration file and resolve it to a `LogLevelResolvedConfig` value. If no log level is specified in the workspace configuration, it will default to \"info\" for development mode and \"warn\" for production mode.\n *\n * @returns A promise that resolves to the default log level for the current execution, which can be \"fatal\", \"error\", \"warn\", \"info\", \"debug\", or \"trace\".\n */\n protected async getDefaultLogLevel(): Promise<LogLevelResolvedConfig> {\n const workspaceConfig = await this.getWorkspaceConfig();\n\n return resolveLogLevel(\n workspaceConfig?.logLevel\n ? workspaceConfig.logLevel === \"success\" ||\n workspaceConfig.logLevel === \"performance\"\n ? \"info\"\n : workspaceConfig.logLevel === \"all\"\n ? \"debug\"\n : workspaceConfig.logLevel === \"fatal\"\n ? \"error\"\n : workspaceConfig.logLevel\n : undefined,\n this.options?.mode ||\n this.inputOptions?.mode ||\n workspaceConfig?.mode ||\n (await this.getDefaultMode())\n );\n }\n\n /**\n * Initialize the context with the provided configuration options\n *\n * @remarks\n * This method will set up the resolver and load the user configuration file based on the provided options. It is called during the construction of the context and can also be called when cloning the context to ensure that the new context has the same configuration and resolver setup.\n *\n * @param options - The configuration options to initialize the context with\n */\n protected async init(options: EngineOptions) {\n this.inputOptions = { ...options };\n\n if (!this.powerlinesPath) {\n const powerlinesPath = await resolvePackage(\"powerlines\");\n if (!powerlinesPath) {\n throw new Error(\"Could not resolve `powerlines` package location.\");\n }\n this.powerlinesPath = powerlinesPath;\n }\n\n const cwd = options.cwd || this.options?.cwd || process.cwd();\n const root = replacePath(\n (options.root || this.options?.root) &&\n (options.root || this.options.root).replace(/^\\.\\/?/, \"\") &&\n !isEqual(options.root || this.options.root, cwd)\n ? options.root || this.options.root\n : \".\",\n cwd\n );\n\n this.options = defu(\n {\n name: options.name,\n root,\n cwd,\n mode: options.mode,\n logLevel: options.logLevel,\n framework: options.framework,\n organization: options.organization,\n configFile: options.configFile\n },\n this.options ?? {},\n {\n mode: await this.getDefaultMode(),\n logLevel: await this.getDefaultLogLevel()\n }\n );\n\n this.resolver = createResolver({\n workspaceRoot: cwd,\n root,\n cacheDir: this.envPaths.cache,\n mode: this.options.mode\n });\n\n this.configFile = await loadUserConfigFile(this.options, this.resolver);\n if (!this.options.name) {\n if (this.configFile.config) {\n if (\n isSetObject(this.configFile.config) &&\n isSetString((this.configFile.config as UserConfig).name)\n ) {\n this.options.name = (this.configFile.config as UserConfig).name;\n } else if (Array.isArray(this.configFile.config)) {\n for (const config of this.configFile.config) {\n if (\n isSetObject(config) &&\n isSetString((config as UserConfig).name)\n ) {\n this.options.name = (config as UserConfig).name;\n break;\n }\n }\n }\n }\n\n if (!this.options.name) {\n const packageJsonPath = joinPaths(\n appendPath(this.options.root, this.options.cwd),\n \"package.json\"\n );\n if (existsSync(packageJsonPath)) {\n const packageJson = await readJsonFile(packageJsonPath);\n this.options.name = packageJson.name;\n }\n\n if (!this.options.name) {\n const projectJsonPath = joinPaths(\n appendPath(this.options.root, this.options.cwd),\n \"project.json\"\n );\n if (existsSync(projectJsonPath)) {\n const projectJson = await readJsonFile(projectJsonPath);\n this.options.name = projectJson.name;\n }\n }\n }\n }\n }\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"engine-context-C-11i43N.mjs","names":["#executions"],"sources":["../src/context/engine-context.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 {\n EngineContext,\n EngineOptions,\n ExecutionState\n} from \"@powerlines/core\";\nimport { uuid } from \"@stryke/unique-id/uuid\";\nimport { PowerlinesBaseContext } from \"./base-context\";\n\nexport class PowerlinesEngineContext\n extends PowerlinesBaseContext\n implements EngineContext\n{\n #executions: ExecutionState[] = [];\n\n /**\n * Creates a new instance of the PowerlinesEngineContext class.\n *\n * @param options - The options to initialize the context with.\n * @returns A promise that resolves to an instance of the PowerlinesEngineContext class.\n */\n public static async fromOptions(\n options: EngineOptions\n ): Promise<PowerlinesEngineContext> {\n const context = new PowerlinesEngineContext();\n await context.init(options);\n\n if (!context.configFile?.config) {\n context.fatal(\n \"No configuration file found. Please ensure you have a valid configuration file in your project.\"\n );\n throw new Error(\"No configuration file found\");\n }\n\n if (Array.isArray(context.configFile.config)) {\n context.#executions = await Promise.all(\n context.configFile.config.map(async (_, executionIndex) => {\n const executionId = uuid();\n\n return {\n executionId,\n options: {\n ...context.options,\n executionId,\n executionIndex\n },\n active: {\n command: null,\n hook: null,\n plugin: null\n }\n };\n })\n );\n } else {\n const executionId = uuid();\n context.#executions = [\n {\n executionId,\n options: {\n ...context.options,\n executionId,\n executionIndex: 0\n },\n active: {\n command: null,\n hook: null,\n plugin: null\n }\n }\n ];\n }\n\n return context;\n }\n\n /**\n * A list of all command executions that will be run during the lifecycle of the engine\n *\n * @returns An array of {@link ExecutionState} representing each execution context for the engine.\n */\n public get executions(): ExecutionState[] {\n return this.#executions;\n }\n}\n"],"mappings":";;;;AA0BA,IAAa,0BAAb,MAAa,gCACH,sBAEV;CACE,cAAgC,EAAE;;;;;;;CAQlC,aAAoB,YAClB,SACkC;EAClC,MAAM,UAAU,IAAI,yBAAyB;AAC7C,QAAM,QAAQ,KAAK,QAAQ;AAE3B,MAAI,CAAC,QAAQ,YAAY,QAAQ;AAC/B,WAAQ,MACN,kGACD;AACD,SAAM,IAAI,MAAM,8BAA8B;;AAGhD,MAAI,MAAM,QAAQ,QAAQ,WAAW,OAAO,CAC1C,UAAQA,aAAc,MAAM,QAAQ,IAClC,QAAQ,WAAW,OAAO,IAAI,OAAO,GAAG,mBAAmB;GACzD,MAAM,cAAc,MAAM;AAE1B,UAAO;IACL;IACA,SAAS;KACP,GAAG,QAAQ;KACX;KACA;KACD;IACD,QAAQ;KACN,SAAS;KACT,MAAM;KACN,QAAQ;KACT;IACF;IACD,CACH;OACI;GACL,MAAM,cAAc,MAAM;AAC1B,YAAQA,aAAc,CACpB;IACE;IACA,SAAS;KACP,GAAG,QAAQ;KACX;KACA,gBAAgB;KACjB;IACD,QAAQ;KACN,SAAS;KACT,MAAM;KACN,QAAQ;KACT;IACF,CACF;;AAGH,SAAO;;;;;;;CAQT,IAAW,aAA+B;AACxC,SAAO,MAAKA"}