Skip to content

Programmatic execution

The CLI and every subcommand can be called from code instead of from the terminal. Input is an object, not an argv array, and it is validated against the same schemas.

Note

run is like calling the CLI from the terminal: it parses strings and returns errors in the result. execute is like calling a function: it takes typed values and throws on bad input.

import type { InferOptionsInputType } from "@staticbolt/args-parser";
import { listyCLI } from "./cli.ts";
/** @throws {CliError} */
export function executeListy(options: InferOptionsInputType<typeof listyCLI>) {
listyCLI.execute({ options });
}
/** @throws {CliError} */
export async function executeListyAsync(options: InferOptionsInputType<typeof listyCLI>) {
await listyCLI.executeAsync({ options });
}

The input object

command.execute({
options: {/* ... */},
arguments: {/* ... */},
positionals: [],
});

Fields that you have not defined are not accepted, and fields whose schemas are all optional can be left out entirely. When everything is optional you can call execute() with no argument at all.

Values go in as the schema's input type, so z.number() wants a number, not "3306". No coercion happens here, since nothing arrived as a string.

Sync and async

execute calls the handlers and returns. A promise returned by an async handler is not awaited, so its rejection would go unhandled. Use executeAsync with async handlers.

Both throw a CliError when the input fails validation, or when the command has no handler attached (DefinitionErrorCode.MissingOnExecute).

Handling failure

import { CliError } from "@staticbolt/args-parser";
try {
listyCLI.execute({ options: { listName: "groceries" } });
} catch (error) {
if (error instanceof CliError) {
console.error(error.code, error.message);
}
}

Inside the handler, context.source is "programmatic" for anything you passed this way. See Context.

Types for the input

Type utility Gives you
InferInputType The whole input object
InferOptionsInputType Just the options
InferArgumentsInputType Just the arguments

The output side has the same three. See Type utilities.