FUNC - Tiny typed CLI framework

Parameters

Parameter decorators inject runtime context into constructors and handler methods. Undecorated parameters are not filled by func.

Args

@Args() injects FuncArgs, the normalized context for the current command execution.

import { Args, Command, FuncArgs, Handler } from 'func'

@Command({ name: 'config' })
export class ConfigCommand {
  @Handler({ path: ['get'] })
  get(@Args() args: FuncArgs) {
    console.log(args.path)   // ['get']
    console.log(args.inputs) // remaining input after the path
    console.log(args.option) // normalized options
    console.log(args.native) // native arg parser output
  }
}

inputs contains remaining positional input. path contains the selected handler path. option contains normalized option values, including field options and sub-options.

import { Args, Command, FuncArgs, Handler, Value } from 'func'

@Command({ name: 'serve' })
export class ServeCommand {
  @Value()
  port: number = 3000

  @Handler()
  run(@Args() args: FuncArgs) {
    console.log(this.port)
    console.log(args.option.port)
    console.log(args.command?.name)
    console.log(args.handler?.methodName)
  }
}

Regs

@Regs() injects CommandRegistry. It is useful for help output, command lists, and custom suggestions.

import { CommandMajor, CommandRegistry, Handler, Regs } from 'func'

@CommandMajor()
export class Major {
  @Handler({ flag: 'help', alias: 'h' })
  help(@Regs() regs: CommandRegistry) {
    regs.commands.forEach(command => {
      console.log(command.name, command.description)
    })
  }
}

Exception

@Exception() injects FuncException in local catch methods and global error handlers. It exposes code, level, type, message, details, and preventDefaultPrint().

import { Catch, CommandMajor, Exception, FuncException, Handler } from 'func'

@CommandMajor()
export class Major {
  @Catch()
  onError(@Exception() exception: FuncException) {
    console.error(exception.code)
    console.error(exception.message)
    exception.preventDefaultPrint()
  }

  @Handler()
  run() {
    throw new Error('boom')
  }
}

Constructor Injection

Any parameter decorator can also be used in a command constructor. Use this when several handlers need the same runtime context.

import { Args, Command, FuncArgs, Handler, Regs, CommandRegistry } from 'func'

@Command({ name: 'inspect' })
export class InspectCommand {
  constructor(
    @Args() private args: FuncArgs,
    @Regs() private regs: CommandRegistry,
  ) {}

  @Handler()
  run() {
    console.log(this.args.inputs)
    console.log(this.regs.commands.length)
  }
}