@jayalfredprufrock/flagship
v0.0.4
Published
Tiny type-safe flag parser for node CLIs.
Readme
Type-safe CLI flag parsing built on Node's built-in util.parseArgs. Fully infers output types from flag definitions, supports custom parsing and validation (sync or async), and has zero runtime dependencies.
Installation
npm install @jayalfredprufrock/flagshipUsage
Shorthands
For common cases, use a shorthand string instead of a full flag definition:
import { parseFlags } from "@jayalfredprufrock/flagship";
const flags = await parseFlags({
name: "string*", // string (required)
env: "string", // string | undefined
port: "number", // number | undefined
verbose: "boolean", // boolean | undefined
tags: "string[]", // string[] | undefined
});The * suffix marks a flag as required. The [] suffix accepts multiple values (flag can be repeated). Both can be combined: 'number[]*'.
Full example
import { parseFlags } from "@jayalfredprufrock/flagship";
const flags = await parseFlags(
{
env: {
parse: (value) => value as "development" | "production" | "test",
required: true,
validate: (value) => {
if (!["development", "production", "test"].includes(value)) {
throw new Error(`Invalid --env: ${value}`);
}
},
},
port: {
parse: (value) => parseInt(value, 10),
default: (ctx) => (ctx.flags.env === "production" ? 80 : 3000),
},
verbose: {
type: "boolean",
parse: Boolean,
short: "v",
},
outputDir: {
parse: async (value) => resolveOutputDir(value),
default: "./dist",
},
},
{ allowPositionals: true },
);
// flags.env → 'development' | 'production' | 'test'
// flags.port → number
// flags.verbose → boolean | undefined
// flags.outputDir → stringAPI
parseFlags(flags, options?)
parseFlags<F>(flags: F, options?: ParseOptions): Promise<ParsedFlags<F>>Parses process.argv (or a custom args array) and returns a fully-typed object of resolved flag values. Flags are processed in definition order; each flag's default and validate callbacks receive the flags resolved so far via context.flags.
camelCase flag names are automatically aliased to kebab-case — outputDir is accepted as both --outputDir and --output-dir.
strict mode and allowNegative (for --no-<flag> booleans) are enabled by default.
FlagDef
interface FlagDef<Input, Output> {
parse: (input: Input, context: FlagContext) => Output | Promise<Output>;
type?: "string" | "boolean"; // default: 'string'
multiple?: boolean; // accept repeated flag values
required?: boolean; // throw if not provided and no default resolves
short?: string; // single-char alias, e.g. 'v' → -v
default?: Output | ((context: FlagContext) => Output | Promise<Output>);
validate?: (output: Output, context: FlagContext) => void | Promise<void>;
}Input is inferred automatically:
stringwhentypeis'string'(default)booleanwhentypeis'boolean'string[]/boolean[]whenmultiple: true
Output is inferred from the return type of parse.
Throw from validate to signal an invalid value. Throwing from parse is also fine for parse-time errors.
FlagContext
interface FlagContext {
name: string; // name of the flag being processed
flags: Record<string, any>; // flags fully resolved so far (definition order)
}Passed as the second argument to parse and validate, and as the sole argument to default when it is a function. Useful for computing derived defaults or cross-field validation.
ParseOptions
All fields from Node.js ParseArgsConfig except options:
| Option | Default | Description |
| ------------------ | ----------------------- | -------------------------------------------- |
| args | process.argv.slice(2) | Override the argv to parse (useful in tests) |
| allowPositionals | false | Allow positional arguments |
| allowNegative | true | Allow --no-<flag> negation syntax |
| strict | true | Throw on unknown flags |
| tokens | false | Include token metadata in parse output |
Shorthands
Shorthand strings expand to a predefined FlagDef. The * suffix sets required: true; the [] suffix sets multiple: true.
| Shorthand | Output type |
| -------------- | ------------------------ |
| 'string' | string \| undefined |
| 'string*' | string |
| 'string[]' | string[] \| undefined |
| 'string[]*' | string[] |
| 'boolean' | boolean \| undefined |
| 'boolean*' | boolean |
| 'boolean[]' | boolean[] \| undefined |
| 'boolean[]*' | boolean[] |
| 'number' | number \| undefined |
| 'number*' | number |
| 'number[]' | number[] \| undefined |
| 'number[]*' | number[] |
Number shorthands parse the raw string value and throw if it is not a valid number.
Utilities
parseNumber(value: string): number — Parses a string to a number; throws on NaN. Used internally by number shorthands, but exported for use in custom FlagDef.parse functions.
camelToKebab(str: string): string — Converts a camelCase string to kebab-case. Used internally to alias flag names.
