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 🙏

© 2025 – Pkg Stats / Ryan Hefner

axom

v0.1.1

Published

Command-line flag parsing library for TypeScript/Node.js with a clean, intuitive API

Readme

axom

A comprehensive command-line flag parsing library for TypeScript/Node.js with a clean, intuitive API.

Features

  • 🚀 Easy to use: Simple, intuitive API
  • 🎯 Type-safe: Full TypeScript support with type inference
  • 📦 Core types: Support for bool, number, string, and float
  • 🔧 Custom flags: Implement custom flag types using the Value interface
  • 🎨 Flexible parsing: Support for -flag, --flag, -flag=value, and -flag value syntaxes
  • 🏗️ FlagSet support: Create multiple independent flag sets for subcommands
  • JavaScript-native: Designed specifically for JavaScript/TypeScript environments

Installation

npm install
npm run build

Testing

The library includes comprehensive tests covering all functionality:

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests with coverage
npm run test:coverage

Test Coverage: >80% (25 tests, all passing)

Quick Start

import * as axom from './axom';

// Define flags
const name = axom.string("name", "World", "Your name");
const age = axom.number("age", 0, "Your age");
const verbose = axom.bool("verbose", false, "Enable verbose mode");

// Parse command line
axom.parse();

// Use the values
console.log(`Hello, ${name.value}!`);
console.log(`Age: ${age.value}`);
if (verbose.value) {
    console.log("Verbose mode enabled");
}

Run your program:

ts-node your-program.ts -name John -age 30 -verbose

Usage

Basic Flag Types

Boolean Flags

const verbose = axom.bool("verbose", false, "Enable verbose mode");
axom.parse();

// Usage: -verbose or -verbose=true or -verbose=false
console.log(verbose.value); // true/false

Number Flags

const count = axom.number("count", 10, "Number of items");
const port = axom.number("port", 8080, "Server port");
axom.parse();

// Usage: -count 42 or -count=0x2A or -count=020 (octal)
console.log(count.value); // 42
console.log(port.value); // 8080

String Flags

const name = axom.string("name", "default", "User name");
axom.parse();

// Usage: -name "John Doe" or -name=value
console.log(name.value);

Float Flags

const rate = axom.float("rate", 1.5, "Rate multiplier");
axom.parse();

// Usage: -rate 2.5 or -rate=3.14
console.log(rate.value);

Multiple Flags

Define multiple flags for your application:

// Define all your flags
const port = axom.number("port", 8080, "Server port");
const host = axom.string("host", "localhost", "Server host");
const debug = axom.bool("debug", false, "Debug mode");
const timeout = axom.number("timeout", 5000, "Timeout in ms");

// Parse command line
axom.parse();

// Access the values
console.log(`Server running on ${host.value}:${port.value}`);
console.log(`Timeout: ${timeout.value}ms`);
if (debug.value) {
    console.log("Debug mode enabled");
}

Custom Flag Types

Implement the Value interface to create custom flag types:

class EmailValue implements axom.Value {
    constructor(private email: { value: string }) {}

    set(s: string): Error | null {
        if (!s.includes('@')) {
            return new Error("invalid email format");
        }
        this.email.value = s;
        return null;
    }

    string(): string {
        return this.email.value;
    }
}

const email = { value: "[email protected]" };
axom.varFlag(new EmailValue(email), "email", "[email protected]", "Email address");
axom.parse();

console.log(email.value);

Function Flags

Execute custom logic when a flag is encountered:

const tags: string[] = [];

axom.func("tag", "Add a tag (can be specified multiple times)", (value: string) => {
    tags.push(value);
    return null;
});

axom.parse();
// Usage: -tag one -tag two -tag three
console.log(tags); // ['one', 'two', 'three']

FlagSet for Subcommands

Create independent flag sets for implementing subcommands:

import * as axom from './axom';

const serverCmd = axom.newFlagSet("server", axom.ErrorHandling.ContinueOnError);
const serverPort = serverCmd.number("port", 3000, "Server port");
const serverHost = serverCmd.string("host", "0.0.0.0", "Server host");

const clientCmd = axom.newFlagSet("client", axom.ErrorHandling.ContinueOnError);
const clientURL = clientCmd.string("url", "http://localhost:3000", "Server URL");
const clientRetries = clientCmd.number("retries", 3, "Number of retries");

// Parse main command line
axom.parse();

