Core Concepts
A func app registers decorated classes in a
FuncModule. At runtime, func finds the class that matches
the user's CLI input, selects one handler method, injects fields and parameters, then
runs the handler.
Command Scopes
A command scope is the class that owns the current CLI input. Start with the two common cases: no command name, and a named command.
Major Command
@CommandMajor runs when the user invokes the CLI without a command name.
import { CommandMajor, Handler } from 'func'
@CommandMajor()
export class MajorCommand {
@Handler()
run() {
console.log('welcome')
}
}Named Command
@Command runs when the first input token matches its
name or alias.
import { Command, Handler } from 'func'
@Command({ name: 'build', alias: 'b' })
export class BuildCommand {
@Handler()
run() {
console.log('build')
}
}| User Input | Runs | Why |
|---|---|---|
my-cli | MajorCommand | There is no command name, so the major command runs. |
my-cli build | BuildCommand | The first input token matches build. |
my-cli b | BuildCommand | The first input token matches the command alias. |
Unknown Command
@CommandMissing is optional. Use it when you want a custom message for
input that does not match any named command.
import { CommandMissing } from 'func'
@CommandMissing()
export class MissingCommand {
constructor() {
console.log('unknown command')
}
}| User Input | Runs | Why |
|---|---|---|
my-cli unknown | MissingCommand | The first input token is not a registered command. |
Handlers
Every command scope needs at least one @Handler method. A handler can
be the default method, a flag-triggered method, or a path method. Path handlers are
checked before flag handlers, and the longest matching path wins.
import { Command, Handler } from 'func'
@Command({ name: 'config' })
export class ConfigCommand {
@Handler({ path: ['get'] })
get() {
console.log('get config')
}
@Handler({ flag: 'help', alias: 'h' })
help() {
console.log('usage')
}
@Handler()
run() {
console.log('config')
}
}
For my-cli config get, the path handler runs. For
my-cli config --help, the flag handler runs. If no path or flag
handler matches, the default handler runs.
Modules and Services
@FuncModule can register commands, import feature modules, and register
services. Services are instantiated once and can depend on other registered services.
import { Command, FuncModule, Handler, Service, run } from 'func'
@Service()
class ProjectService {
name() {
return 'demo'
}
}
@Command({ name: 'build' })
class BuildCommand {
constructor(private project: ProjectService) {}
@Handler()
run() {
console.log(this.project.name())
}
}
@FuncModule({
commands: [BuildCommand],
services: [ProjectService],
})
class AppModule {}
run(AppModule)Next Topics
Use Field Options for flags and values,
Parameters for @Args,
@Regs, and @Exception, and Errors
for local and global error handling.