Documentation
¶
Overview ¶
Package cli provides helpers for building command-line applications with go-service.
This package wraps the command framework used by this module (github.com/cristalhq/acmd) and provides a small layer of conveniences for wiring subcommands using go-service DI (Fx/Dig via the `di` package).
In typical service applications, this package is used together with `go-service-template` and the high-level module bundles from the `module` package.
Entry points ¶
Start with `NewApplication` to construct an `Application` and register subcommands via a `RegisterFunc`. Most applications then call either:
- `(*Application).Run` to execute the CLI and return any error, or
- `(*Application).ExitOnError` to log failures and invoke `cli.Exit` with a non-zero status code.
Subcommands and DI wiring ¶
Subcommands are added via `Commander` methods:
- `(*Application).AddServer` creates a long-running server-style command. It starts the DI app and then blocks until the DI app signals completion, stopping it afterwards.
- `(*Application).AddClient` creates a short-lived client-style command. It starts the DI app, then stops it immediately after startup completes.
Each added subcommand returns a `*Command`, which embeds a `*flag.FlagSet`. You can define and parse flags on that `FlagSet`; the command implementation wires the flag set into DI so constructors can read parsed values. Command names must be unique across the application.
Environment-derived metadata ¶
The CLI name and version are derived from environment helpers in `env` and exposed via package variables (`Name` and `Version`) so they can be reused consistently.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrCommandRegistered = errors.New("command already registered")
ErrCommandRegistered indicates a subcommand name has already been registered on an Application.
var Exit = os.Exit
Exit is invoked by (*Application).ExitOnError after logging a startup failure.
Tests may replace this variable to avoid terminating the test process.
var FS = os.NewFS()
FS is the filesystem used by CLI helpers for configuration lookup and reading sources.
It defaults to an `*os.FS` rooted in the host filesystem (see `os.NewFS`). Tests may override this variable to control filesystem reads performed during CLI setup.
var Name = env.NewName(FS)
Name is the CLI application name derived from the environment.
The name is resolved via `env.NewName(FS)` and is used by `Application.Run` to populate the command runner's app metadata (for example help text and descriptions).
var Version = env.NewVersion()
Version is the CLI application version derived from the environment.
The version is resolved via `env.NewVersion()` and is used by `Application.Run` to populate the command runner's version information.
Functions ¶
This section is empty.
Types ¶
type Application ¶
type Application struct {
// contains filtered or unexported fields
}
Application is a command-line application composed of subcommands.
An Application maintains a set of commands and delegates parsing/execution to the underlying command framework (github.com/cristalhq/acmd).
func NewApplication ¶
func NewApplication(register RegisterFunc) *Application
NewApplication constructs an Application and invokes register to add subcommands.
The returned Application is pre-populated with module-level Name and Version derived from the environment (see cli.Name and cli.Version).
func (*Application) AddClient ¶
func (a *Application) AddClient(name, description string, opts ...Option) *Command
AddClient adds a short-lived client subcommand with DI lifecycle wiring.
The returned *Command embeds a *flag.FlagSet. The flag set is parsed before DI startup and is then provided into the DI container so constructors can consume parsed flag values. Command names must be unique across the application.
Execution semantics:
- parse the command args into the command's FlagSet
- build a DI application with panic recovery, a fresh copy of the provided options, plus the command's module
- start the DI application
- stop the DI application immediately after startup completes
Any start/stop error is wrapped with the subcommand name for easier attribution.
func (*Application) AddServer ¶
func (a *Application) AddServer(name, description string, opts ...Option) *Command
AddServer adds a long-running server subcommand with DI lifecycle wiring.
The returned *Command embeds a *flag.FlagSet. The flag set is parsed before DI startup and is then provided into the DI container so constructors can consume parsed flag values. Command names must be unique across the application.
Execution semantics:
- parse the command args into the command's FlagSet
- build a DI application with panic recovery, a fresh copy of the provided options, plus the command's module and runtime.Module
- start the DI application
- block until the DI application's Done channel is closed or ctx is canceled
- stop the DI application
Any start/stop error is wrapped with the subcommand name for easier attribution.
func (*Application) ExitOnError ¶
func (a *Application) ExitOnError(ctx context.Context)
ExitOnError runs the application and terminates the process with exit status 1 if Run returns an error.
The error is logged using the telemetry logger before Exit is invoked.
func (*Application) Run ¶
func (a *Application) Run(ctx context.Context) error
Run executes the application using the configured command set.
Run configures the underlying command runner with:
- app name/description derived from a.name
- version derived from a.version
- sanitized process arguments (see os.SanitizeArgs)
- the provided context
It returns any execution error from the underlying runner or command ExecFunc.
type Command ¶
Command wraps a `*flag.FlagSet` and provides DI wiring for CLI subcommands.
The embedded FlagSet is intended to be configured with flags by the caller, then parsed by the subcommand execution path. The `module` method exposes providers for the filesystem/name/version metadata and the command's FlagSet, and enables DI panic recovery.
func NewCommand ¶ added in v2.66.0
NewCommand creates a new CLI Command with the given name.
The returned Command embeds a `*flag.FlagSet` that you can use to define CLI flags. Application subcommands call `(*flag.FlagSet).Parse` before starting DI, and the Command's `module` wires the parsed FlagSet into the DI container so constructors can read flag values.
type Commander ¶
type Commander interface {
// AddServer registers a long-running server-style subcommand.
//
// Command names must be unique across the entire application.
//
// The subcommand:
// - parses command args into the returned `*Command`'s FlagSet,
// - starts a DI application built from opts plus server-specific wiring,
// - blocks until the DI application signals completion,
// - then stops the DI application.
AddServer(name, description string, opts ...Option) *Command
// AddClient registers a short-lived client-style subcommand.
//
// Command names must be unique across the entire application.
//
// The subcommand:
// - parses command args into the returned `*Command`'s FlagSet,
// - starts a DI application built from opts plus client-specific wiring,
// - then stops the DI application immediately after startup completes.
AddClient(name, description string, opts ...Option) *Command
}
Commander registers CLI subcommands on an application.
Implementations typically add subcommands that build and run a DI application using go-service's `di` package. The returned `*Command` embeds a `*flag.FlagSet` so you can define command-specific flags before execution.
type RegisterFunc ¶
type RegisterFunc = func(commander Commander)
RegisterFunc registers subcommands on a Commander.
A RegisterFunc is invoked by NewApplication to populate the application's command set. Implementations typically call commander.AddServer and/or commander.AddClient.