const subcommand = axom.arg(0);
if (subcommand === "server") {
    serverCmd.parse(axom.args().slice(1));
    console.log(`Starting server on ${serverHost.value}:${serverPort.value}`);
} else if (subcommand === "client") {
    clientCmd.parse(axom.args().slice(1));
    console.log(`Connecting to ${clientURL.value} (${clientRetries.value} retries)`);
}

Usage:

node app.js server -port 8080 -host localhost
node app.js client -url http://api.example.com -retries 5

Error Handling

Control how parsing errors are handled:

const fs = axom.newFlagSet("myapp", axom.ErrorHandling.ContinueOnError);
// ErrorHandling.ContinueOnError - return error
// ErrorHandling.ExitOnError - call process.exit(2)
// ErrorHandling.PanicOnError - throw error

const err = fs.parse(process.argv.slice(2));
if (err) {
    console.error("Error:", err.message);
    // Handle error
}

Accessing Arguments

Get non-flag arguments after parsing:

axom.parse();

console.log(axom.nArg()); // Number of arguments
console.log(axom.args()); // All arguments as array
console.log(axom.arg(0)); // First argument
console.log(axom.arg(1)); // Second argument

Visiting Flags

Iterate over defined or set flags:

// Visit all defined flags
axom.visitAll((f) => {
    console.log(`-${f.name}: ${f.usage} (default: ${f.defValue})`);
});

// Visit only flags that were set
axom.visit((f) => {
    console.log(`-${f.name} = ${f.value.string()}`);
});

Custom Usage Function

Customize the help message:

axom.usage = () => {
    console.log("Custom usage message");
    console.log("\nOptions:");
    axom.printDefaults();
};

axom.parse();
// Run with: -h or -help to see the custom message

Command Line Syntax

The library supports several command-line syntaxes:

# Boolean flags
-verbose
-verbose=true
-verbose=false

# Number/String/Float flags
-count value
-count=value
--count value
--count=value

# Mixing formats
-v -name=John -count 30 file1 file2

# Terminator (stop parsing flags)
-v -name=John -- -not-a-flag file2

Examples

The library includes 10 comprehensive examples demonstrating all features:

  1. Basic Usage - Simple flag definition and parsing
  2. All Types - Bool, number, string, float types
  3. Custom Flags - Custom validation with Value interface
  4. Function Flags - Func and BoolFunc for repeated flags
  5. Subcommands - FlagSet for git/docker style CLIs
  6. Visiting Flags - Inspecting and iterating over flags
  7. Set Flags - Programmatic flag setting
  8. Help & Usage - Custom help messages
  9. Error Handling - Different error handling modes
  10. Advanced - Complete production-ready example

See the examples/ directory and examples/README.md for detailed documentation and usage.

# Run any example
ts-node examples/01-basic-usage.ts -name John -age 30 -verbose
ts-node examples/04-func-flags.ts -v -v -v -add-tag one -add-tag two
ts-node examples/05-flagset-subcommands.ts server -port 8080 -debug

# Run the main example
npm run example -- -name John -age 30 -verbose

API Reference

Top-Level Functions

  • bool(name, value, usage) - Define a boolean flag
  • number(name, value, usage) - Define a number flag (integers and floats)
  • float(name, value, usage) - Define a float flag (alias for number)
  • string(name, value, usage) - Define a string flag
  • varFlag(value, name, usage) - Define a custom flag
  • func(name, usage, fn) - Define a function flag
  • boolFunc(name, usage, fn) - Define a boolean function flag
  • parse() - Parse command line arguments
  • args() - Get remaining non-flag arguments
  • arg(i) - Get i-th non-flag argument
  • nArg() - Get number of non-flag arguments
  • nFlag() - Get number of flags that were set
  • visit(fn) - Visit flags that were set
  • visitAll(fn) - Visit all defined flags

FlagSet Class

  • new FlagSet(name, errorHandling) - Create a new flag set
  • parse(arguments) - Parse arguments
  • bool/number/string/float - Same as top-level functions
  • All other methods mirror the top-level API

License

BSD-3-Clause

Design Philosophy

axom is designed with TypeScript/JavaScript best practices in mind:

  1. Type Safety: Full TypeScript support with type inference
  2. Reference Objects: Returns reference objects with a value property: { value: T }
  3. Type Simplification:
    • Uses JavaScript's unified number type for all numeric values
    • No need for separate signed/unsigned types
    • float is an alias for number for clarity
  4. Flexible Parsing: Supports multiple command-line syntaxes
  5. Error Handling: Uses JavaScript Error objects with clear error messages
  6. Custom Types: Easy to implement custom flag types using the Value interface

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.