@jfhbrook/mrs-commanderson
v1.0.1
Published
command line app framework
Downloads
5
Maintainers
Readme
mrs commanderson
mrs commanderson is a command line parsing library built on top of minimist and director.
install
this package is distributed with npm and may be installed with:
npm install @jfhbrook/mrs-commanderson
examples
the simplest example looks like this:
#!/usr/bin/env node
const { app } = require('../');
app(process.argv.slice(2), async (opts) => {
console.log(`hello ${opts.message}`);
});
this will construct a default minimist ParsedArgs
object and call the main
function with it as a coroutine.
a more interesting example implements subcommands:
#!/usr/bin/env node
const { App } = require('../');
const app = new App();
app.command("init", async (ctx) => {
console.log('init:', ctx);
});
app.command("install :pkg", async (ctx, pkg) => {
console.log('install:', pkg, ctx);
});
app.run(process.argv.slice(2));
this example is pretending to be some kind of installer, and supports the
commands init
and install <some package>
.
api
the api is poorly documented right now, beyond the examples. this is because
there are some issues with the api in the underlying routing library which
I'd like to iron out before going too deep into documentation. that said,
the index.ts
is short and sweet, and router.ts
is well-commented.
background
like a lot of people, I enjoy using minimist to parse options. what it brings to the table is a simple, straightforward API and clear conventions for how cli arguments translate into javascript objects. it's great! I use it in all my cli tools!
however, one thing minimist isn't very good at - or rather, doesn't try to
solve at all - is subcommands. what minimist does instead is collect all
positional arguments and assign them to _: string[]
in the return value.
what minimist is missing is command line routing. a good example of what this might look like is click - click uses a decorators pattern to connect command handlers to routes. click is a little more heavy-handed than what I want though - I still want the lightwight approach of minimist that scales small, while also having just a little extra addition of abstraction to support subcommands.
enter flatiron and director. director is the flatiron framework's router, as would be used in an http server. but they also supported a version of it on the frontend, and - important here - a command line version. in fact, it's what nodejitsu used to power jitsu.
but using director directly, I found a bit of friction. the API made a lot of
compromises to support all three use cases with the same base implementation.
it set this
in function callbacks to a hard-coded context object with
minimal customizability. it was written prior to async/await and didn't support
promises. finally, I was trying to use it with typescript, and the types
available - while workable - weren't quite what I wanted either.
so, here's what I did:
- I took director's core router and cli router, and mashed them together
- I converted the router code into typescript, with additional (but not total) type safety
- I converted the tests to use tap and @jfhbrook/swears, and got the CLI-specific tests running
- I removed "async" (callbacks) routing support and changed everything to await coroutines
- I made the context the first argument to route handlers the context object, and I made the context object fully customizable
- I wrapped it all in an
Application
abstraction which plumbs minimist and the router together.
current status
the basics work - I have the mvp of features for the director router married to minimist options.
however, the truth is tha those compromises the router made are still leaking through to the app-level api. for instance, a custom routing table doesn't actually work right now and there aren't good mechanisms in place for when routes don't match anything.
I'm also trying to decide if I should integrate logging into this library or
not. click only integrates logging insofar as it handles some console encoding
edge cases better than print()
does, but I also have strong opinions on
logging that I set up every time. mrs. commanderson doesn't have logging right
now, but may in the future.
my strategy going forward is going to be trying to use this, and scratching itches / shaving yaks when I really need to.
license
this work is based on director, which has an MIT license. it also incorporates some ideas from the DefinitelyTyped stubs, which have a similarly permissive license. my work is licensed under an apache 2.0 license. for more information, read the LICENSE and NOTICE texts.