Functions based CLI framework
$ npm install @pawelgalazka/cli --save
$ touch yourScript.js # add your script file
$ chmod a+x ./yourScript.js # add execute permissions
yourScript.js
:
#!/usr/bin/env node
const { cli } = require('@pawelgalazka/cli')
cli((options, name = '', surname = '') => {
console.log(`Hello ${name} ${surname}!`)
if (options.yay) {
console.log('YAY!')
}
})
$ ./yourScript.js Pawel Galazka
Hello Pawel Galazka!
$ ./yourScript.js Pawel Galazka --yay
Hello Pawel Galazka!
YAY!
#!/usr/bin/env node
const { cli, withHelp } = require('@pawelgalazka/cli')
cli(withHelp((options, name = '', surname = '') => {
console.log(`Hello ${name} ${surname}!`)
if (options.yay) {
console.log('YAY!')
}
}, 'Script description'))
$ ./yourScript.js --help
Usage: yourScript.js
Script description
You can also add more detailed help
which will print out info
about options and params:
#!/usr/bin/env node
const { cli, help } = require('@pawelgalazka/cli')
function command(options, name = '', surname = '') {
console.log(`Hello ${name} ${surname}!`)
if (options.yay) {
console.log('YAY!')
}
}
help(command, 'Script description', {
options: {
yay: 'print yay'
},
params: ['name', 'surname']
})
cli(command)
$ ./yourScript.js --help
Usage: yourScript.js [options] [name surname]
Script description
Options:
--yay print yay
const { cli, help } = require('@pawelgalazka/cli')
help(cmd1, 'Description of first command')
function cmd1(options) {
console.log('First command')
}
help(cmd2, 'Description of second command')
function cmd2(options) {
console.log('Second command')
}
help(defaultCmd, 'Description of default command')
function defaultCmd(options) {
console.log('Default command')
}
cli({
cmd1,
cmd2,
default: defaultCmd
})
$ ./yourScript.js cmd1
First command
$ ./yourScript.js
Default command
Mutlicommand version of cli can as well accept options
and params which
will be passed to proper function. --help
generation is handled too.
To better organise commands, it is possible to group them in namespaces:
const test = {
unit (options) {
console.log('Doing unit testing!')
}
e2e (options) {
console.log('Doing e2e testing!')
}
}
cli({
test
})
$ ./yourScript.js test:unit
Doing unit testing!
Because namespace is just an object with functions, namespace can be created also from a module:
./commands/test.js
:
function unit () {
console.log('Doing unit testing!')
}
function e2e () {
console.log('Doing e2e testing!')
}
module.exports = {
unit,
integration
}
./yourScript.js
const test = require('./commands/test')
cli({
test
})
$ ./yourScript.js test:unit
Doing unit testing!
You can customise behaviour of cli
framework by middleware system. cli
itself is build on chain of middlewares.
To add custom middleware:
#!/usr/bin/env node
const { cli, useMiddlewares } = require('@pawelgalazka/cli')
const customMiddleware = next => ({
options,
params,
command,
definition,
namespace
}) => {
const nextParams = params.map(param => param.toUpperCase())
// Run next middleware
next({ options, params: nextParams, command, definition, namespace })
}
cli((options, name = '', surname = '') => {
console.log(`Hello ${name} ${surname}!`)
}, useMiddlewares([customMiddleware]))
$ ./yourScript.js Pawel Galazka
Hello PAWEL GALAZKA!
What useMiddlewares
does, it takes your middleware and puts it within the chain
with default middlewares, which looks like this:
[
errorsHandler(logger),
argsParser(argv),
commandFinder,
helper(logger, argv),
validator,
rawArgsParser(argv),
...middlewares, // here goes your middlewares
commandCaller
]
So custom middlewares gets called right before calling command function. You
can totally customise the chain by not using useMiddlewares
. You can provide an array
of middlewares directly to cli
as a second argument, instead of useMiddlewares
call.
By this default chain of middlewares will get overwritten.
cli
has support for TypeScript
. TS
types are included within the
library, so you can write your scripts fully in TypeScript
with usage
of ts-node
:
$ npm install ts-node --save-dev
yourScript.ts
:
#!/usr/bin/env ts-node
import { cli } from '@pawelgalazka/cli'
cli((options, name = '', surname = '') => {
console.log(`Hello ${name} ${surname}!`)
})