Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork239
Process execution for humans
License
NotificationsYou must be signed in to change notification settings
sindresorhus/execa
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Process execution for humans
Execa runs commands in your script, application or library. Unlike shells, it isoptimized for programmatic usage. Built on top of thechild_process
core module.
- Simple syntax: promises andtemplate strings, like
zx
. - Script interface.
- No escaping nor quoting needed. No risk of shell injection.
- Executelocally installed binaries without
npx
. - ImprovedWindows support:shebangs,
PATHEXT
,graceful termination,and more. - Detailed errors,verbose mode andcustom logging, fordebugging.
- Pipe multiple subprocesses better than in shells: retrieveintermediate results, use multiplesources/destinations,unpipe.
- Split the output into text lines, oriterate progressively over them.
- Stripunnecessary newlines.
- Pass anyinput to the subprocess:files,strings,
Uint8Array
s,iterables,objects and almost anyother type. - Returnalmost any type from the subprocess, or redirect it tofiles.
- Getinterleaved output from
stdout
andstderr
similar to what is printed on the terminal. - Retrieve the outputprogrammatically and print it on the console at the same time.
- Transform or filter the input and output withsimple functions.
- PassNode.js streams orweb streams to subprocesses, orconvert subprocesses toa stream.
- Exchange messages with the subprocess.
- Ensure subprocesses exit even when theyintercept termination signals, or when the current processends abruptly.
npm install execa
Execution:
Input/output:
Advanced usage:
- 🔀Piping multiple subprocesses
- ⏳️Streams
- 📞Inter-process communication
- 🐛Debugging
- 📎Windows
- 🔍Difference with Bash and zx
- 🐭Small packages
- 🤓TypeScript
- 📔API reference
import{execa}from'execa';const{stdout}=awaitexeca`npm run build`;// Print command's outputconsole.log(stdout);
import{$}from'execa';const{stdout:name}=await$`cat package.json`.pipe`grep name`;console.log(name);constbranch=await$`git branch --show-current`;await$`dep deploy --branch=${branch}`;awaitPromise.all([$`sleep 1`,$`sleep 2`,$`sleep 3`,]);constdirectoryName='foo bar';await$`mkdir /tmp/${directoryName}`;
$ npm install -D eslint
awaitexeca({preferLocal:true})`eslint`;
const{stdout, pipedFrom}=awaitexeca`npm run build`.pipe`sort`.pipe`head -n 2`;// Output of `npm run build | sort | head -n 2`console.log(stdout);// Output of `npm run build | sort`console.log(pipedFrom[0].stdout);// Output of `npm run build`console.log(pipedFrom[0].pipedFrom[0].stdout);
const{all}=awaitexeca({all:true})`npm run build`;// stdout + stderr, interleavedconsole.log(all);
const{stdout}=awaitexeca({stdout:['pipe','inherit']})`npm run build`;// stdout is also printed to the terminalconsole.log(stdout);
constgetInputString=()=>{/* ... */};const{stdout}=awaitexeca({input:getInputString()})`sort`;console.log(stdout);
// Similar to: npm run build < input.txtawaitexeca({stdin:{file:'input.txt'}})`npm run build`;
// Similar to: npm run build > output.txtawaitexeca({stdout:{file:'output.txt'}})`npm run build`;
const{stdout}=awaitexeca({lines:true})`npm run build`;// Print first 10 linesconsole.log(stdout.slice(0,10).join('\n'));
forawait(constlineofexeca`npm run build`){if(line.includes('WARN')){console.warn(line);}}
letcount=0;// Filter out secret lines, then prepend the line numberconsttransform=function*(line){if(!line.includes('secret')){yield`[${count++}]${line}`;}};awaitexeca({stdout:transform})`npm run build`;
constresponse=awaitfetch('https://example.com');awaitexeca({stdin:response.body})`sort`;
import{execa}from'execa';import{pipeline}from'node:stream/promises';import{createReadStream,createWriteStream}from'node:fs';awaitpipeline(createReadStream('./input.txt'),execa`node ./transform.js`.duplex(),createWriteStream('./output.txt'),);
// parent.jsimport{execaNode}from'execa';constsubprocess=execaNode`child.js`;awaitsubprocess.sendMessage('Hello from parent');constmessage=awaitsubprocess.getOneMessage();console.log(message);// 'Hello from child'
// child.jsimport{getOneMessage,sendMessage}from'execa';constmessage=awaitgetOneMessage();// 'Hello from parent'constnewMessage=message.replace('parent','child');// 'Hello from child'awaitsendMessage(newMessage);
// main.jsimport{execaNode}from'execa';constipcInput=[{task:'lint',ignore:/test\.js/},{task:'copy',files:newSet(['main.js','index.js']),}];awaitexecaNode({ipcInput})`build.js`;
// build.jsimport{getOneMessage}from'execa';constipcInput=awaitgetOneMessage();
// main.jsimport{execaNode}from'execa';const{ipcOutput}=awaitexecaNode`build.js`;console.log(ipcOutput[0]);// {kind: 'start', timestamp: date}console.log(ipcOutput[1]);// {kind: 'stop', timestamp: date}
// build.jsimport{sendMessage}from'execa';construnBuild=()=>{/* ... */};awaitsendMessage({kind:'start',timestamp:newDate()});awaitrunBuild();awaitsendMessage({kind:'stop',timestamp:newDate()});
// main.jsimport{execaNode}from'execa';constcontroller=newAbortController();setTimeout(()=>{controller.abort();},5000);awaitexecaNode({cancelSignal:controller.signal,gracefulCancel:true,})`build.js`;
// build.jsimport{getCancelSignal}from'execa';constcancelSignal=awaitgetCancelSignal();consturl='https://example.com/build/info';constresponse=awaitfetch(url,{signal:cancelSignal});
import{execa,ExecaError}from'execa';try{awaitexeca`unknown command`;}catch(error){if(errorinstanceofExecaError){console.log(error);}/*ExecaError: Command failed with ENOENT: unknown commandspawn unknown ENOENTat ...at ... {shortMessage: 'Command failed with ENOENT: unknown command\nspawn unknown ENOENT',originalMessage: 'spawn unknown ENOENT',command: 'unknown command',escapedCommand: 'unknown command',cwd: '/path/to/cwd',durationMs: 28.217566,failed: true,timedOut: false,isCanceled: false,isTerminated: false,isMaxBuffer: false,code: 'ENOENT',stdout: '',stderr: '',stdio: [undefined, '', ''],pipedFrom: [][cause]: Error: spawn unknown ENOENTat ...at ... {errno: -2,code: 'ENOENT',syscall: 'spawn unknown',path: 'unknown',spawnargs: [ 'command' ]}}*/}
awaitexeca`npm run build`;awaitexeca`npm run test`;
import{execaasexeca_}from'execa';import{createLogger,transports}from'winston';// Log to a file using Winstonconsttransport=newtransports.File({filename:'logs.txt'});constlogger=createLogger({transports:[transport]});constLOG_LEVELS={command:'info',output:'verbose',ipc:'verbose',error:'error',duration:'info',};constexeca=execa_({verbose(verboseLine,{message, ...verboseObject}){constlevel=LOG_LEVELS[verboseObject.type];logger[level](message,verboseObject);},});awaitexeca`npm run build`;awaitexeca`npm run test`;
- nano-spawn - Like Execa butsmaller
- gulp-execa - Gulp plugin for Execa
- nvexeca - Run Execa using any Node.js version
About
Process execution for humans
Topics
Resources
License
Code of conduct
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.
Packages0
No packages published