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).RunCode` to execute the CLI and return a process exit code.
Use `WithExitCodeFunc` when an application needs to map specific errors to specific process exit codes.
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 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, opts ...ApplicationOption) *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) 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.
func (*Application) RunCode ¶ added in v2.372.0
func (a *Application) RunCode(ctx context.Context) int
RunCode executes the application and returns the process exit code that represents the result.
RunCode returns 0 when Run succeeds. When Run returns an error, RunCode logs the error using the telemetry logger and returns the configured exit code for that error.
type ApplicationOption ¶
type ApplicationOption interface {
// contains filtered or unexported methods
}
ApplicationOption configures an Application constructed by NewApplication.
Options are applied in the order provided to NewApplication. If multiple options configure the same field, the last one wins.
func WithExitCodeFunc ¶ added in v2.372.0
func WithExitCodeFunc(f ExitCodeFunc) ApplicationOption
WithExitCodeFunc configures how RunCode chooses a process exit code for an error.
If f returns zero or a negative value for a non-nil error, the application falls back to exit code 1.
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 ExitCodeFunc ¶ added in v2.372.0
ExitCodeFunc maps an application execution error to a process exit code.
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.