| 37 | * ``` |
| 38 | */ |
| 39 | export class ShellCliAdapter implements CliAdapter { |
| 40 | readonly name: string; |
| 41 | readonly description: string; |
| 42 | |
| 43 | private command: string; |
| 44 | private env: Record<string, string> | undefined; |
| 45 | private cwd: string | undefined; |
| 46 | private timeoutMs: number; |
| 47 | |
| 48 | constructor(options: ShellCliAdapterOptions) { |
| 49 | this.name = options.name ?? options.command; |
| 50 | this.description = options.description; |
| 51 | this.command = options.command; |
| 52 | this.env = options.env; |
| 53 | this.cwd = options.cwd; |
| 54 | this.timeoutMs = options.timeoutMs ?? 30_000; |
| 55 | } |
| 56 | |
| 57 | async isAvailable(): Promise<boolean> { |
| 58 | try { |
| 59 | const result = await this.execute(["--version"]); |
| 60 | return result.exitCode === 0; |
| 61 | } catch { |
| 62 | return false; |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | execute(args: string[]): Promise<CliResult> { |
| 67 | return new Promise((resolve) => { |
| 68 | const child = execFile( |
| 69 | this.command, |
| 70 | args, |
| 71 | { |
| 72 | env: this.env ? { ...process.env, ...this.env } : process.env, |
| 73 | cwd: this.cwd, |
| 74 | timeout: this.timeoutMs, |
| 75 | maxBuffer: 10 * 1024 * 1024, // 10MB |
| 76 | encoding: "utf-8", |
| 77 | }, |
| 78 | (error, stdout, stderr) => { |
| 79 | resolve({ |
| 80 | stdout: stdout ?? "", |
| 81 | stderr: stderr ?? "", |
| 82 | exitCode: |
| 83 | error?.code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" |
| 84 | ? 1 |
| 85 | : ((error as any)?.code ?? child.exitCode ?? 0), |
| 86 | }); |
| 87 | }, |
| 88 | ); |
| 89 | }); |
| 90 | } |
| 91 | } |
nothing calls this directly
no outgoing calls
no test coverage detected