Add maintained consumer migration examples
This commit is contained in:
@@ -989,95 +989,10 @@ public records, replay ordering, redaction, rendering, and allocation bounds.
|
||||
|
||||
### Module-specific options
|
||||
|
||||
Use a canonical object entry with an explicit module identifier and options
|
||||
mapping. Shorthand strings and custom structural decoders are not required to
|
||||
express the domain information. For a known application module catalog, model
|
||||
the available option fields with ordinary typed structs; application validation
|
||||
selects the meaningful fields and rejects incompatible combinations.
|
||||
|
||||
Illustrative YAML for an application that supports two modules:
|
||||
|
||||
```yaml
|
||||
modules:
|
||||
- module: chunker
|
||||
options:
|
||||
window_units: 12
|
||||
- module: discussion
|
||||
options:
|
||||
sections: [short_term]
|
||||
```
|
||||
|
||||
The corresponding typed configuration and validator need no second parser:
|
||||
|
||||
```go
|
||||
type ModuleOptions struct {
|
||||
WindowUnits *int `yaml:"window_units"`
|
||||
Sections []string `yaml:"sections"`
|
||||
}
|
||||
|
||||
type ModuleSpec struct {
|
||||
Module string `yaml:"module"`
|
||||
Options ModuleOptions `yaml:"options"`
|
||||
}
|
||||
|
||||
type ModuleConfig struct {
|
||||
Modules []ModuleSpec `yaml:"modules"`
|
||||
}
|
||||
|
||||
func validateModules(cfg *ModuleConfig, v *configkit.Validation) {
|
||||
for index, spec := range cfg.Modules {
|
||||
path := configkit.Keys("modules").Index(index)
|
||||
switch spec.Module {
|
||||
case "chunker":
|
||||
if spec.Options.WindowUnits == nil || *spec.Options.WindowUnits < 1 {
|
||||
v.Error(path.Key("options").Key("window_units"), "must be a positive integer")
|
||||
}
|
||||
if spec.Options.Sections != nil {
|
||||
v.Error(path.Key("options").Key("sections"), "not supported by this module")
|
||||
}
|
||||
case "discussion":
|
||||
if spec.Options.WindowUnits != nil {
|
||||
v.Error(path.Key("options").Key("window_units"), "not supported by this module")
|
||||
}
|
||||
if len(spec.Options.Sections) == 0 {
|
||||
v.Error(path.Key("options").Key("sections"), "must contain at least one section")
|
||||
}
|
||||
default:
|
||||
v.Error(path.Key("module"), "unsupported module")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ReadModuleConfig(path string) (*configkit.Result[ModuleConfig], error) {
|
||||
return configkit.Load(configkit.File(path), configkit.Options[ModuleConfig]{
|
||||
Definition: configkit.Definition[ModuleConfig]{Validate: validateModules},
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
The pointer and nil-slice states above express optional domain values; this
|
||||
application treats explicit null as unselected for those optional alternatives.
|
||||
ConfigKit rejects unknown fields and invalid scalar types. The application owns
|
||||
which supported options apply to a module and their domain constraints. Larger
|
||||
catalogs may use nested typed option objects rather than one flat options struct.
|
||||
Neither shape requires a library registry, parser hook, or configurable merge rule.
|
||||
|
||||
For an application whose option schema is genuinely selected at runtime,
|
||||
`map[string]any` remains available. ConfigKit owns parsing, paths, and the single
|
||||
dynamic scalar representation; application validation owns the selected schema,
|
||||
including allowed keys and value constraints. Conversion into runtime module
|
||||
arguments is application code. Dynamic integers remain checked `int64`; existing
|
||||
`int` assertions must be adapted with range checks when converting to `int`.
|
||||
|
||||
The initial API does not add a generic subtree-conversion helper. Prefer typed
|
||||
configuration where option shapes are known, and direct domain validation where
|
||||
they are dynamic. Do not introduce a second YAML marshal/decode round trip as the
|
||||
blessed pattern. Reconsider a narrow conversion helper only if a concrete dynamic
|
||||
catalog demonstrates substantial duplicated type-binding infrastructure that
|
||||
ordinary models cannot remove. Such a helper would have to retain strictness and
|
||||
source attribution; that is a separate justified extension, not an escape hatch
|
||||
for legacy shorthand. Configuration inspection describes the validated input
|
||||
model, not the application's separately constructed runtime module objects.
|
||||
Canonical typed and dynamic module options are implemented through the ordinary
|
||||
schema. The [current module-options contract](../config.md#canonical-module-options)
|
||||
and [consumer adoption guide](../consumers/README.md) own the maintained object
|
||||
forms, validation boundary, and executable examples.
|
||||
|
||||
### Supported types and projection
|
||||
|
||||
|
||||
Reference in New Issue
Block a user