Expose layered configuration loading and inspection
This commit is contained in:
74
layered.go
Normal file
74
layered.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package configkit
|
||||
|
||||
import "gitea.maximumdirect.net/eric/ConfigKit/internal/engine"
|
||||
|
||||
// Input selects one source, whether its imports are enabled, and any explicit
|
||||
// filesystem context. A zero Source is invalid; use NoSource() for an omitted
|
||||
// main input. Sources keep their documented reuse and reader ownership rules.
|
||||
type Input struct {
|
||||
Source Source
|
||||
Imports bool
|
||||
Filesystem *FilesystemContext
|
||||
}
|
||||
|
||||
// Underlay contains inputs that must compose strictly within one tier. Tiers
|
||||
// appear in lowest-to-highest precedence order; an empty tier is a no-op.
|
||||
type Underlay struct{ Inputs []Input }
|
||||
|
||||
// LayeredOptions selects lower-priority tiers and final application rules.
|
||||
// An active Overlay requires an explicit OverlayFilesystem; an inactive overlay
|
||||
// ignores it. Overrides remain explicit CLI records, not general mappings.
|
||||
type LayeredOptions[T any] struct {
|
||||
Definition Definition[T]
|
||||
Underlays []Underlay
|
||||
Overlay string
|
||||
OverlayFilesystem *FilesystemContext
|
||||
Overrides []Override
|
||||
}
|
||||
|
||||
// LoadLayered acquires the main input first, strictly composes each underlay,
|
||||
// then applies underlays in order beneath main, a selected overlay, and CLI
|
||||
// overrides. It performs defaults, decoding, resolution, and validation once.
|
||||
// Zero or one options value is accepted; any error returns a nil result.
|
||||
func LoadLayered[T any](main Input, supplied ...LayeredOptions[T]) (*Result[T], error) {
|
||||
options := make([]engine.LayeredOptions[T], len(supplied))
|
||||
for index := range supplied {
|
||||
options[index] = toEngineLayeredOptions(supplied[index])
|
||||
}
|
||||
loaded, err := engine.LoadLayered(toEngineInput(main), secretBinding(), options...)
|
||||
return fromEngineLoaded(loaded, err)
|
||||
}
|
||||
|
||||
func toEngineInput(input Input) engine.Input {
|
||||
return engine.Input{
|
||||
Source: input.Source.toEngine(), Imports: input.Imports,
|
||||
Filesystem: toEngineFilesystemContext(input.Filesystem),
|
||||
}
|
||||
}
|
||||
|
||||
func toEngineLayeredOptions[T any](options LayeredOptions[T]) engine.LayeredOptions[T] {
|
||||
result := engine.LayeredOptions[T]{
|
||||
Definition: toEngineDefinition(options.Definition), Overlay: options.Overlay,
|
||||
OverlayFilesystem: toEngineFilesystemContext(options.OverlayFilesystem),
|
||||
}
|
||||
if options.Underlays != nil {
|
||||
result.Underlays = make([]engine.Underlay, len(options.Underlays))
|
||||
for index, group := range options.Underlays {
|
||||
if group.Inputs != nil {
|
||||
result.Underlays[index].Inputs = make([]engine.Input, len(group.Inputs))
|
||||
for inputIndex, input := range group.Inputs {
|
||||
result.Underlays[index].Inputs[inputIndex] = toEngineInput(input)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if options.Overrides != nil {
|
||||
result.Overrides = make([]engine.Override, len(options.Overrides))
|
||||
for index, override := range options.Overrides {
|
||||
result.Overrides[index] = engine.Override{
|
||||
Path: toEnginePath(override.Path), Value: override.Value, Flag: override.Flag,
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user