cmd

package
v0.0.0-...-d983338 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 8, 2026 License: MIT Imports: 17 Imported by: 8

Documentation

Overview

Package cmd defines structures and implements functionality required for creating and managing the command-line interface (CLI) of an application. It leverages the Kong library to parse CLI arguments and execute the associated commands. The package provides common CLI components such as version information and license display, ensuring consistency and reusability throughout the application's command-line utilities.

Struct tags use "name" for CLI flag binding. To also support environment variables, use kong.DefaultEnvars when creating the Kong parser. This automatically maps flags to environment variables (e.g. --postgres-host becomes POSTGRES_HOST).

Usage:

type CLI struct {
    cmd.Commons
    cmd.HTTPServer `embed:"" prefix:""`
    cmd.Postgres   `embed:"" prefix:""`
}

func main() {
    var cli CLI
    ctx := kong.Parse(&cli, kong.DefaultEnvars("MYAPP"))
    // ...
    _ = ctx.Run()
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Commons

type Commons struct {
	Development bool   `short:"D" env:"DEBUG,DEV,DEVELOPMENT" help:"Set to true to enable development mode with debug-level logging."`
	Level       string `short:"l" env:"LOG_LEVEL" help:"Specify the logging level, options are: debug, info, warn, error, fatal." default:"info"`
	Lang        string `env:"LANG" help:"Specify the print lang for tailored message." default:"en"`

	Version Version `cmd:"" help:"Display version information."`
	Licence Licence `cmd:"" help:"Show the application's licence."`
}

Commons defines the common flags and embedded commands shared across all CLI applications. It provides development mode toggling, log level configuration, language selection, and built-in version/licence subcommands.

Usage:

type CLI struct {
    cmd.Commons
    Run RunCmd `cmd:"" default:"withargs" help:"Start the application."`
}

type RunCmd struct{}

func (r *RunCmd) Run(commons *cmd.Commons) error {
    logger := commons.MustLogger()
    defer logger.Sync()
    logger.Info("starting application")
    return nil
}

func main() {
    var cli CLI
    ctx := kong.Parse(&cli, kong.DefaultEnvars("MYAPP"))
    _ = ctx.Run()
}

func (*Commons) Logger

func (c *Commons) Logger() (*zap.Logger, error)

Logger initializes a new zap.Logger based on the Development and Level fields in the commons struct. It returns the configured logger or an error if the logging level is invalid or the logger cannot be created.

func (*Commons) MustLogger

func (c *Commons) MustLogger() *zap.Logger

MustLogger will panic if a logger can't be provided.

func (*Commons) Printer

func (c *Commons) Printer() Printer

Printer returns a new message.Printer configured for the specified language. This printer can be used to format and print localized messages within the command-line interface, ensuring that output is tailored to the user's language preference.

type Config

type Config struct {
	ConfigFile kong.ConfigFlag `json:"config" name:"config" short:"c" help:"Full path to a user-supplied config file"`
	// contains filtered or unexported fields
}

Config provides automatic YAML configuration file loading for Kong CLI applications. It exposes a `--config` / `-c` flag for an explicit override, and otherwise looks for files in host-scoped `/etc/...` and user-scoped `~/...` locations.

Lookup order at startup, first match wins:

  1. `--config <path>` (the [Config.ConfigFile] flag)
  2. user-scoped — `~/.<group>/<name>.yaml`, or `~/.<name>/config.yaml` when no group is set
  3. host-scoped — `/etc/<group>/<name>.yaml`, or `/etc/<name>/config.yaml` when no group is set

`<name>` defaults to the kong application name (the binary name); override with WithName. `<group>` is unset by default; set it with WithGroup to colocate the config alongside other state on disk.

Usage:

type CLI struct {
    cmd.Commons
    Run RunCmd `cmd:"" default:"withargs" help:"Start the application."`
}

func main() {
    // Defaults: ~/.<binary>/config.yaml + /etc/<binary>/config.yaml
    cfg := cmd.NewConfig()

    // With group, colocates under a shared state dir:
    //   ~/.<group>/<binary>.yaml + /etc/<group>/<binary>.yaml
    cfg = cmd.NewConfig(cmd.WithGroup("mygroup"))

    // With group + name, fully custom:
    //   ~/.<group>/<name>.yaml + /etc/<group>/<name>.yaml
    cfg = cmd.NewConfig(cmd.WithGroup("mygroup"), cmd.WithName("config"))

    var cli CLI
    ctx := kong.Parse(&cli,
        kong.DefaultEnvars("MYAPP"),
        kong.Bind(cfg),
    )
    _ = ctx.Run()
}

func NewConfig

func NewConfig(opts ...Option) *Config

func (*Config) BeforeResolve

func (c *Config) BeforeResolve(k *kong.Kong) error

type DBOption

type DBOption func(*sql.DB)

func WithConnMaxIdleTime

func WithConnMaxIdleTime(d time.Duration) DBOption

func WithConnMaxLifetime

func WithConnMaxLifetime(d time.Duration) DBOption

func WithMaxIdleConns

func WithMaxIdleConns(n int) DBOption

func WithMaxOpenConns

func WithMaxOpenConns(n int) DBOption

type HTTPServer

type HTTPServer struct {
	Host              string        `name:"http-host" help:"Host to bind the server to" default:"0.0.0.0"`
	Port              int           `name:"http-port" help:"Port to bind the server to" default:"8080"`
	ReadHeaderTimeout time.Duration `name:"http-read-header-timeout" help:"Max duration for reading the request header" default:"5s"`
	ReadTimeout       time.Duration `name:"http-read-timeout" help:"Max duration for reading the entire request" default:"30s"`
	WriteTimeout      time.Duration `name:"http-write-timeout" help:"Max duration for writing the response" default:"60s"`
	IdleTimeout       time.Duration `name:"http-idle-timeout" help:"Max duration to wait for the next request" default:"120s"`
	GracefulPeriod    time.Duration `name:"http-graceful-period" help:"Period to wait for graceful shutdown" default:"5s"`
}

HTTPServer provides CLI flags for configuring an HTTP server. It handles binding, timeouts, and graceful shutdown.

Usage:

type CLI struct {
    cmd.Commons
    cmd.HTTPServer `embed:"" prefix:""`
    Run RunCmd `cmd:"" default:"withargs" help:"Start the application."`
}

type RunCmd struct{}

func (r *RunCmd) Run(srv *cmd.HTTPServer) error {
    ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
    defer cancel()
    return srv.Start(ctx, zap.L(), mux)()
}

func main() {
    var cli CLI
    ctx := kong.Parse(&cli, kong.DefaultEnvars("MYAPP"))
    _ = ctx.Run()
}

func NewHTTPServer

func NewHTTPServer() *HTTPServer

func (*HTTPServer) Addr

func (srv *HTTPServer) Addr() string

func (*HTTPServer) Start

func (srv *HTTPServer) Start(ctx context.Context, logger *zap.Logger, router http.Handler) func() error

type Licence

type Licence struct {
	// contains filtered or unexported fields
}

Licence holds the licence content of an application. It is automatically registered as a subcommand when embedded via Commons.

Usage:

//go:embed LICENSE
var license string

func main() {
    var cli CLI
    ctx := kong.Parse(&cli,
        kong.DefaultEnvars("MYAPP"),
        kong.Bind(cmd.NewLicence(license)),
    )
    _ = ctx.Run()
}

Then run:

$ myapp licence
MIT License ...

func NewLicence

func NewLicence(s string) Licence

NewLicence creates a new Licence instance with the provided licence content.

func (Licence) Run

func (l Licence) Run() error

Run prints the licence content to the console when the licence command is invoked. This method satisfies the Kong interface contract for command execution.

type Option

type Option func(c *Config)

func WithGroup

func WithGroup(group string) Option

WithGroup namespaces the config under a parent directory. Setting a group changes the lookup paths from the per-binary defaults to a shared parent: `~/.<group>/<name>.yaml` and `/etc/<group>/<name>.yaml`.

Use a group when several binaries share state on disk and you want their config files to live alongside that data — e.g. a daemon `myapp` whose state lives at `~/.myapp/` and a sibling CLI `myapp-cli` can both read from `~/.myapp/<binary>.yaml` by constructing their `Config` with `WithGroup("myapp")`.

Pass an empty group (or skip the option) for single-binary projects — the default lookup is `~/.<binary>/config.yaml` and `/etc/<binary>/config.yaml`, which is enough for most CLIs.

func WithName

func WithName(name string) Option

WithName overrides the config file's basename. Without this option the basename comes from the parsed kong application name (`kong.Model.Name`, normally the binary name). Override when the binary name and the desired config filename should differ — most often to colocate a binary's config under a state directory owned by its broader project, with a generic basename.

Combines with WithGroup:

  • `WithGroup("myapp") + WithName("config")` → `~/.myapp/config.yaml`, `/etc/myapp/config.yaml`
  • `WithGroup("myapp")` alone → `~/.myapp/<binary>.yaml`, `/etc/myapp/<binary>.yaml`
  • `WithName("config")` alone → `~/.config.yaml`, `/etc/config.yaml` (rarely useful; prefer pairing with `WithGroup`)

Empty string is treated as "no override" — the binary name wins.

func (Option) Apply

func (o Option) Apply(c *Config)

type PoolOption

type PoolOption func(*pgxpool.Config)

func WithAfterConnect

func WithAfterConnect(fn func(context.Context, *pgx.Conn) error) PoolOption

func WithAfterRelease

func WithAfterRelease(fn func(*pgx.Conn) bool) PoolOption

func WithBeforeClose

func WithBeforeClose(fn func(*pgx.Conn)) PoolOption

func WithBeforeConnect

func WithBeforeConnect(fn func(context.Context, *pgx.ConnConfig) error) PoolOption

func WithHealthCheckPeriod

func WithHealthCheckPeriod(d time.Duration) PoolOption

func WithMaxConnIdleTime

func WithMaxConnIdleTime(d time.Duration) PoolOption

func WithMaxConnLifetime

func WithMaxConnLifetime(d time.Duration) PoolOption

func WithMaxConnLifetimeJitter

func WithMaxConnLifetimeJitter(d time.Duration) PoolOption

func WithMaxConns

func WithMaxConns(n int32) PoolOption

func WithMinConns

func WithMinConns(n int32) PoolOption

func WithMinIdleConns

func WithMinIdleConns(n int32) PoolOption

func WithPrepareConn

func WithPrepareConn(fn func(context.Context, *pgx.Conn) (bool, error)) PoolOption

func WithShouldPing

func WithShouldPing(fn func(context.Context, pgxpool.ShouldPingParams) bool) PoolOption

type Postgres

type Postgres struct {
	Host            string        `name:"postgres-host" help:"PostgreSQL host" default:"localhost"`
	Port            int           `name:"postgres-port" help:"PostgreSQL port" default:"5432"`
	User            string        `name:"postgres-user" help:"PostgreSQL user" default:"postgres"`
	Password        string        `name:"postgres-password" help:"PostgreSQL password"`
	Database        string        `name:"postgres-database" help:"PostgreSQL database"`
	SSLMode         string        `name:"postgres-ssl-mode" help:"PostgreSQL SSL mode" default:"disable"`
	MaxConns        int32         `name:"postgres-max-conns" help:"Max number of connections" default:"10"`
	MinConns        int32         `name:"postgres-min-conns" help:"Min number of connections" default:"2"`
	MaxConnLifetime time.Duration `name:"postgres-max-conn-lifetime" help:"Max lifetime of a connection" default:"1h"`
	MaxConnIdleTime time.Duration `name:"postgres-max-conn-idle-time" help:"Max idle time of a connection" default:"30m"`
}

Postgres provides CLI flags for configuring a PostgreSQL connection pool.

Usage:

type CLI struct {
    cmd.Commons
    cmd.Postgres `embed:"" prefix:""`
    Run RunCmd `cmd:"" default:"withargs" help:"Start the application."`
}

type RunCmd struct{}

func (r *RunCmd) Run(ctx context.Context, pg *cmd.Postgres) error {
    pool, err := pg.Pool(ctx)
    if err != nil {
        return err
    }
    defer pool.Close()
    // ...
    return nil
}

func main() {
    var cli CLI
    ctx := kong.Parse(&cli, kong.DefaultEnvars("MYAPP"))
    _ = ctx.Run()
}

func NewPostgres

func NewPostgres() *Postgres

func (*Postgres) DSN

func (p *Postgres) DSN() string

func (*Postgres) Pool

func (p *Postgres) Pool(ctx context.Context, options ...PoolOption) (*pgxpool.Pool, error)

type Printer

type Printer interface {
	Sprint(a ...interface{}) string
	Print(a ...interface{}) (n int, err error)
	Println(a ...interface{}) (n int, err error)
	Printf(key message.Reference, a ...interface{}) (n int, err error)
}

type SQLite

type SQLite struct {
	Path            string        `name:"sqlite-path" help:"SQLite database file path" default:":memory:"`
	JournalMode     string        `name:"sqlite-journal-mode" help:"SQLite journal mode" default:"wal"`
	BusyTimeout     int           `name:"sqlite-busy-timeout" help:"Busy timeout in milliseconds" default:"5000"`
	ForeignKeys     bool          `name:"sqlite-foreign-key" help:"Enable foreign keys" default:"true"`
	Synchronous     string        `name:"sqlite-synchronous" help:"Synchronous mode" default:"normal"`
	CacheSize       int           `name:"sqlite-cache-size" help:"Cache size in pages (negative for KiB)" default:"-2000"`
	MaxOpenConns    int           `name:"sqlite-max-open-conns" help:"Max number of open connections" default:"10"`
	MaxIdleConns    int           `name:"sqlite-max-idle-conns" help:"Max number of idle connections" default:"5"`
	ConnMaxLifetime time.Duration `name:"sqlite-conn-max-lifetime" help:"Max lifetime of a connection" default:"1h"`
	ConnMaxIdleTime time.Duration `name:"sqlite-conn-max-idle-time" help:"Max idle time of a connection" default:"30m"`
}

SQLite provides CLI flags for configuring a SQLite database connection.

Usage:

type CLI struct {
    cmd.Commons
    cmd.SQLite `embed:"" prefix:""`
    Run RunCmd `cmd:"" default:"withargs" help:"Start the application."`
}

type RunCmd struct{}

func (r *RunCmd) Run(sq *cmd.SQLite) error {
    db, err := sq.Open()
    if err != nil {
        return err
    }
    defer db.Close()
    // ...
    return nil
}

func main() {
    var cli CLI
    ctx := kong.Parse(&cli, kong.DefaultEnvars("MYAPP"))
    _ = ctx.Run()
}

func NewSQLite

func NewSQLite() *SQLite

func (*SQLite) DSN

func (s *SQLite) DSN() string

func (*SQLite) Open

func (s *SQLite) Open(options ...DBOption) (*sql.DB, error)

type Version

type Version struct {
	buildinfo.BuildInfo
}

Version holds detailed build information for an application, including the name, the specific version string, commit hash, the source of the build, and the build date. It is automatically registered as a subcommand when embedded via Commons.

Usage:

var (
    version     = "dev"
    commit      = "none"
    buildSource = "unknown"
    date        = "unknown"
)

func main() {
    var cli CLI
    ctx := kong.Parse(&cli,
        kong.DefaultEnvars("MYAPP"),
        kong.Bind(cmd.NewVersion("myapp", version, commit, buildSource, date)),
    )
    _ = ctx.Run()
}

Then run:

$ myapp version
name=myapp, version=dev, commit=none, buildDate=unknown, buildSource=unknown

func NewVersion

func NewVersion(name, version, commit, buildSource, date string) Version

NewVersion creates a new Version instance with the given version details.

func (Version) Run

func (u Version) Run() error

Run outputs the version information to the console. It implements the interface required to integrate with the kong CLI parsing library.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL