@orkestrel/process 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +69 -0
- package/dist/src/core/index.cjs +87 -0
- package/dist/src/core/index.cjs.map +1 -0
- package/dist/src/core/index.d.cts +351 -0
- package/dist/src/core/index.d.ts +351 -0
- package/dist/src/core/index.js +80 -0
- package/dist/src/core/index.js.map +1 -0
- package/dist/src/server/index.cjs +717 -0
- package/dist/src/server/index.cjs.map +1 -0
- package/dist/src/server/index.d.cts +379 -0
- package/dist/src/server/index.d.ts +379 -0
- package/dist/src/server/index.js +704 -0
- package/dist/src/server/index.js.map +1 -0
- package/package.json +91 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["#emitter","#child","#reader","#grace","#limit","#decoder","#exit","#lines","#buffer","#waiters","#signal","#abort","#iterate","#push","#finish","#close","#retain","#terminate","#tail","#closed","#stopping","#kill","#ending","#teardown","#next","#ended","#emitter","#children","#evict","#stopAll","#stopOne","#stopMany","#ending","#teardown"],"sources":["../../../src/server/helpers.ts","../../../src/server/Process.ts","../../../src/server/ProcessManager.ts","../../../src/server/factories.ts"],"sourcesContent":["import type { ChildProcessWithoutNullStreams } from 'node:child_process'\nimport type { ProcessCommand, RunOptions, RunResult } from '@src/core'\nimport { Buffer } from 'node:buffer'\nimport { spawn, spawnSync } from 'node:child_process'\nimport { extname } from 'node:path'\nimport { createRunError, PROCESS_GRACE, PROCESS_OUTPUT } from '@src/core'\n\n/**\n * Signals one owned child process, or its detached process group on a POSIX host.\n *\n * @remarks\n * On a POSIX host a child spawned `detached` leads its own process group, so signalling the\n * negated pid reaches the whole tree. On Windows, or when no pid is available, the signal goes to\n * the child directly. A throw during signalling is swallowed: the process can exit and win the\n * signal race, and the child's close event remains the authoritative terminal state.\n *\n * @param child - The child process signal boundary\n * @param signal - The signal to deliver\n * @returns Nothing\n *\n * @example\n * ```ts\n * killProcess(child, 'SIGTERM')\n * ```\n */\nexport function killProcess(\n\tchild: { readonly pid?: number | undefined; kill(signal: NodeJS.Signals): boolean },\n\tsignal: NodeJS.Signals,\n): void {\n\ttry {\n\t\tif (process.platform === 'win32' || child.pid === undefined) {\n\t\t\tchild.kill(signal)\n\t\t\treturn\n\t\t}\n\t\tprocess.kill(-child.pid, signal)\n\t} catch {\n\t\t// Exit can win the signal race; the close event remains authoritative.\n\t}\n}\n\n/**\n * Trims a buffer to at most `limit` trailing bytes without splitting a UTF-8 sequence.\n *\n * @remarks\n * Keeps the tail — the diagnostic end of a stderr stream. When the cut point lands inside a\n * multibyte sequence, the start advances past the leading continuation bytes so the retained\n * bytes always begin on a code-point boundary.\n *\n * @param buffer - The accumulated bytes\n * @param limit - The maximum retained byte count\n * @returns The trailing bytes, at most `limit` and never starting mid-sequence\n *\n * @example\n * ```ts\n * trimTail(Buffer.from('hello'), 3) // <Buffer 6c 6c 6f>\n * ```\n */\nexport function trimTail(buffer: Buffer, limit: number): Buffer {\n\tif (buffer.byteLength <= limit) return buffer\n\tlet start = buffer.byteLength - limit\n\twhile (start < buffer.byteLength) {\n\t\tconst byte = buffer[start]\n\t\tif (byte === undefined || (byte & 0xc0) !== 0x80) break\n\t\tstart += 1\n\t}\n\treturn Buffer.from(buffer.subarray(start))\n}\n\n/**\n * Trims a buffer to at most `limit` leading bytes without splitting a UTF-8 sequence.\n *\n * @remarks\n * Keeps the head — the captured start of a one-shot run's output. When the cut point lands inside\n * a multibyte sequence, the end retreats to the sequence's start so the retained bytes always end\n * on a code-point boundary and decode without a replacement character.\n *\n * @param buffer - The accumulated bytes\n * @param limit - The maximum retained byte count\n * @returns The leading bytes, at most `limit` and never ending mid-sequence\n *\n * @example\n * ```ts\n * trimHead(Buffer.from('hello'), 3) // <Buffer 68 65 6c>\n * ```\n */\nexport function trimHead(buffer: Buffer, limit: number): Buffer {\n\tif (buffer.byteLength <= limit) return buffer\n\tlet end = limit\n\twhile (end > 0) {\n\t\tconst byte = buffer[end]\n\t\tif (byte === undefined || (byte & 0xc0) !== 0x80) break\n\t\tend -= 1\n\t}\n\treturn Buffer.from(buffer.subarray(0, end))\n}\n\n/**\n * Checks whether a command file must be spawned through a shell on the current host.\n *\n * @remarks\n * Node v22+ refuses to spawn a Windows `.cmd` or `.bat` batch file directly and returns `EINVAL`,\n * and a bare command name such as `git` resolves through `PATHEXT` to a batch shim rather than an\n * executable. Both cases run through the shell. A POSIX host, and a Windows path carrying a real\n * executable extension such as `.exe`, spawn directly. When the result is `true`, treat the\n * command file and arguments as trusted: shell invocation exposes shell metacharacters.\n *\n * @param file - The command executable name or path\n * @returns True when the file must run through a shell; false when it spawns directly\n *\n * @example\n * ```ts\n * requiresShell('git') // true on Windows, false on POSIX\n * ```\n */\nexport function requiresShell(file: string): boolean {\n\tif (process.platform !== 'win32') return false\n\tconst lower = file.toLowerCase()\n\treturn lower.endsWith('.cmd') || lower.endsWith('.bat') || extname(file) === ''\n}\n\n/**\n * Renders one command into its diagnostic command line.\n *\n * @param command - The executable and its argument vector\n * @returns The space-joined command line, for a {@link RunResult} and error messages\n *\n * @example\n * ```ts\n * commandLine({ file: 'git', arguments: ['status'] }) // 'git status'\n * ```\n */\nexport function commandLine(command: ProcessCommand): string {\n\treturn [command.file, ...command.arguments].join(' ')\n}\n\n/**\n * Merges environment overrides over the current process environment.\n *\n * @remarks\n * Later maps override earlier ones and an `undefined` value unsets a key. The base is the parent\n * process environment, so a child inherits it unless a key is overridden or unset.\n *\n * @param base - The command's own environment overrides\n * @param override - Per-invocation overrides applied last\n * @returns The merged environment for a spawn\n *\n * @example\n * ```ts\n * mergeEnvironment({ TOKEN: 'a' }, { TOKEN: undefined }) // TOKEN unset\n * ```\n */\nexport function mergeEnvironment(\n\tbase?: Readonly<Record<string, string | undefined>>,\n\toverride?: Readonly<Record<string, string | undefined>>,\n): NodeJS.ProcessEnv {\n\treturn { ...process.env, ...base, ...override }\n}\n\n/**\n * Builds one settled {@link RunResult} from a completed one-shot run's captured bytes and exit.\n *\n * @remarks\n * `failed` is derived: a run failed when it timed out, was ended by a signal, or exited with a\n * code other than `0` — a `null` code from a spawn fault is therefore a failure. Both output\n * buffers are byte-bounded by `limit` before decoding.\n *\n * @param command - The diagnostic command line\n * @param stdout - The captured standard output bytes\n * @param stderr - The captured standard error bytes\n * @param code - The exit code, or `null` when a signal or spawn fault ended the run\n * @param signal - The terminating signal, or `null`\n * @param timedOut - If `true`, the run's own timeout elapsed; if `false`, it did not\n * @param limit - The maximum captured bytes for each stream\n * @returns The frozen run outcome\n *\n * @example\n * ```ts\n * buildRunResult('git status', Buffer.from('ok'), Buffer.alloc(0), 0, null, false, 1024)\n * ```\n */\nexport function buildRunResult(\n\tcommand: string,\n\tstdout: Buffer,\n\tstderr: Buffer,\n\tcode: number | null,\n\tsignal: string | null,\n\ttimedOut: boolean,\n\tlimit: number,\n): RunResult {\n\treturn Object.freeze({\n\t\tcommand,\n\t\tstdout: trimHead(stdout, limit).toString('utf8'),\n\t\tstderr: trimHead(stderr, limit).toString('utf8'),\n\t\tcode,\n\t\tsignal,\n\t\tfailed: timedOut || signal !== null || code !== 0,\n\t\ttimedOut,\n\t})\n}\n\n/**\n * Runs one command to completion, buffering its output, and settles with the outcome.\n *\n * @remarks\n * The child is spawned through the cross-platform command resolver ({@link requiresShell}) and, on\n * a POSIX host, detached so its whole process group can be terminated. Standard output and error\n * are each byte-bounded by `limit` (default {@link PROCESS_OUTPUT}). A positive `timeout` arms a\n * timer that terminates the child through `SIGTERM`, then `SIGKILL` after `grace`\n * (default {@link PROCESS_GRACE}); aborting `signal` terminates the same way. The child's\n * `environment` merges over the parent, then `options.environment` on top, and `options.input`\n * overrides `command.input`. Unless `reject` is `false`, a failed run rejects with a\n * {@link createRunError} carrying the {@link RunResult}.\n *\n * @param command - The executable, arguments, and optional environment and input\n * @param options - Working directory, timeout, grace, signal, capture limit, and reject behavior\n * @returns The settled run outcome\n * @throws A {@link ProcessError} carrying the {@link RunResult} when the run failed and `reject` is not `false`\n *\n * @example\n * ```ts\n * const result = await run({ file: 'git', arguments: ['status'] }, { workspace: process.cwd() })\n * ```\n */\nexport async function run(command: ProcessCommand, options?: RunOptions): Promise<RunResult> {\n\tconst limit = options?.limit ?? PROCESS_OUTPUT\n\tconst grace = options?.grace ?? PROCESS_GRACE\n\tconst timeout = options?.timeout ?? 0\n\tconst reject = options?.reject ?? true\n\tconst input = options?.input ?? command.input\n\tconst line = commandLine(command)\n\tconst settled = Promise.withResolvers<RunResult>()\n\tconst terminate = new AbortController()\n\tconst cleanup = new AbortController()\n\tlet stdout: Buffer = Buffer.alloc(0)\n\tlet stderr: Buffer = Buffer.alloc(0)\n\tlet timedOut = false\n\tlet killTimer: ReturnType<typeof setTimeout> | undefined\n\tlet timeoutTimer: ReturnType<typeof setTimeout> | undefined\n\tlet done = false\n\n\tconst child: ChildProcessWithoutNullStreams = spawn(command.file, [...command.arguments], {\n\t\tcwd: options?.workspace ?? process.cwd(),\n\t\tdetached: process.platform !== 'win32',\n\t\tenv: mergeEnvironment(command.environment, options?.environment),\n\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\tshell: requiresShell(command.file),\n\t\twindowsHide: true,\n\t})\n\n\tterminate.signal.addEventListener(\n\t\t'abort',\n\t\t() => {\n\t\t\tkillProcess(child, 'SIGTERM')\n\t\t\tkillTimer = setTimeout(() => killProcess(child, 'SIGKILL'), grace)\n\t\t},\n\t\t{ once: true },\n\t)\n\n\tchild.stdin.on('error', () => undefined)\n\tchild.stdout.on('data', (chunk: unknown) => {\n\t\tif (Buffer.isBuffer(chunk)) stdout = trimHead(Buffer.concat([stdout, chunk]), limit)\n\t})\n\tchild.stderr.on('data', (chunk: unknown) => {\n\t\tif (Buffer.isBuffer(chunk)) stderr = trimHead(Buffer.concat([stderr, chunk]), limit)\n\t})\n\tchild.once('error', () => {\n\t\tif (done) return\n\t\tdone = true\n\t\tcleanup.abort()\n\t\tclearTimeout(killTimer)\n\t\tclearTimeout(timeoutTimer)\n\t\tsettled.resolve(buildRunResult(line, stdout, stderr, null, null, false, limit))\n\t})\n\tchild.once('close', (code: number | null, signal: NodeJS.Signals | null) => {\n\t\tif (done) return\n\t\tdone = true\n\t\tcleanup.abort()\n\t\tclearTimeout(killTimer)\n\t\tclearTimeout(timeoutTimer)\n\t\tsettled.resolve(buildRunResult(line, stdout, stderr, code, signal, timedOut, limit))\n\t})\n\n\tif (input !== undefined) child.stdin.write(input)\n\tchild.stdin.end()\n\tif (timeout > 0) {\n\t\ttimeoutTimer = setTimeout(() => {\n\t\t\ttimedOut = true\n\t\t\tterminate.abort()\n\t\t}, timeout)\n\t}\n\tif (options?.signal !== undefined) {\n\t\tconst signal = options.signal\n\t\tsignal.addEventListener('abort', () => terminate.abort(), {\n\t\t\tonce: true,\n\t\t\tsignal: cleanup.signal,\n\t\t})\n\t\tif (signal.aborted) terminate.abort()\n\t}\n\n\tconst result = await settled.promise\n\tif (result.failed && reject) throw createRunError(result)\n\treturn result\n}\n\n/**\n * Runs one command to completion synchronously, buffering its output, and returns the outcome.\n *\n * @remarks\n * The synchronous counterpart of {@link run}. The child is spawned through the same cross-platform\n * command resolver ({@link requiresShell}). Standard output and error are each byte-bounded by\n * `limit` (default {@link PROCESS_OUTPUT}). A positive `timeout` is enforced by the host, which\n * ends the child with `SIGKILL` when it elapses. The environment and input follow the same merge\n * as {@link run}. Unless `reject` is `false`, a failed run throws a {@link createRunError} carrying\n * the {@link RunResult}.\n *\n * @param command - The executable, arguments, and optional environment and input\n * @param options - Working directory, timeout, signal, capture limit, and reject behavior\n * @returns The run outcome\n * @throws A {@link ProcessError} carrying the {@link RunResult} when the run failed and `reject` is not `false`\n *\n * @example\n * ```ts\n * const result = runSync({ file: 'git', arguments: ['--version'] }, { reject: false })\n * ```\n */\nexport function runSync(command: ProcessCommand, options?: RunOptions): RunResult {\n\tconst limit = options?.limit ?? PROCESS_OUTPUT\n\tconst timeout = options?.timeout ?? 0\n\tconst reject = options?.reject ?? true\n\tconst input = options?.input ?? command.input\n\tconst line = commandLine(command)\n\tconst outcome = spawnSync(command.file, [...command.arguments], {\n\t\tcwd: options?.workspace ?? process.cwd(),\n\t\tenv: mergeEnvironment(command.environment, options?.environment),\n\t\tencoding: 'buffer',\n\t\tmaxBuffer: limit,\n\t\tshell: requiresShell(command.file),\n\t\twindowsHide: true,\n\t\t...(input !== undefined ? { input } : {}),\n\t\t...(options?.signal !== undefined ? { signal: options.signal } : {}),\n\t\t...(timeout > 0 ? { timeout, killSignal: 'SIGKILL' } : {}),\n\t})\n\tconst error = outcome.error\n\tconst timedOut = error !== undefined && 'code' in error && error.code === 'ETIMEDOUT'\n\tconst stdout = Buffer.isBuffer(outcome.stdout) ? outcome.stdout : Buffer.alloc(0)\n\tconst stderr = Buffer.isBuffer(outcome.stderr) ? outcome.stderr : Buffer.alloc(0)\n\tconst result = buildRunResult(\n\t\tline,\n\t\tstdout,\n\t\tstderr,\n\t\toutcome.status,\n\t\toutcome.signal,\n\t\ttimedOut,\n\t\tlimit,\n\t)\n\tif (result.failed && reject) throw createRunError(result)\n\treturn result\n}\n","import type { ChildProcessWithoutNullStreams } from 'node:child_process'\nimport type { Interface as ReadLineInterface } from 'node:readline'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { ProcessEventMap, ProcessExit, ProcessInterface, ProcessOptions } from '@src/core'\nimport { Buffer } from 'node:buffer'\nimport { spawn } from 'node:child_process'\nimport { createInterface } from 'node:readline'\nimport { StringDecoder } from 'node:string_decoder'\nimport { Emitter } from '@orkestrel/emitter'\nimport { PROCESS_EVIDENCE } from '@src/core'\nimport { killProcess, mergeEnvironment, trimTail } from './helpers.js'\n\n/**\n * One supervised child process with eagerly framed output and bounded termination.\n *\n * @remarks\n * Standard output is drained eagerly through `readline`, so `exit` resolves and a late consumer of\n * `lines` still receives every framed line, including a final line written without a trailing\n * newline. Standard error is decoded and forwarded live as the `stderr` event while a byte-bounded\n * raw tail is retained as `evidence`. The typed `emitter` also carries the terminal `exit`,\n * alongside the `exit` promise. `stop` terminates the child through `SIGTERM`, then `SIGKILL` after\n * `grace`, and is idempotent; `destroy` stops the child and destroys the emitter last.\n *\n * @example\n * ```ts\n * import { Process } from '@orkestrel/process/server'\n *\n * const child = new Process({\n * \tcommand: { file: 'node', arguments: ['--version'] },\n * \tworkspace: process.cwd(),\n * \tgrace: 5000,\n * })\n * const exit = await child.exit\n * await child.destroy()\n * ```\n */\nexport class Process implements ProcessInterface {\n\treadonly #emitter: Emitter<ProcessEventMap>\n\treadonly #child: ChildProcessWithoutNullStreams\n\treadonly #reader: ReadLineInterface\n\treadonly #grace: number\n\treadonly #limit: number\n\treadonly #decoder = new StringDecoder('utf8')\n\treadonly #exit = Promise.withResolvers<ProcessExit>()\n\treadonly #lines: AsyncIterable<string>\n\treadonly #buffer: string[] = []\n\treadonly #waiters: Array<PromiseWithResolvers<IteratorResult<string, void>>> = []\n\treadonly #signal: AbortSignal | undefined\n\treadonly #abort: EventListener | undefined\n\t#tail: Buffer = Buffer.alloc(0)\n\t#closed = false\n\t#ended = false\n\t#stopping: Promise<void> | undefined\n\t#ending: Promise<void> | undefined\n\n\t/**\n\t * Spawn one child process and begin eager stream capture.\n\t *\n\t * @param options - Command, workspace, termination, evidence, stdin, and observation settings\n\t */\n\tconstructor(options: ProcessOptions) {\n\t\tconst on = options.on\n\t\tconst error = options.error\n\t\tthis.#emitter = new Emitter<ProcessEventMap>({\n\t\t\t...(on === undefined ? {} : { on }),\n\t\t\t...(error === undefined ? {} : { error }),\n\t\t})\n\t\tthis.#grace = options.grace\n\t\tthis.#limit = options.evidence ?? PROCESS_EVIDENCE\n\t\tthis.#signal = options.signal\n\t\tthis.#lines = Object.freeze({ [Symbol.asyncIterator]: this.#iterate.bind(this) })\n\t\tthis.#child = spawn(options.command.file, [...options.command.arguments], {\n\t\t\tcwd: options.workspace,\n\t\t\tdetached: process.platform !== 'win32',\n\t\t\tenv: mergeEnvironment(options.command.environment),\n\t\t\tstdio: ['pipe', 'pipe', 'pipe'],\n\t\t\twindowsHide: true,\n\t\t})\n\t\tthis.#reader = createInterface({ input: this.#child.stdout, crlfDelay: Infinity })\n\t\tthis.#reader.on('line', this.#push.bind(this))\n\t\tthis.#reader.once('close', this.#finish.bind(this))\n\t\tthis.#child.once('error', () => undefined)\n\t\tthis.#child.once('close', this.#close.bind(this))\n\t\tthis.#child.stdin.on('error', () => undefined)\n\t\tthis.#child.stderr.on('data', this.#retain.bind(this))\n\t\tif (options.command.input !== undefined) this.#child.stdin.write(options.command.input)\n\t\tif (options.writable !== true) this.#child.stdin.end()\n\t\tif (this.#signal !== undefined) {\n\t\t\tthis.#abort = this.#terminate.bind(this)\n\t\t\tthis.#signal.addEventListener('abort', this.#abort, { once: true })\n\t\t\tif (this.#signal.aborted) void this.stop()\n\t\t}\n\t}\n\n\t/** The typed lifecycle observation surface. */\n\tget emitter(): EmitterInterface<ProcessEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\t/** The eagerly captured stdout lines, in arrival order, ending when the child's stdout closes. */\n\tget lines(): AsyncIterable<string> {\n\t\treturn this.#lines\n\t}\n\n\t/** The decoded byte-bounded stderr tail. */\n\tget evidence(): string {\n\t\treturn this.#tail.toString('utf8')\n\t}\n\n\t/** The terminal child state, observed once from the close event. */\n\tget exit(): Promise<ProcessExit> {\n\t\treturn this.#exit.promise\n\t}\n\n\t/**\n\t * Write one line to the open standard-input channel.\n\t *\n\t * @param text - The line text without its trailing newline\n\t * @returns True when the channel accepted the line without backpressure; false otherwise\n\t */\n\tsend(text: string): boolean {\n\t\tif (this.#closed || this.#child.stdin.destroyed || this.#child.stdin.writableEnded) return false\n\t\ttry {\n\t\t\treturn this.#child.stdin.write(`${text}\\n`)\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Terminate the child process tree and await its observed exit.\n\t *\n\t * @returns A promise that resolves after bounded termination\n\t */\n\tstop(): Promise<void> {\n\t\tif (this.#stopping !== undefined) return this.#stopping\n\t\tthis.#stopping = this.#kill()\n\t\treturn this.#stopping\n\t}\n\n\t/**\n\t * Stop the child and destroy the observation emitter.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tdestroy(): Promise<void> {\n\t\tif (this.#ending !== undefined) return this.#ending\n\t\tthis.#ending = this.#teardown()\n\t\treturn this.#ending\n\t}\n\n\t#iterate(): AsyncIterator<string, void, void> {\n\t\treturn Object.freeze({ next: this.#next.bind(this) })\n\t}\n\n\t#next(): Promise<IteratorResult<string, void>> {\n\t\tconst line = this.#buffer.shift()\n\t\tif (line !== undefined) return Promise.resolve(Object.freeze({ done: false, value: line }))\n\t\tif (this.#ended) return Promise.resolve(Object.freeze({ done: true, value: undefined }))\n\t\tconst waiter = Promise.withResolvers<IteratorResult<string, void>>()\n\t\tthis.#waiters.push(waiter)\n\t\treturn waiter.promise\n\t}\n\n\t#push(line: string): void {\n\t\tif (this.#ended) return\n\t\tconst waiter = this.#waiters.shift()\n\t\tif (waiter === undefined) {\n\t\t\tthis.#buffer.push(line)\n\t\t\treturn\n\t\t}\n\t\twaiter.resolve(Object.freeze({ done: false, value: line }))\n\t}\n\n\t#finish(): void {\n\t\tif (this.#ended) return\n\t\tthis.#ended = true\n\t\tfor (const waiter of this.#waiters) {\n\t\t\twaiter.resolve(Object.freeze({ done: true, value: undefined }))\n\t\t}\n\t\tthis.#waiters.length = 0\n\t}\n\n\t#retain(chunk: unknown): void {\n\t\tif (!Buffer.isBuffer(chunk) || this.#closed) return\n\t\tthis.#tail = trimTail(Buffer.concat([this.#tail, chunk]), this.#limit)\n\t\tconst text = this.#decoder.write(chunk)\n\t\tif (text.length > 0) this.#emitter.emit('stderr', text)\n\t}\n\n\t#close(code: number | null, signal: NodeJS.Signals | null): void {\n\t\tif (this.#closed) return\n\t\tconst suffix = this.#decoder.end()\n\t\tif (suffix.length > 0) this.#emitter.emit('stderr', suffix)\n\t\tthis.#closed = true\n\t\tif (this.#signal !== undefined && this.#abort !== undefined) {\n\t\t\tthis.#signal.removeEventListener('abort', this.#abort)\n\t\t}\n\t\tthis.#reader.close()\n\t\tconst exit = Object.freeze({ code, signal })\n\t\tthis.#exit.resolve(exit)\n\t\tthis.#emitter.emit('exit', exit)\n\t}\n\n\t#terminate(): void {\n\t\tvoid this.stop()\n\t}\n\n\tasync #kill(): Promise<void> {\n\t\tif (this.#closed) return\n\t\tkillProcess(this.#child, 'SIGTERM')\n\t\tconst grace = Promise.withResolvers<void>()\n\t\tconst timer = setTimeout(grace.resolve, this.#grace)\n\t\tawait Promise.race([this.#exit.promise, grace.promise])\n\t\tclearTimeout(timer)\n\t\tif (this.#closed) return\n\t\tkillProcess(this.#child, 'SIGKILL')\n\t\tawait this.#exit.promise\n\t}\n\n\tasync #teardown(): Promise<void> {\n\t\tawait this.stop()\n\t\tthis.#emitter.destroy()\n\t}\n}\n","import type { EmitterInterface } from '@orkestrel/emitter'\nimport type {\n\tProcessExit,\n\tProcessInterface,\n\tProcessManagerEventMap,\n\tProcessManagerInterface,\n\tProcessManagerOptions,\n\tProcessOptions,\n} from '@src/core'\nimport { Emitter } from '@orkestrel/emitter'\nimport { createDuplicateError } from '@src/core'\nimport { Process } from './Process.js'\n\n/**\n * A keyed registry of live supervised child processes.\n *\n * @remarks\n * A child launched under an id joins the registry and emits `launch`; when it settles it removes\n * itself and emits `exit`, so `count` and `processes` reflect only live children. `launch` throws\n * a {@link createDuplicateError} when the id is already live — a spawn fault surfaces through the\n * returned child's `exit`, never from `launch`. `destroy` stops every child, then destroys the\n * registry emitter last.\n *\n * @example\n * ```ts\n * import { ProcessManager } from '@orkestrel/process/server'\n *\n * const manager = new ProcessManager()\n * const child = manager.launch('build', {\n * \tcommand: { file: 'node', arguments: ['build.js'] },\n * \tworkspace: process.cwd(),\n * \tgrace: 5000,\n * })\n * await child.exit\n * await manager.destroy()\n * ```\n */\nexport class ProcessManager implements ProcessManagerInterface {\n\treadonly #emitter: Emitter<ProcessManagerEventMap>\n\treadonly #children = new Map<string, ProcessInterface>()\n\t#ending: Promise<void> | undefined\n\n\t/**\n\t * Construct a process registry.\n\t *\n\t * @param options - Initial fleet-level observation hooks and listener-error handling\n\t */\n\tconstructor(options?: ProcessManagerOptions) {\n\t\tconst on = options?.on\n\t\tconst error = options?.error\n\t\tthis.#emitter = new Emitter<ProcessManagerEventMap>({\n\t\t\t...(on === undefined ? {} : { on }),\n\t\t\t...(error === undefined ? {} : { error }),\n\t\t})\n\t}\n\n\t/** The typed fleet-level observation surface. */\n\tget emitter(): EmitterInterface<ProcessManagerEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\t/** The number of live children. */\n\tget count(): number {\n\t\treturn this.#children.size\n\t}\n\n\t/**\n\t * The live child under `id`, or `undefined` when none is.\n\t *\n\t * @param id - The registry key\n\t * @returns The child, or `undefined`\n\t */\n\tprocess(id: string): ProcessInterface | undefined {\n\t\treturn this.#children.get(id)\n\t}\n\n\t/**\n\t * A snapshot of every live child.\n\t *\n\t * @returns The live children in launch order\n\t */\n\tprocesses(): readonly ProcessInterface[] {\n\t\treturn [...this.#children.values()]\n\t}\n\n\t/**\n\t * Spawn and register one child under `id`.\n\t *\n\t * @param id - The registry key, unique among live children\n\t * @param options - The child construction options\n\t * @returns The launched child\n\t * @throws A {@link ProcessError} coded `duplicate` when `id` is already live\n\t */\n\tlaunch(id: string, options: ProcessOptions): ProcessInterface {\n\t\tif (this.#children.has(id)) throw createDuplicateError(id)\n\t\tconst child = new Process(options)\n\t\tthis.#children.set(id, child)\n\t\tchild.emitter.on('exit', (exit) => this.#evict(id, child, exit))\n\t\tthis.#emitter.emit('launch', id)\n\t\treturn child\n\t}\n\n\t/**\n\t * Terminate the named children and await their exit.\n\t *\n\t * @param ids - The registry keys to stop\n\t * @returns True when every named child stopped, false when any id was not live\n\t */\n\tstop(ids: readonly string[]): Promise<boolean>\n\t/**\n\t * Terminate one child and await its exit.\n\t *\n\t * @param id - The registry key to stop\n\t * @returns True when the child was live and stopped, false when the id was not live\n\t */\n\tstop(id: string): Promise<boolean>\n\t/**\n\t * Terminate every live child and await their exit.\n\t *\n\t * @returns A promise that resolves after all children stop\n\t */\n\tstop(): Promise<void>\n\tstop(target?: string | readonly string[]): Promise<boolean | void> {\n\t\tif (target === undefined) return this.#stopAll()\n\t\tif (typeof target === 'string') return this.#stopOne(target)\n\t\treturn this.#stopMany(target)\n\t}\n\n\t/**\n\t * Stop every child, then destroy the registry emitter last.\n\t *\n\t * @returns The stable barrier shared by every call\n\t */\n\tdestroy(): Promise<void> {\n\t\tif (this.#ending !== undefined) return this.#ending\n\t\tthis.#ending = this.#teardown()\n\t\treturn this.#ending\n\t}\n\n\t#evict(id: string, child: ProcessInterface, exit: ProcessExit): void {\n\t\tif (this.#children.get(id) !== child) return\n\t\tthis.#children.delete(id)\n\t\tthis.#emitter.emit('exit', id, exit)\n\t}\n\n\tasync #stopOne(id: string): Promise<boolean> {\n\t\tconst child = this.#children.get(id)\n\t\tif (child === undefined) return false\n\t\tawait child.stop()\n\t\treturn true\n\t}\n\n\tasync #stopMany(ids: readonly string[]): Promise<boolean> {\n\t\tconst stopped = await Promise.all(ids.map((id) => this.#stopOne(id)))\n\t\treturn stopped.every((ok) => ok)\n\t}\n\n\tasync #stopAll(): Promise<void> {\n\t\tawait Promise.all([...this.#children.values()].map((child) => child.stop()))\n\t}\n\n\tasync #teardown(): Promise<void> {\n\t\tawait Promise.all([...this.#children.values()].map((child) => child.destroy()))\n\t\tthis.#emitter.destroy()\n\t}\n}\n","import type {\n\tProcessInterface,\n\tProcessManagerInterface,\n\tProcessManagerOptions,\n\tProcessOptions,\n} from '@src/core'\nimport { Process } from './Process.js'\nimport { ProcessManager } from './ProcessManager.js'\n\n/**\n * Creates one supervised child process.\n *\n * @param options - Command, workspace, termination, evidence, stdin, and observation settings\n * @returns The launched {@link ProcessInterface}\n *\n * @example\n * ```ts\n * import { createProcess } from '@orkestrel/process/server'\n *\n * const child = createProcess({\n * \tcommand: { file: 'node', arguments: ['--version'] },\n * \tworkspace: process.cwd(),\n * \tgrace: 5000,\n * })\n * ```\n */\nexport function createProcess(options: ProcessOptions): ProcessInterface {\n\treturn new Process(options)\n}\n\n/**\n * Creates one keyed registry of supervised child processes.\n *\n * @param options - Initial fleet-level observation hooks and listener-error handling\n * @returns The {@link ProcessManagerInterface} registry\n *\n * @example\n * ```ts\n * import { createProcessManager } from '@orkestrel/process/server'\n *\n * const manager = createProcessManager()\n * ```\n */\nexport function createProcessManager(options?: ProcessManagerOptions): ProcessManagerInterface {\n\treturn new ProcessManager(options)\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@orkestrel/process",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "The @orkestrel/process package.",
|
|
5
|
+
"keywords": [],
|
|
6
|
+
"homepage": "https://github.com/orkestrel/process#readme",
|
|
7
|
+
"bugs": "https://github.com/orkestrel/process/issues",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/orkestrel/process.git"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/src",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"type": "module",
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"main": "./dist/src/core/index.cjs",
|
|
20
|
+
"module": "./dist/src/core/index.js",
|
|
21
|
+
"exports": {
|
|
22
|
+
".": {
|
|
23
|
+
"import": {
|
|
24
|
+
"types": "./dist/src/core/index.d.ts",
|
|
25
|
+
"default": "./dist/src/core/index.js"
|
|
26
|
+
},
|
|
27
|
+
"require": {
|
|
28
|
+
"types": "./dist/src/core/index.d.cts",
|
|
29
|
+
"default": "./dist/src/core/index.cjs"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"./server": {
|
|
33
|
+
"import": {
|
|
34
|
+
"types": "./dist/src/server/index.d.ts",
|
|
35
|
+
"default": "./dist/src/server/index.js"
|
|
36
|
+
},
|
|
37
|
+
"require": {
|
|
38
|
+
"types": "./dist/src/server/index.d.cts",
|
|
39
|
+
"default": "./dist/src/server/index.cjs"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"./package.json": "./package.json"
|
|
43
|
+
},
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
49
|
+
"copy": "node -e \"const fs=require('node:fs'),p=require('node:path'),a=process.argv[1],b=process.argv[2];fs.mkdirSync(p.dirname(b),{recursive:true});fs.cpSync(a,b,{force:true});console.log('Copied: '+a+' to '+b)\"",
|
|
50
|
+
"format": "oxfmt --config .oxfmtrc.json --write .",
|
|
51
|
+
"format:check": "oxfmt --config .oxfmtrc.json --check .",
|
|
52
|
+
"lint": "oxlint --config .oxlintrc.json --fix .",
|
|
53
|
+
"lint:check": "oxlint --config .oxlintrc.json --deny-warnings .",
|
|
54
|
+
"check": "tsc --noEmit --project tsconfig.json && npm run check:src",
|
|
55
|
+
"check:src": "npm run check:src:core && npm run check:src:server",
|
|
56
|
+
"check:src:core": "tsc --noEmit -p configs/src/tsconfig.core.json",
|
|
57
|
+
"check:src:server": "tsc --noEmit -p configs/src/tsconfig.server.json",
|
|
58
|
+
"test": "npm run test:src && npm run test:policy && npm run test:config",
|
|
59
|
+
"test:src": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core --project src:server",
|
|
60
|
+
"test:src:core": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core",
|
|
61
|
+
"test:src:server": "vitest run --config vite.config.ts --no-cache --reporter=dot --project src:server",
|
|
62
|
+
"test:policy": "vitest run --config vite.config.ts --no-cache --reporter=dot --project policy",
|
|
63
|
+
"test:config": "vitest run --config vite.config.ts --no-cache --reporter=dot --project config",
|
|
64
|
+
"test:probe": "vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe",
|
|
65
|
+
"build": "npm run clean && npm run build:src",
|
|
66
|
+
"build:src": "npm run build:src:core && npm run build:src:server",
|
|
67
|
+
"build:src:core": "vite build --config configs/src/vite.core.config.ts && npm run copy dist/src/core/index.d.ts dist/src/core/index.d.cts",
|
|
68
|
+
"build:src:server": "vite build --config configs/src/vite.server.config.ts && npm run copy dist/src/server/index.d.ts dist/src/server/index.d.cts",
|
|
69
|
+
"prepublishOnly": "npm run format:check && npm run lint:check && npm run check && npm run build && npm test"
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"@orkestrel/contract": "^0.0.12",
|
|
73
|
+
"@orkestrel/emitter": "^0.0.7"
|
|
74
|
+
},
|
|
75
|
+
"devDependencies": {
|
|
76
|
+
"@microsoft/api-extractor": "^7.58.12",
|
|
77
|
+
"@orkestrel/guide": "^0.0.12",
|
|
78
|
+
"@orkestrel/scaffold": "^0.0.43",
|
|
79
|
+
"@orkestrel/test": "^0.0.7",
|
|
80
|
+
"@types/node": "^26.2.0",
|
|
81
|
+
"oxfmt": "^0.62.0",
|
|
82
|
+
"oxlint": "^1.77.0",
|
|
83
|
+
"typescript": "^6.0.3",
|
|
84
|
+
"vite": "~8.2.0",
|
|
85
|
+
"vite-plugin-dts": "^5.0.3",
|
|
86
|
+
"vitest": "^4.1.10"
|
|
87
|
+
},
|
|
88
|
+
"engines": {
|
|
89
|
+
"node": ">=22.12.0"
|
|
90
|
+
}
|
|
91
|
+
}
|