Skip to content
This repository has been archived by the owner on Oct 19, 2022. It is now read-only.

pawelgalazka/cli

Repository files navigation

CLI node version Build Status npm version

Functions based CLI framework

Quick Start

$ 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!

Add help

#!/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

Add commands

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.

Add namespaces

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!

Add middleware

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.

Use TypeScript

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}!`)
})

About

Functions based CLI framework

Resources

License

Stars

Watchers

Forks

Packages

No packages published