Skip to content
/ mtd Public

Just-in-time dependency injection of command line options for executable contexts in Node.js

License

Notifications You must be signed in to change notification settings

okabsd/mtd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MTD

Multi-track drifting for your command line applications

NPM version Downloads

logo

Just-in-time dependency injection of command line options for executable contexts in Node.js.

More formally, MTD stands for managing terminal dependencies - but that's no fun.

MTD is a lightweight module that wraps around minimist, providing an intelligent way to define tracks that your command line application might travel down, and allowing you to specify the command line options that each track depends upon. Tracks are essentially different execution contexts that your singular command line application might want to run, and are defined as the loose arguments provided to a command line application.

Install

Using npm, of course.

$ npm install mtd

Learn By Example

Basic

Below is a basic example of a command line application with a single track, echo, which in turn has a single, required command line option, input or i.

// basic.js
'use strict';

const Depot = require('mtd');

new Depot()

.track(
  'echo',
  [ { $: 'input', alias: 'i', info: 'Some input.' } ],
  (input) => console.log(input)
)

.embark();

We can test out our example script as $ node basic.js echo.

This however results in an error:

Track [ echo ] missing options:
    --input (-i)    Some input.

MTD has spotted that our echo track is missing an option, and lets us know.

If we try again, $ node basic.js echo --input Hello!, we'll get the appropriate response:

Hello!

To allow for optional options, you must specify a default, using the property _. If we changed the second argument of track to

[ { $: 'input', _: 'Yo.' alias: 'i', info: 'Some input.' } ]

and ran $ node basic.js echo again, we'd see no issues, and Yo. would be printed to our terminal display.

Multi

Below is an example showcasing multiple tracks, foo and bar, both of which take no arguments.

// multi.js
'use strict';

const Depot = require('mtd');

new Depot()

.track('foo', [], () => {
  console.log('foo track');
})

.track('bar', [], () => {
  console.log('bar track');
})

.embark();

By default, MTD allows for multiple tracks to be executed. The execution of these tracks is synchronous, and happens in the same order that they are specified at the command line.

If we ran $ node multi.js foo bar we would see the following in our terminal:

foo track
bar track

Conversely, $ node multi.js bar foo would result in:

bar track
foo track

By default, MTD restricts tracks to a single execution. $ node multi.js foo foo would display:

foo track

See the configure method below for how to change the multi and reruns settings.

Documentation

Requiring

Requiring the module works very much like most Node modules do.

const Depot = require('mtd');

With the previous, Depot now holds a reference to the chief export, a class of the same name. You can of course give this any identifier you'd like.

Note: The rest of this document uses TypeScript notation.

Construction

constructor (options?: TypedOption[], args?: string[])

When constructed, Depot instances take two optional arguments: options, and args.

Option and TypedOption objects will be explained below.

args is an array of strings to parse as command line arguments. It defaults to process.argv.slice(2) if not provided (or if passed process.argv).

Methods

Note the methods that return the instance (configure, track, default, always), and as such can be chained.

Configuring

public configure (
  config: Settings
): this

This method takes an object where the values of any keys also found in the settings object property of the Depot instance will be overwritten with the values from this provided object.

Example

This example shows the configuring the instance with the default settings.

.configure({
  multi: true, // Allow execution of more than one track
  reportErrors: true, // Print missing arguments and issues
  reruns: false // Allow multiple executions of the same track
})

Laying Tracks

The following three methods each create Track objects from their arguments. They are used to register tracks within a Depot instance, and specify the command line arguments that are required.

public track (
  handle: string,
  options: Option[],
  block: Block
): this

track creates a regular track.

public default (
  handle: string,
  options: Option[],
  block: Block
): this

default creates a regular track, and sets it as the default track to execute if no tracks are provided via the command line. There can only be one default track at any given time, and repeat invocations will override an existing default.

public always (
  handle: string,
  options: Option[],
  block: Block
): this

always creates a regular track, and pushes its handle into an array of tracks that will be executed after all other tracks have departed.

The arguments for all three methods are the same, and are as follows:

  • handle is the name of the track, and must be unique. Remember that tracks are defined as the loose arguments provided to a command line application.

  • options is an array of Option-like objects (see below), whose order corresponds with the arguments specified by block.

  • block is a generic function, with the signature (...args: any[]): any;, and is the executable context of the track.

Example
.track(
  'foo',
  [ { $: 'bar', _: false, alias: 'b', info: 'A description.' } ],
  bar => {
    if (bar) { ... }
    ...
  }
)

Heading Off

public embark (): void

embark is the final method that sets your command line application in motion. Call it after all tracks have been registered.

Failure to invoke this method will result in no tracks being dispatched.

Option-like Objects (Option, TypedOption)

Option objects are used by the instance constructor for initial parsing, and global option settings. They are also used on a per-track track basis for specifying the command line arguments to be injected into the execution context.

interface Option extends Object {
  [index: string]: any;

  /*
   * The name of the command line option.
   * The most important property, and the only one that is required.
   * It is also the most used property, so we use $ for brevity.
   *
   * $: foo would correspond with the command line option --foo
   */
  $: string;

  /*
   * A default value to use in the event that no value
   * is specified via the command line.
   */
  _?: any;

  /*
   * An alternative name ($) to use.
   * Generally speaking, this should be a single character,
   * but that's not strictly enforced.
   */
  alias?: string;
  /*
   * A description of the command line option,
   * used for self documentation.
   */
  info?: string;
}

The instance constructor alternatively takes an optional array of objects matching an extended version of the Object interface, TypedOption. These objects have two additional type properties, to tell the initial argument parsing which type the inputs should be resolved to. See minimist for more information.

interface TypedOption extends Option {
    bool?: boolean;
    string?: boolean;
}

These two options are mutually exclusive (if you include both, bool takes precedence).

string is useful for forcing large integers to be parsed as strings, without losing information to 53-bit doubles, since numeric-like arguments are treated as numbers otherwise.

These are not available to per-track Option objects, since the argument parsing is long done by the time those are reviewed. They must be shadowed from the instance constructor option pool if you need these type assurances.

Extras

License

MTD is MIT!

Read it here.

Enjoy!

Oka.io

About

Just-in-time dependency injection of command line options for executable contexts in Node.js

Resources

License

Stars

Watchers

Forks

Packages

No packages published