runner.ts 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. /**
  2. * Shared no-shell `execFile` runner for host-native OS integrations.
  3. * @module @deepseek-ai/dsh-native-command/runner
  4. */
  5. import { execFile } from 'node:child_process'
  6. /** Testable command boundary; native implementations never invoke a shell. */
  7. export type NativeCommandRunner = (
  8. command: string,
  9. args: readonly string[],
  10. signal: AbortSignal,
  11. ) => Promise<{ stdout: string; stderr: string }>
  12. /**
  13. * Run a host command with utf8 stdio, abort propagation, and Windows hide.
  14. * @param command - executable path or PATH name.
  15. * @param args - argv (never a shell string).
  16. * @param signal - caller/connection lifetime; abort terminates the child.
  17. * @returns captured stdout/stderr on exit 0.
  18. */
  19. export const runNativeCommand: NativeCommandRunner = (command, args, signal) =>
  20. new Promise((resolve, reject) => {
  21. execFile(
  22. command,
  23. [...args],
  24. { encoding: 'utf8', signal, windowsHide: true },
  25. (error, stdout, stderr) => {
  26. if (error !== null) {
  27. const failure = Object.assign(new Error(error.message, { cause: error }), {
  28. code: error.code,
  29. stdout,
  30. stderr,
  31. })
  32. reject(failure)
  33. return
  34. }
  35. resolve({ stdout, stderr })
  36. },
  37. )
  38. })