npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

shellcraft

v1.3.6

Published

Simple CLI and shell for Node.js based on commander and inquirer.

Downloads

353

Readme

shellcraft.js

npm version dependencies Build Status ![gitter](https://badges.gitter.im/Join Chat.svg)

Simple CLI and shell for Node.js based on commander and inquirer.

This module provides a way in order to use commander and inquirer together. There are a CLI and a shell mode, and the same commands can be used everywhere.

shellcraft.js supports the command history and the auto-completion (in shell mode).

Documentation

Installation

NPM Badge

$ npm install shellcraft

Hello, World

var shellcraft = require('shellcraft');

var options = {
  version: '0.1.0',
};

shellcraft.begin(options, function (err, results) {
  if (results) {
    console.log(results);
  }
});

API

There are only two public API in order to play with shellcraft.


shellcraft.begin (options, callback)

✤ options

options = {
  version: '0.1.0',
  prompt: '>',
  promptFixed: false,
};

The version is used by Commander with the -V, --version parameter. The default prompt > can be changed by something else, like for example:

myprompt>

The promptFixed option is experimental and disabled by default. The purpose is to keep the prompt at the bottom even if async console.log outputs are used. In other words, (most) outputs are put before the prompt. Outputs via process.stdout.write (or stderr) are not handled by this option.

✤ callback (results)

The callback is called when the shell or the CLI is terminated. Note that currently the results argument is not consistent between the CLI and the shell mode. This behavior will change in the future.

Example
shellcraft.begin(
  {
    version: '0.0.1',
    prompt: 'orc>',
  },
  function (err, results) {
    if (results) {
      console.log(results);
    }
  }
);

shell mode

$ node myShell.js
orc> _
orc> help
 exit     exit the shell
 help     list of commands
 scope    change scope

orc> exit
$ _

CLI mode

$ node myShell.js -h

  Usage: myShell [options]

  Options:

    -h, --help         output usage information
    -V, --version      output the version number
    -s, --scoped       include scoped commands (CLI only)

$ _

shellcraft.registerExtension (shellExt, callback);

There are two builtin commands help and exit. For more commands you must register one or more extensions. An extension must be "requirable" and must export two functions (register() and unregister()).

✤ shellExt

The path on the .js file where the register and unregister methods are exported. An extension argument is passed with the register call. This object has four methods, command, option, remove and reload. It looks like the commander API in some ways.

extension
  .command('foo', 'foo description', options, function (callback, args) {
    /*
     * callback (wizard, function (answers) {})
     *   Is called in order to return to the prompt (or exit if CLI). The wizard
     *   argument must be used only in order to process an Inquirer definition
     *   in the shell (or the CLI). Otherwise you must call the callback without
     *   arguments.
     *   The Inquirer answers are retrieved with the second argument.
     *
     * args
     *   Are the arguments provided with the command.
     */
  })
  .option('-f, --foo', 'foo description', options, function (callback, args) {
    /*
     * callback ()
     *
     * args
     *   This array can not have more than one item.
     */
  });

/* Remove a specific command or option */
extension.remove('foo');

/* Reload for autocomplete (for example after removing a command) */
extension.reload();

The options can be (for command):

options : {
  wizard : false,              /* when it needs Inquirer          */
  params : {
    scope: 'goblin',           /* override global scope filter    */
    required: 'argName',       /* a required argument             */
    optional: 'optionals...'   /* several optionals arguments     */
                               /* do not append ... in order to   */
                               /* limit to one optional argument  */
  }
}

It's possible to have an array of required or optional arguments, for example:

options : {
  params : {
    required: ['arg1', 'arg2'],
    optional: ['opt1', 'opt2', 'opts...']
  }
}

The options can be (for option):

options : {
  params : {
    required: 'argName',       /* a required argument             */
  }
}

✤ callback ()

The callback must be called when the extension is registered.

Example

myShellExtension.js

'use strict';

var zog = 'zog';

var cmd = {};
var opt = {};

cmd.hello = function (callback, args) {
  console.log(zog + ' tells "Hello, ' + args.join(' ') + '"');
  callback();
};

cmd.wizard = function (callback) {
  var wizard = [
    {
      /* Inquirer definition... */
      type: 'input',
      name: 'zog',
      message: 'tell ' + zog,
    },
  ];

  callback(wizard, function (answers) {
    /* stuff on answers */
    if (answers.zog === zog) {
      console.log(zog + ' ' + zog);
    } else {
      console.log('lokthar?');
    }

    /*
     * You can return false if you must provide several wizard with only
     * one call to this command handler.
     * You can call callback () without argument in order to return to the
     * prompt instead of returning true.
     */
    return true;
  });
};

opt.foobar = function (callback, args) {
  if (args) {
    zog = args[0];
  } else {
    zog = 'lokthar';
  }
  callback();
};

exports.register = function (extension, callback) {
  extension
    .command(
      'hello',
      'print Hello, John',
      {
        wizard: false,
        params: {
          required: 'name',
          optional: 'etc...',
        },
      },
      cmd.hello
    )
    .command(
      'wizard',
      'begins a wizard',
      {
        wizard: true,
        scope: 'warcraft',
      },
      cmd.wizard
    )
    .option(
      '-f, --foobar',
      'zog is foobar',
      {
        params: {
          required: 'who',
        },
      },
      opt.foobar
    );

  callback();
};

exports.unregister = function (callback) {
  /* internal stuff */
  callback();
};

myShell.js

'use strict';

var path = require('path');
var shellcraft = require('../');

var options = {
  version: '0.0.1',
  prompt: 'orc>',
};
var shellExt = path.join(__dirname, 'myShellExtension.js');

shellcraft.registerExtension(shellExt, function () {
  shellcraft.begin(options, function (err, results) {
    if (results) {
      console.log(results);
    }
  });
});

shell mode

$ node myShell.js
orc> _
orc> help
 exit                    exit the shell
 help                    list of commands
 scope                   change scope (warcraft)
 hello <name> [etc...]   print Hello, John

orc> hello Tux
zog tells "Hello, Tux"
orc> exit
$ _

CLI mode

$ node myShell.js -h

  Usage: myShell [options] [command]


  Commands:

    *
    hello <name> [etc...]  print Hello, John

  Options:

    -h, --help          output usage information
    -V, --version       output the version number
    -s, --scoped        include scoped commands (CLI only)
    -f, --foobar <who>  zog is foobar

$ _
$ node myShell.js hello Alice
zog tells "Hello, Alice"
$ node myShell.js -f Bob hello Alice
Bob tells "Hello, Alice"
$ _

Note that the commands which are in a different scope (like wizard in this example), are not shown in the global help output.

In order to see all commands, you must pass the -s, --scope argument:

$ node examples/myShell -sh

  Usage: myShell [options] [command]


  Commands:

    *
    hello <name> [etc...]  print Hello, John
    warcraft@wizard        begins a wizard

  Options:

    -h, --help          output usage information
    -V, --version       output the version number
    -s, --scoped        include scoped commands (CLI only)
    -f, --foobar <who>  zog is foobar

$ _

License

The MIT License (MIT)

Copyright (c) 2014-2017 Xcraft <[email protected]>
Copyright (c) 2015      Xcraft <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.