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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@samipourquoi/commander

v1.4.1

Published

Commander helps you build, dispatch and run commands.

Readme

Commander

NPM

Commander helps you build, dispatch and run commands.

Consider the following commands, each having their 'own things':

  • cmd foo
  • cmd foo <number>
  • cmd fubar
const { Command, NumberType } = require("@samipourquoi/commander");

class MyCommand extends Command {
	constructor() {
		super();
		this.register.with.literal("cmd")
            .with.literal("foo").run(() => console.log("it's a foo!"))
            .____.doc({ description: "It's my foo command!" })
            .____.with.arg("number", NumberType.number).run(w => {
            	console.log("it's a value of " + w + "!")
            }).end
            .or.literal("fubar").run(() => console.log("it's a fubar!"));
	}
}

let cmd = new MyCommand();
cmd.run("cmd foo 4"); // "it's a value of 4!"
cmd.run("cmd fubar"); // "it's a fubar!"
cmd.run("cmd blabla"); // throws an error: "Unable to find command"

Features

TypeScript compatible

This library is written in TypeScript, which makes it usable in both the TS and JS world!

Types

Through types, you can add arguments to your commands! As shown in the example, use the .arg() method to register a typed argument. The in-built types are:

  • NumberType.number: any kind of number;
  • UnquotedType.unquoted: a string without any quotes;
  • QuotedType.quoted: a string surrounded with quotes, allowing spaces in it;
  • WordType.word: a single-worded string composed of the letters of the english alphabet, underscores _ and numbers.

Readable Syntax

The syntax is concise and readable, making the command easy to maintain without having to write dozens of lines every time.

Add documentation

You can easily add documentation to any of your command, at any node (= argument).

Syntax

In Commandier, there are three objects which work together to build commands:

  • Command: the base class of the command;
  • Brancher: a class which represents a 'node', where the command can split into two branches;
  • Register: a class with which you will add an argument.

Branching

From a Brancher, .with will allow you to register from the above node new arguments. We will refer to that as being 'branching'.

this.register.with.literal("help");

.or gets used after having branched. It allows you to add arguments to the node.

this.register
    .with.literal("help")
    .or.literal("help2");

If you have branched twice in a command (a node within another node), use .end to 'go back' to the parent node.

this.register
    .with.literal("help")
    .____.with.literal("inside")
    .____.or.literal("inside2").end
    .or.literal("help2");

Note: .____ is a property of a Brancher which allows you to indent, but which does not mess up with Linters, etc. It does not do anything.

Registering

.with and .or return a Register. From that class, as shown above, you can register arguments with:

  • .literal(...words: string[]) which registers one (or more) plain text words as constants;
  • .arg(name: string, type: Type<unknown>) which registers an named argument from a specified type. cf. above section.

They both return a Brancher.

Running

From a Brancher, use .run(n: any, o: any[]) with a function as a parameter. n being the node's parsed argument and o an array of all the other parsed arguments. That function will get executed when it runs the command, and it arrives at the latest registered argument's node. Careful! if the command is run with invalid arguments, it will throw an error. Make sure to surround the Command.run() with a try...catch statement.

// in the constructor
this.register
    .with.literal("help").run(() => console.log("help!"))
    .____.with.literal("inside").run(() => console.log("input must be 'help inside'!"))
    .____.or.arg("number", NumberType.number).run((n, o) => {
    	console.log(n, o);
    })
    .____.or.literal("inside2").end
    .or.literal("help2");

// somewhere else
try {
    command.run("help inside2"); // "input must be 'help inside'!"
    command.run("help inside3"); // throws an error
    command.run("help 3"); // 3, ['help', 3]
} catch (e) {
    console.error(e);
}

It is possible to return from one .run() to the final command.run("<input>") call. This is encouraged as it allows easier testing.

// in the constructor
this.register
    .with.literal("help").run(() => console.log("help!"))
    .____.with.literal("inside").run(() => "input must be 'help inside'!")
    .____.or.literal("inside2").end
    .or.literal("help2");

// somewhere else
try {
    let msg = command.run("help inside2");
    console.log(msg); // "input must be 'help inside'!"
} catch (e) {
    console.error(e);
}

Documenting

You can easily document what a specific node does using .doc() on a Brancher.

this.register
    .with.literal("help").run(() => console.log("help!"))
    .____.doc({ description: "Sens help about something, hopefully.", author: "samipourquoi" })
    .____.with.literal("inside").run(() => console.log("input must be 'help inside'!"))
    .____.or.literal("inside2").end
    .or.literal("help2");

Credits

Inspired somewhat by Brigadier. Feel free to contact be on Discord samipourquoi#9267 or create an issue for any help.