15.1.0 • Published 4 months ago

seeli v15.1.0

Weekly downloads
575
License
MIT
Repository
github
Last release
4 months ago

Test + Release package dependancies Codacy Badge semantic-release

seeli ( C. L. I. )

Object orientated, event driven , Interactive CLI module. Seeli aims to give you the tools to compose A command line interface the way you want it, and otherwise, stays out of your way.

gif

const os = require('os')
const cli = require('seeli')

cli.config({
  exitOnError: true
, color: 'green'
, name: 'example'
})

const Hello = new cli.Command({
  description:"displays a simple hello world command"
, name: 'hello'
, ui: 'dots'
, usage:[
    `${cli.bold("Usage:")} ${cli.get('name')} hello --interactive`
  , `${cli.bold("Usage:")} ${cli.get('name')} hello --name=john`
  , `${cli.bold("Usage:")} ${cli.get('name')} hello --name=john --name=marry --name=paul -v screaming`
  ]

, flags:{

    name:{
      type:[ String, Array ]
    , shorthand:'n'
    , description:"The name of the person to say hello to"
    , required:true
    }

  , 'nested:value' : {
      type: Number
    , shorthand: 'nv'
    , description: 'A newsted Value'
    , name: 'nested'
    }

  , excited: {
      type:Boolean
    , shorthand: 'e'
    , description:"Say hello in a very excited manner"
    , default:false
    }

  , volume:{
      type:String
    , choices:['normal', 'screaming']
    , description:"Will yell at each person"
    , default:'normal'
    , shorthand:'v'
    }
  }
, onContent: (content) => {
    // command success
    // content is the final output from run function
    // non string content is not written to stdout automatically
    // you could do it here

    console.log(content.join(os.EOL))
  }

, run: async function( cmd, data ){
    const out = [];
    this.ui.start('processing names');
    var names = Array.isArray( data.name ) ? data.name : [ data.name ];
    for( var x = 0; x< names.length; x++ ){
      this.ui.text = (`processing ${names[x]}`)
      await new Promise((resolve) => {
        setTimeout(() => {
          let value = "Hello, " + names[x];
          if( data.excited ){
            value += '!';
          }

          out.push( data.volume === 'screaming' ? value.toUpperCase() : value );
          resolve(true);
        }, 1000 * x + 1);
      });
    }

    this.ui.succeed('names processed successfully');
    // anything returned from run
    // is emitted from the `content` event
    // strings will automatically be written to stdout
    return out
  }
});

cli.use('hello', Hello)
cli.run();

now you will have a fully functional hello world command with help and an interactive walk through

node ./cli help world
node ./cli world --help
node ./cli world --interactive
node ./cli world --name=Mark --name=Sally --no-excited

API

Seeli.run( )

Executes The command line interface

Seeli.list<Array>

List of all top level registered commands

Seeli.use( name <string>, cmd <Command> )

Registers a new command under the specified name where the name will invoke the associated command

var cli = require('seeli')
var Cmd = new cli.Command();

cli.use('test', Cmd )
cli.run()

Seeli.bold( text <string>)

wraps text in the ansi code for bold

Seeli.green( text <string>)

wraps text in the ansi code for green

Seeli.blue( text <string>)

wraps text in the ansi code for blue

Seeli.red( text <string>)

wraps text in the ansi code for red

Seeli.yellow( text <string>)

wraps text in the ansi code for yellow

Seeli.cyan( text <string>)

wraps text in the ansi code for cyan

Seeli.magenta( text <string>)

wraps text in the ansi code for magenta

Seeli.redBright( text <string>)

wraps text in the ansi code for redBright

Seeli.blueBright( text <string>)

wraps text in the ansi code for blueBright

Seeli.greenBright( text <string>)

wraps text in the ansi code for greenBright

Seeli.yellowBright( text <string>)

wraps text in the ansi code for yellowBright

Seeli.cyanBright( text <string>)

