Validation & Constraints¶
BOA provides several ways to validate and constrain parameter values.
Required vs Optional¶
By default, all parameters are required. Mark parameters as optional explicitly:
type Params struct {
Name string // required
Port int `optional:"true"` // optional
Verbose bool `optional:"true"` // optional
}
Allowed Values (Alternatives)¶
Use alts to restrict a parameter to specific values:
type Params struct {
LogLevel string `alts:"debug,info,warn,error"`
Format string `alts:"json,yaml,toml"`
}
This provides:
- Shell completion - Tab completion suggests valid values
- Validation - Invalid values are rejected (when
strictis true, which is the default)
Strict Mode¶
By default, alts enforces validation. To allow any value while still providing completion hints:
type Params struct {
// Validation enforced (default)
LogLevel string `alts:"debug,info,warn,error" strict:"true"`
// Suggestions only, any value accepted
Color string `alts:"red,green,blue" strict:"false"`
}
Conditional Requirements¶
Make parameters conditionally required based on other values using HookContext:
type Params struct {
Mode string
FilePath string `optional:"true"`
URL string `optional:"true"`
}
func main() {
boa.CmdT[Params]{
Use: "app",
InitFuncCtx: func(ctx *boa.HookContext, p *Params, cmd *cobra.Command) error {
// FilePath required when Mode is "file"
ctx.GetParam(&p.FilePath).SetRequiredFn(func() bool {
return p.Mode == "file"
})
// URL required when Mode is "http"
ctx.GetParam(&p.URL).SetRequiredFn(func() bool {
return p.Mode == "http"
})
return nil
},
RunFunc: func(p *Params, cmd *cobra.Command, args []string) {
// ...
},
}.Run()
}
type Params struct {
Mode string
FilePath string `optional:"true"`
URL string `optional:"true"`
}
func main() {
boa.NewCmdT[Params]("app").
WithInitFuncCtx(func(ctx *boa.HookContext, p *Params, cmd *cobra.Command) error {
// FilePath required when Mode is "file"
ctx.GetParam(&p.FilePath).SetRequiredFn(func() bool {
return p.Mode == "file"
})
// URL required when Mode is "http"
ctx.GetParam(&p.URL).SetRequiredFn(func() bool {
return p.Mode == "http"
})
return nil
}).
WithRunFunc(func(p *Params) {
// ...
}).
Run()
}
Conditional Visibility¶
Hide parameters entirely based on conditions:
type Params struct {
Debug bool `optional:"true"`
Verbose bool `optional:"true"`
}
func main() {
boa.CmdT[Params]{
Use: "app",
InitFuncCtx: func(ctx *boa.HookContext, p *Params, cmd *cobra.Command) error {
// Verbose flag only visible when Debug is true
ctx.GetParam(&p.Verbose).SetIsEnabledFn(func() bool {
return p.Debug
})
return nil
},
RunFunc: func(p *Params, cmd *cobra.Command, args []string) {
// ...
},
}.Run()
}
type Params struct {
Debug bool `optional:"true"`
Verbose bool `optional:"true"`
}
func main() {
boa.NewCmdT[Params]("app").
WithInitFuncCtx(func(ctx *boa.HookContext, p *Params, cmd *cobra.Command) error {
// Verbose flag only visible when Debug is true
ctx.GetParam(&p.Verbose).SetIsEnabledFn(func() bool {
return p.Debug
})
return nil
}).
WithRunFunc(func(p *Params) {
// ...
}).
Run()
}
Dynamic Alternatives¶
For alternatives that depend on runtime state, use SetAlternatives in a hook:
func (c *Config) InitCtx(ctx *boa.HookContext) error {
// Set alternatives based on available options
envs := []string{"dev", "staging", "prod"}
ctx.GetParam(&c.Environment).SetAlternatives(envs)
ctx.GetParam(&c.Environment).SetStrictAlts(true)
return nil
}
Value Priority¶
When multiple sources provide values, BOA uses this priority:
- CLI flags -
--port 8080 - Environment variables -
PORT=8080 - Config files - (via PreValidate hook)
- Default values -
default:"8080" - Zero value -
0for int,""for string, etc.
Higher priority sources override lower ones.