CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-stricli--core

Build complex CLIs with type safety and no dependencies

Overview
Eval results
Files

commands-and-routing.mddocs/

Commands and Routing

Define commands and organize them into nested route maps.

Quick Reference

// Simple command
const cmd = buildCommand({
  func: async function(flags, arg1, arg2) { /* ... */ },
  parameters: { flags: { /* ... */ }, positional: { /* ... */ } },
  docs: { brief: "Description" }
})

// Lazy-loaded command
const cmd = buildCommand({
  loader: () => import("./commands/deploy.js"),
  parameters: { /* ... */ },
  docs: { brief: "Description" }
})

// Route map
const routes = buildRouteMap({
  routes: { cmd1, cmd2, nested: nestedRouteMap },
  defaultCommand: "cmd1",  // optional
  docs: { brief: "Description" },
  aliases: { c: "cmd1" }  // optional
})

buildCommand

Builds a command from a function or loader with parameters and documentation.

function buildCommand<FLAGS, ARGS, CONTEXT>(
  builderArgs: CommandBuilderArguments<FLAGS, ARGS, CONTEXT>
): Command<CONTEXT>

Local Function:

buildCommand({
  func: async function(flags, ...args) {
    this.process.stdout.write("Hello\n");
  },
  parameters: {
    flags: { /* FlagParametersForType<FLAGS> */ },
    positional: { /* TypedPositionalParameters<ARGS> */ },
    aliases: { /* single-char to flag name mapping */ }
  },
  docs: {
    brief: "Short description",
    fullDescription: "Optional longer description"
  }
})

Lazy-Loaded Function:

buildCommand({
  loader: async () => import("./commands/deploy.js"),  // or () => CommandFunction
  parameters: { /* ... */ },
  docs: { /* ... */ }
})

// In commands/deploy.ts:
export default async function(flags, ...args) {
  // Command implementation
}

CommandFunction Signature:

type CommandFunction<FLAGS, ARGS, CONTEXT> = (
  this: CONTEXT,
  flags: FLAGS,
  ...args: ARGS
) => void | Error | Promise<void | Error>

Validation: Checks for reserved flags (--help, --helpAll, -h, -H), negation collisions, and variadic separators.

buildRouteMap

Organizes commands into nested structures with optional default command and aliases.

function buildRouteMap<R extends string, CONTEXT>(
  args: RouteMapBuilderArguments<R, CONTEXT>
): RouteMap<CONTEXT>

Example:

const dbRoutes = buildRouteMap({
  routes: {
    connect: connectCmd,
    migrate: migrateCmd,
    backup: backupCmd
  },
  defaultCommand: "connect",  // Optional: runs when user types "myapp db"
  docs: { brief: "Database commands" },
  aliases: { c: "connect", m: "migrate", b: "backup" }  // Optional
});

const app = buildApplication(
  buildRouteMap({
    routes: {
      db: dbRoutes,
      server: serverCmd
    },
    docs: { brief: "Application CLI" }
  }),
  { name: "myapp" }
);

// Usage:
// myapp db connect --host localhost
// myapp db c --host localhost  (using alias)
// myapp db  (runs default connect command)
// myapp server --port 8080

Validation: Route map must contain at least one route, aliases can't conflict with route names, default command must be a Command (not another RouteMap).

Complete Example

import { buildApplication, buildRouteMap, buildCommand, numberParser } from "@stricli/core";

// Commands
const deployCmd = buildCommand({
  func: async function(flags, service) {
    this.process.stdout.write(`Deploying ${service} to ${flags.env}\n`);
  },
  parameters: {
    flags: {
      env: { kind: "enum", values: ["dev", "staging", "prod"], brief: "Environment", default: "dev" },
      force: { kind: "boolean", brief: "Force deployment" }
    },
    positional: {
      kind: "tuple",
      parameters: [{ brief: "Service name", parse: String }]
    },
    aliases: { e: "env", f: "force" }
  },
  docs: { brief: "Deploy service" }
});

const statusCmd = buildCommand({
  func: async function(flags) {
    this.process.stdout.write(`Checking status (verbose: ${flags.verbose})\n`);
  },
  parameters: {
    flags: {
      verbose: { kind: "boolean", brief: "Verbose output", default: false }
    },
    aliases: { v: "verbose" }
  },
  docs: { brief: "Check status" }
});

// Route map
const app = buildApplication(
  buildRouteMap({
    routes: {
      deploy: deployCmd,
      status: statusCmd
    },
    docs: { brief: "Deployment CLI" }
  }),
  {
    name: "myapp",
    scanner: { caseStyle: "allow-kebab-for-camel" }
  }
);

// Usage:
// myapp deploy api --env prod --force
// myapp deploy api -e prod -f
// myapp status --verbose
// myapp status -v

Related

  • Flag Parameters
  • Positional Parameters
  • Configuration and Context

Install with Tessl CLI

npx tessl i tessl/npm-stricli--core

docs

application.md

commands-and-routing.md

configuration-and-context.md

documentation-and-help.md

error-handling.md

exit-codes.md

flag-parameters.md

index.md

parameter-parsers.md

positional-parameters.md

text-and-localization.md

tile.json