wraps text in the ansi code for cyanBright

Seeli.config( key <string>, value <object> )

sets a configuration value.

Seeli.config( opts <object> )

set multiple configuration values using a single object

Seeli.config( key <string> )

A config value to look up. Can be a dot separated key to look up nested values

Supported Confgurations

  • color <String> - The chalk color to use when outputting help text. default green
  • name <String> - the name of the command that is used in generated help
  • exitOnError <Boolean> - Seeli will forcefully exit the current process when an error is encountered. default false
  • exitOnContent <Boolean> - Seeli will forefully exit the current process when it is passed output content from a command. default true
  • plugins <String>|<function>[] - A list of plugins to load and execute. A plugin may be either a function, or a module id to be required. If it is a module id, the module must export a single function which will be passed the seeli instance when called.
  • help <String> - a file path or module name to a custom help command. This will be passed to require and must export a single command instance
    • seeli.config('help', '/path/to/help/command')
Package Configuration

Alternatively, initial configuration may be provided via package.json in a top-level key - seeli

// package.json

{
  "seeli": {
    "color": "blue",
    "name": "whizbang",
    "plugins": [
      "@myscope/simple-command"
    ]
  }
}

Command( options <object> )

Options

nametypedefaultdescription
descriptionString""Used to render help output
strictBooleanfalseWhen true, commands will error when the receive unknown flags
argsArraynullif supplied, agrs will be used instead of process.argv
interactiveBooleantrueIf set to false, the flag will be excluded from the interactive prompts
usageString / Array""A string or array of strings used to generate help text
flagsObject{}key value pairs used to control the command where keys are the name of the flag and the values is a configuration object for the flag
uiStringdotsThe kind of progress indicator your command should use
runFunctionno-opAn async function used as the body of the command. It will be passed a subcommand name if one was passed, and a data object containing the processed values from the command input.
commandsCommand[][]A list of additional command to utilize as sub commands.

Flag Options

namerequiredtypedescription
typetruestringThe type of input that is expected. Boolean types to not expect input. The present of the flag implies true. Additionally, boolean flags allow for --no-<flag> to enforce false. If you want to accept multiple values, you specify type as an array with the first value being the type you which to accept. For example [String, Array ]**** means you will accept multiple string values.
descriptionfalsestringa description of the flag in question.
requiredfalsebooleanIf set to true a RequiredFieldError will be emitted
shorthandfalsestringAn options short hand flag that will be expanded out to the long hand flag.
interacivefalsebooleanIf set to false the flag will omitted from interactive prompts
defaultfalsemixedA value to return if the flag is omitted.
maskfalsebooleaninteractive mode only Sets the input type to masked input to hide values
choicesfalsearrayUsed only during an interactive command. Restricts the users options only to the options specified
multifalsebooleaninteractive mode only If choices is specified, and multi is true, this user will be presented a multi checkbox UI allowing them to pick multiple values. The return value will be an array
skipfalsebooleaninteractive mode only - if set to true this flag will be omitted from the interactive command prompts
eventfalsebooleanif set to true the command will emit an event withe the same name as the flag with the value that was captured for that flag
whenfalsefunctioninteractive mode only Receives the current user answers hash and should return true or false depending on whether or not this question should be asked.
validatefalsefunctionreceives user input and should return true if the value is valid, and an error message (String) otherwise. If false is returned, a default error message is provided.
filterfalsefunctionReceives the user input and return the filtered value to be used inside the program. The value returned will be added to the Answers hash.

Nested Flags

Flag names that contain a colon (:) will be parsed as a nested value in the data that is return to you commands. You can Set arbitrarily deep values. You can use this to automatically construct complex object. Array values are limited to primitive types

// cli --foo:bar:foobar=hello --foo:bar:baz=world --nested:array=1 --nested:array=2

{
  foo: {
    bar: {
      foobar: "hello"
    , baz: "world"
    }
  }
, nested: {
    array: [1, 2]
  }
}

