Execute shell commands in Node.js with timeouts, abort control, and streaming output.
npm install @neabyte/exec-command// CommonJSconstexec=require('@neabyte/exec-command')// ESM (ES Modules)importexecfrom'@neabyte/exec-command'importexecfrom'@neabyte/exec-command'// Simple command execution - collects all output before resolvingconstresult=awaitexec('echo "Hello World"')console.log(result.stdout)// "Hello World"console.log(result.stderr)// ""console.log(result.exitCode)// 0console.log(result.kill)// Function to terminate the process// Real-time output streaming - processes data as it arrivesconststream=exec('ping -c 5 google.com',{stream: true})// Process output in real-time using async iterationforawait(constchunkofstream.output){console.log(chunk.toString())// Buffer containing raw output}// Wait for process completionawaitstream.promise// Returns ExecResult when done// Access kill method for early terminationstream.kill()// Terminates the process immediately// Kill running processes - works for both streaming and buffered modesconststream=exec('ping -c 20 google.com',{stream: true})setTimeout(()=>{stream.kill()// Kill with default SIGTERM signalstream.kill('SIGKILL')// Kill with specific signal},5000)// Buffered process can also be killedconstbuffered=exec('long-running-command')buffered.kill()// Terminates immediately, promise will reject// Set timeout (in milliseconds) - process will be killed if it runs too longconstresult=awaitexec('slow-command',{timeout: 5000})// Process will be killed after 5 seconds with SIGTERM, then SIGKILL after 5 more seconds// No timeout (default)constresult2=awaitexec('command',{timeout: 0})// Process runs indefinitely until completion or manual kill// Execute in specific directory - changes the current working directoryconstresult=awaitexec('ls',{cwd: '/path/to/directory'})// Lists files in the specified directory// Use relative pathsconstresult2=awaitexec('pwd',{cwd: './src'})// Shows the absolute path of the src directory// Custom environment variables - merged with existing process.envconstresult=awaitexec('echo $MY_VAR',{env: {MY_VAR: 'Hello World'}})// Output: "Hello World"// Multiple environment variablesconstresult2=awaitexec('node -e "console.log(process.env.VAR1, process.env.VAR2)"',{env: {VAR1: 'First',VAR2: 'Second'}})// Output: "First Second"// Override existing environment variablesconstresult3=awaitexec('echo $HOME',{env: {HOME: '/custom/home'}})// Output: "/custom/home"// Complex shell commands with operators - automatically detected and executed with shellconstresult=awaitexec('ls -la | grep .txt')// Lists files and filters for .txt files// Chained commands with &&constresult2=awaitexec('cd /tmp && pwd')// Changes to /tmp directory and shows current path// Environment variable expansionconstresult3=awaitexec('echo $HOME && echo $USER')// Shows home directory and username// Pipes and redirectionsconstresult4=awaitexec('echo "Hello" | wc -c')// Counts characters in "Hello" (output: 6)// Complex shell operationsconstresult5=awaitexec('find . -name "*.js" | head -5')// Finds first 5 JavaScript filesAll options are optional and can be combined:
interfaceExecOptions{/** Timeout duration in milliseconds (0 = no timeout) */timeout?: number/** Enable streaming mode for real-time output */stream?: boolean/** Working directory for command execution */cwd?: string/** Environment variables to pass to the process */env?: Record<string,string|undefined>}timeout: Kill process after X milliseconds (0 = no timeout)stream:true= real-time output,false= collect all output firstcwd: Run command in this directoryenv: Add these environment variables
Buffered Mode (stream: false):
interfaceExecResult{stdout: string// Standard outputstderr: string// Standard errorexitCode: number// Process exit codekill(signal?: string|number): void// Kill functionthen: Promise<ExecResult>['then']// Promise methodscatch: Promise<ExecResult>['catch']finally: Promise<ExecResult>['finally']}Streaming Mode (stream: true):
interfaceExecStream{output: AsyncIterable<Buffer>// Real-time output streampromise: Promise<ExecResult>// Completion promisekill(signal?: string|number): void// Kill function}This project is licensed under the MIT license. See the LICENSE file for more info.