Use JS to replace Bash for writting tools.
https://developer.atlassian.com/blog/2015/11/scripting-with-node/
https://github.com/tj/commander.js/
npx runs JS command without need to install it first with -g. Running `npm <command>` , it executes command from
(1) $PATH
(2) local node_modules/.bin
(3) install from a package:
--package can specify the package, or
install the package and guess the name of binary depending on the specifier:
<command> as both package name and binary
--no-install : only finds local .bin
--userconfig <path>
-c <string>
1.
(1) searches path & local packages for executable, so no need to install packages globally (2) install if the package does not exist locally (no need to run npm install first)...
1. npm init
2. create an entry JS file with the shebang
#!/usr/bin/env node
3. add 'bin' into package.json, with "command":"./path/to/entry.js"
"bin": {
+ "snippet": "./index.js"
+ }
4. npm install -g
now able to use command 'snippet'
5. during command development use 'npm link' (with no argument, under development dir) to link the currently developing copy to save from re-installing every time
1. $ npm install --save commander
2. Example
var program = require('commander');
program
.arguments('<file>')
.option('-u, --username <username>', 'The user to authenticate as')
.option('-p, --password <password>', 'The user\'s password')
.action(function(file) {
console.log('user: %s pass: %s file: %s',
program.username, program.password, file);
})
.parse(process.argv);
3. This also provided --help
program
.version('0.0.1', '-v, --version')
Simple case: use async-prompt
// no types at this moment
const {prompt, password, multiline, confirm} = require('async-prompt')
const name = await prompt('username: ');
const pass = await password('password: ');
const desc = await multiline('description: ');
const ok = await confirm('are you sure? ');
(note: *() - a generator function, yield - pause and resume a generator function)
--------------------------------------------
Complex case use https://github.com/SBoudrias/Inquirer.js/
SuperAgent is the article author's choice. Not so related to command line scripting, though.
https://nodejs.org/api/child_process.html
const execSync = require('child_process').execSync;
// import { execSync } from 'child_process';
const output = execSync('ls', { encoding: 'utf-8' }); // the default is 'buffer'
console.log('Output was:\n', output);
execSync Options (may be used)
cwd: child process's working dir
input - string, Buffer, etc. as stdin
stdio - stdio configuration, default 'pipe'
env - environment variables
shell - default '/bin/sh'
uid, gid
timeout - default undefined
killSignal - default SIGTERM
maxBuffer - default 200*1024
encoding - default 'buffer'
Will throw if timeout or non-zero exit code. Error object will contain: status the exit code, see https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options
console.error('some error message');
process.exit(1); // return 0 if no error
var chalk = require('chalk');
console.log(chalk.bold.cyan('Snippet created: ') + link);
var ProgressBar = require('progress');
var bar = new ProgressBar(' uploading [:bar] :percent :etas', barOpts);
...
bar.tick(chunk.length);
This code demonstrate calling a pipe command, pass string to stdin, and write stdout into a file
Note sometimes command behave differently. Due to some environment difference I guess.
if (!pipeCmd) {
fs.writeFileSync(jsonAbsolutePath, pagesAsJson)
} else {
const pipeChildProcess = cp.exec(pipeCmd)
const writeStream = fs.createWriteStream(jsonAbsolutePath)
pipeChildProcess.stdout!.pipe(writeStream)
pipeChildProcess.stdin!.write(pagesAsJson)
pipeChildProcess.stdin!.end()
await new Promise((resolve, reject)=>{pipeChildProcess.on("exit", resolve); pipeChildProcess.on("error", reject)})
}