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

garson

v2.0.1

Published

Interactive config-based command-line tool

Downloads

23

Readme

build npm version

Build interactive config-based command-line interfaces with JavaScript :wink:

Table of Contents

Install

npm install garson

Usage

As a global dependency

Run:

npx garson

This command will look for garson.config.js file in the current directory. You can change the default path with --config option.

See npx garson --help for a full list of options.

As a local dependency

Create a script in package.json:

{
  "scripts": {
    "garson": "garson --config=./path-to/garson.config.js"
  }
}

Now you can run npm run garson.

Configuration

A garson.conf.js file should export a garson object, which is represented by a chain of prompts that ends with an action:

const { garson, prompts, actions } = require('garson');

module.exports = garson()
  .prompt(/* some prompt */)
  .action(/* some action  */);

There could be many prompts, but they must end with a single action:

const { garson, prompts, actions } = require('garson');

module.exports = garson()
  .prompt(/* some prompt */)
  .prompt(/* another prompt */)
  .prompt(/* one more prompt */)
  .action(/* the only action  */); // you can't chain anything to .action()

It's possible to return another garson object from the action callback:

const { garson, prompts, actions } = require('garson');

const branchA = garson()
  .prompt(/* branch A prompt */)
  .action(/* branch A action */);

const branchB = garson()
  .prompt(/* branch B prompt */)
  .action(/* branch B action */);

module.exports = garson()
  .prompt(/* prompt */)
  .action(results => {
    if (results.someKey) {
      return branchA; // will show branch A prompt and then branch A action
    } else {
      return branchB; // will show branch B prompt and then branch B action
    }
  });

Prompts

Each .prompt() takes two arguments:

  1. prompt key
  2. prompt object

Prompt key is needed to define a property in the result object which is passed into an action callback. Prompt objects defines a type of a prompt.

Input prompts.input()

Provides a text input.

Example:

// garson.config.js
const { garson, prompts, actions } = require('garson');

module.exports = garson()
  // first prompt
  .prompt(
    'firstName',
    prompts.input({
      message: "What's your first name?",
      placeholder: 'E.g. John',
    })
  )
  // second prompt
  .prompt(
    'lastName',
    prompts.input({
      message: "What's your last name?",
      placeholder: 'E.g. Smith',
    })
  )
  // final action
  .action(results => {
    // note the keys of the result object
    const { firstName, lastName } = results;
    actions.printMessage({ message: `Hello, ${firstName} ${lastName}` });
  });

input prompt example

Fuzzy path search prompts.fuzzyPath()

Provides a fuzzy search for a file or a folder in a specified directory.

Example:

// garson.config.js
const { garson, prompts, actions } = require('garson');

const cwd = '/Users/goliney/Workspace/garson/src';
module.exports = garson()
  .prompt(
    'file',
    prompts.fuzzyPath({
      message: 'Enter file:',
      pattern: '**',
      options: {
        nodir: true,
        cwd,
      },
    })
  )
  .action(results => {
    const { file } = results;
    actions.spawn(`nano ${cwd}/${file.path}`);
  });

fuzzy path search prompt example

Choices prompts.choices()

Allows to select a value from the list.

Example:

// garson.config.js
const { garson, prompts, actions } = require('garson');

module.exports = garson()
  .prompt(
    'command',
    prompts.choices({
      message: 'What git command you want to run?',
      items: [
        { label: 'See current branch', value: 'git branch' },
        { label: 'Checkout to master', value: 'git checkout master' },
        { label: 'See status', value: 'git status' },
      ],
    })
  )
  .action(results => {
    const { command } = results;
    actions.spawn(command, { showCommand: true });
  });

choices prompt example

Multi choices prompts.multiChoices()

Allows to select multiple values from the list.

Example:

// garson.config.js
const { garson, prompts, actions } = require('garson');

module.exports = garson()
  .prompt(
    'wcOptions',
    prompts.multiChoices({
      message: 'What do you want to count in garson.config.js file?',
      items: [
        { label: 'Lines', value: 'l', isSelected: true },
        { label: 'Words', value: 'w', isSelected: true },
        { label: 'Characters', value: 'm' },
        { label: 'Everything', value: 'lwm', isSelected: false },
      ],
      // optional handler
      onChangeMiddleware(newItems, oldItems, allItems) {
        const isEverything = item => item.value === 'lwm';
        const newItemsHaveEverythingSelected = newItems.some(isEverything);
        const oldItemsHaveEverythingSelected = oldItems.some(isEverything);

        if (newItemsHaveEverythingSelected && !oldItemsHaveEverythingSelected) {
          // if "Everything" just got selected, deselect everything else
          return allItems.filter(isEverything);
        }

        if (oldItemsHaveEverythingSelected) {
          // if "Everything" was selected, deselect it
          return newItems.filter(item => !isEverything(item));
        }

        return newItems;
      },
    })
  )
  .action(results => {
    const { wcOptions } = results;
    const options = wcOptions.length ? `-${wcOptions.join('')}` : '';
    actions.spawn(`wc ${options} ./examples/multi-choices/garson.config.js`);
  });

multi choices prompt example

Actions

The action takes a single argument - a callback which is invoked with the results of all the prompts that were already shown.

It's up to you to decide what to do next with the result data. Since it's JavaScript environment, your further actions are limited only by Node.

For your convenience garson is shipped with a couple of actions that might get handy.

Print message actions.printMessage()

Shows a text message on the screen.

Example:

// garson.config.js
const { garson, prompts, actions } = require('garson');

module.exports = garson()
  .prompt('name', prompts.input({ message: 'Name:' }))
  .action(results => {
    actions.printMessage({
      boxTitle: 'Greetings',
      message: `Hello, ${results.name}`
    });
  });

print message action example

Spawn actions.spawn()

A wrapper over Node's spawn. It can get handy when you want to run a command in the terminal.

actions.spawn accepts two arguments:

  1. A mandatory command string
  2. An optional spawn options objects. See spawn docs for a full list of parameters. Optionally, you can set { showCommand: true } to see the command before executing it.

Example:

// garson.config.js
const { garson, prompts, actions } = require('garson');

module.exports = garson()
  .prompt(
    'command',
    prompts.choices({
      items: [
        { label: 'See current path', value: 'pwd' },
        { label: 'See current folder content', value: 'ls -al' }
      ]
    })
  )
  .action(results => {
    actions.spawn(results.command, { showCommand: true });
  });

spawn action example

Build your own binary

If you want to build your own binary on top of garson, you can use runner:

#!/usr/bin/env node
const { runner, garson, prompts, actions } = require('garson');

const config = garson()
  .prompt(/* config prompts */)
  .action(/* config actions */);

runner(config);