| 192 | } |
| 193 | |
| 194 | async function runShellCommand(command: string): Promise<{ |
| 195 | stdout: string; |
| 196 | stderr: string; |
| 197 | exitCode: number; |
| 198 | }> { |
| 199 | const childProcess = await import("node:child_process"); |
| 200 | return await new Promise((resolve, reject) => { |
| 201 | const child = childProcess.spawn("bash", ["-lc", command], { |
| 202 | stdio: ["ignore", "pipe", "pipe"], |
| 203 | }); |
| 204 | let stdout = ""; |
| 205 | let stderr = ""; |
| 206 | child.stdout.on("data", (chunk: Buffer | string) => { |
| 207 | stdout += String(chunk); |
| 208 | }); |
| 209 | child.stderr.on("data", (chunk: Buffer | string) => { |
| 210 | stderr += String(chunk); |
| 211 | }); |
| 212 | child.on("error", (err: unknown) => { |
| 213 | reject(err); |
| 214 | }); |
| 215 | child.on("close", (code: number | null) => { |
| 216 | const exitCode = code ?? 1; |
| 217 | const result = { stdout, stderr, exitCode }; |
| 218 | if (exitCode === 0) { |
| 219 | resolve(result); |
| 220 | return; |
| 221 | } |
| 222 | reject(new Error(stderr || `Command failed with exit code ${exitCode}`)); |
| 223 | }); |
| 224 | }); |
| 225 | } |
| 226 | |
| 227 | function createShell(): (parts: TemplateStringsArray, ...values: unknown[]) => Promise<unknown> { |
| 228 | const maybeBun = (globalThis as UnknownRecord)["Bun"]; |