Skip to content

Terminus

A Javascript library to build command line applications.

Install

npm install --save @metis-data/terminus
Hello world example
const { TerminusBuilder } = require("@metis-data/terminus");

const terminus = await TerminusBuilder.create("my-app", "0.0.1")
  .addAction({
    name: "test",
    description: "test action",
    category: "test",
    func: () => {
      return "hello world!";
    },
    transformers: {
      pretty: (text) => [{ type: "text", content: text }],
    },
  })
  .build()

terminus
  .start()
  .then(() => {});

Terminus provides a simple state, config and progress so you won't have to do it yourself. These object are provided in the function so there is no need to import them, and they are easy to mock and override.

Action func example
{
  await func: (arg, options, { config, state, progress }) => {
    // Do async work.
    const { stateValue, configValue } = await progress.wrapAsync("doint stuff...", async () => {
      // Read and write to state and config.
      const { stateValue } = state.get()
      state.update({ stateValue: stateValue + 1 })

      const configValue = await config.get("configValue")
      await config.set("configValue", configValue + 1)

      return { stateValue, configValue }
    }
  }
}

Terminus supports different ways of rendering the same action. For example, you can print the result of an action as a JSON object and consume it in another tool, or pretty-print it colors, tables and other UI components. The printing mode is set by --print-mode action.

Terminus is extendable, use a Plugin to add actions, configurations, hooks and more. Checkout the existing plugins to see what you can do with a plugin.

You can read about the main components of Terminus here.

Adding Arguments and Options with Completions and Progress

A more complex action
terminus.addAction({
  name: "test",
  description: "test action",
  category: "test",
  args: [
    {
      name: "name",
      description: "the name to greet",
      type: "string",
      optional: true,
      defaultValue: "world",
    },
  ],
  options: [
    {
      name: "greeting",
      description: "the greeting",
      type: "string",
      defaultValue: "hello",
      completer: () => {
        return ["hi", "hello"];
      },
    },
  ],
  completer: (args) => {
    if (args.length === 1) {
      return ["world", "planet", "universe"];
    }
  },
  func: (name, { greeting }, { progress }) => {
    return progress.wrapAsync("Generating Message...", () => {
      return { name, greeting };
    });
  },
  transformers: {
    pretty: ({ name, greeting }) => [
      { type: "text", content: `${greeting} ${name}!` },
    ],
  },
});
./index.js test
hello world!
./index.js test "new user" --greeting hi
hi new user!

Full Example