| |
| import { extractErrorCode } from "../infra/errors.js"; |
| import { createSanitizedCommandError } from "../process/exec-result.js"; |
| import { runCommandWithTimeout, type SpawnResult } from "../process/exec.js"; |
| import { resolveServiceManagerEnv } from "./service-process-env.js"; |
| import { assertGatewayServiceUpdateCurrent } from "./service-update-authority.js"; |
|
|
| export type ExecResult = Pick<SpawnResult, "stdout" | "stderr"> & { |
| code: number; |
| termination: SpawnResult["termination"] | "error"; |
| errorCode?: string; |
| }; |
|
|
| |
| export async function execFileUtf8( |
| command: string, |
| args: string[], |
| options: { |
| cwd?: string; |
| env?: NodeJS.ProcessEnv; |
| timeout?: number; |
| killSignal?: NodeJS.Signals | number; |
| windowsHide?: boolean; |
| } = {}, |
| ): Promise<ExecResult> { |
| assertGatewayServiceUpdateCurrent(); |
| try { |
| const { stdout, stderr, code, termination, signal } = await runCommandWithTimeout( |
| [command, ...args], |
| { |
| baseEnv: resolveServiceManagerEnv(options.env), |
| |
| cwd: options.cwd ?? (process.platform === "win32" ? undefined : "/"), |
| killSignal: options.killSignal, |
| maxOutputBytes: 1024 * 1024, |
| timeoutMs: options.timeout, |
| }, |
| ); |
| const diagnostic = |
| termination === "exit" |
| ? "" |
| : createSanitizedCommandError({ |
| timedOut: termination === "timeout" || termination === "no-output-timeout", |
| isTerminated: true, |
| signal, |
| }).message; |
| |
| return { |
| stdout, |
| stderr: [stderr, diagnostic].filter(Boolean).join("\n"), |
| code: termination === "exit" ? (code ?? 1) : code || 1, |
| termination, |
| }; |
| } catch (error) { |
| const message = error instanceof Error ? error.message : String(error); |
| const errorCode = extractErrorCode(error); |
| |
| |
| return { stdout: "", stderr: message, code: 1, termination: "error", errorCode }; |
| } |
| } |
|
|