Auto Help

Seeli will generate help from the usage string and flags. You can help as a command seeli help <command> or as a flag seeli <command> --help

Asyncronous

Your defined run function can be an async function, or a function that returns a Promise. This allows you to do complex async operations and I/O. If an error is thrown, it will be displayed. Otherwise, the content returned from your run function will be output to stdout ( if it returned a String).

Progress

Your command's run function has access to an instance of ora allowing you to display progress indicators and helpful messages while you perform other work.

Events

Instances of the seeli Command or Commands that inherit from it as also instances of the EventEmitter class. By default any flag that has its event option set to true will emit an event with the value of the flag before the run function is executed.

var EventCommand = new cli.Command({
  args:[ '--one', '--no-two']
, flags:{
    one:{
      type:Boolean
    , event:true
    }
  , two:{
      type:Boolean
    , event:true
    }
  }
, run: async function( cmd, data ){
    return data.one && data.two
  }
});

EventCommand.on('one', function( value ){
  assert.equal( true, value );
});

EventCommand.on('two', function( value ){
  assert.equal( false, value )
});

EventCommand.on('content', function( value ){
  assert.equal( false, value );
});

EventCommand.run( null );
15.1.0

4 months ago

15.0.0

5 months ago

14.1.1

1 year ago

14.1.0

1 year ago

14.0.0

2 years ago

13.0.3

2 years ago

13.0.2

2 years ago

13.0.0

3 years ago

13.0.1

3 years ago

12.5.9

3 years ago

12.5.8

3 years ago

12.5.6

3 years ago

12.5.7

3 years ago

12.5.4

3 years ago

12.5.5

3 years ago

12.5.2

3 years ago

12.5.3

3 years ago

12.5.1

3 years ago

12.5.0

3 years ago

12.4.0

3 years ago

12.3.0

3 years ago

12.3.1

3 years ago

12.3.2

3 years ago

12.3.3

3 years ago

12.2.0

3 years ago

12.1.3

3 years ago

12.1.4

3 years ago

12.1.2

3 years ago

12.1.1

3 years ago

12.1.0

3 years ago

12.0.0

3 years ago

11.0.2

3 years ago

11.0.0

4 years ago

11.0.1

4 years ago

10.0.2

4 years ago

10.0.1

4 years ago

10.0.0

4 years ago

9.0.0

4 years ago

8.3.0

5 years ago

8.2.2

5 years ago

8.2.1

5 years ago

8.2.0

6 years ago

8.1.3

6 years ago

8.1.2

6 years ago

8.1.1

6 years ago

8.1.0

6 years ago

8.0.1

6 years ago

8.0.0

6 years ago

7.0.0

6 years ago

6.0.3

6 years ago

6.0.2

6 years ago

6.0.1

6 years ago

6.0.0

6 years ago

5.0.0

7 years ago

4.0.0

7 years ago

3.0.1

8 years ago

3.0.0

8 years ago

2.3.1

8 years ago

2.3.0

8 years ago

2.2.1

8 years ago

2.2.0

8 years ago

2.1.0

8 years ago

2.0.1

8 years ago

2.0.0

8 years ago

1.0.1

8 years ago

1.0.0

8 years ago

0.4.3

9 years ago

0.4.2

9 years ago

0.4.1

9 years ago

0.4.0

9 years ago

0.3.13

9 years ago

0.3.12

9 years ago

0.3.11

9 years ago

0.3.10

9 years ago

0.3.9

9 years ago

0.3.8

9 years ago

0.3.7

9 years ago

0.3.6

9 years ago

0.3.5

10 years ago

0.3.4

10 years ago

0.3.3

10 years ago

0.3.2

10 years ago

0.3.1

10 years ago

0.3.0

10 years ago

0.2.2

10 years ago

0.2.1

10 years ago

0.2.0

10 years ago

0.1.1

10 years ago

0.1.0

10 years ago