package ckconfig import ( "context" "io" commandkit "gitea.maximumdirect.net/eric/CommandKit" configkit "gitea.maximumdirect.net/eric/ConfigKit" ) // Selection carries the configuration and overlay choices supplied for a // configuration scope. type Selection struct { // Config is the caller-supplied configuration path, if present. Config commandkit.Supplied[string] // Overlay is the caller-supplied overlay path, if present. Overlay commandkit.Supplied[string] } // Operation identifies a supported configuration inspection operation. type Operation string const ( // Validate checks the selected configuration and reports diagnostics. Validate Operation = "validate" // Show writes the selected configuration's effective form. Show Operation = "show" // Sources reports the selected configuration's input sources. Sources Operation = "sources" // Explain reports the history and provenance of a selected path. Explain Operation = "explain" ) // Request describes one configuration operation and its selected inputs. type Request struct { // Operation identifies the requested inspection operation. Operation Operation // Selection carries the explicit config and overlay inputs. Selection Selection } // EffectiveWriter writes a configuration's native effective representation. type EffectiveWriter interface { WriteEffective(io.Writer) error } // SourceReader reports the native source inventory for a configuration. type SourceReader interface { Sources() []configkit.SourceInfo } // ExplanationReader reads and writes a configuration's native path explanation. type ExplanationReader interface { Explain(configkit.Path) (configkit.Explanation, bool) WriteExplanation(io.Writer, configkit.Path) error } // View exposes native configuration facets without reconstructing their // reports. type View struct { Effective EffectiveWriter Sources SourceReader Explanation ExplanationReader } // Scope declares the operations and acquisition callback for one named // configuration. Construction issues are retained privately until family // assembly attaches them to its command declaration. type Scope[I, S any] struct { // Name identifies the scope in CLI selection and reports. Name string // Summary describes the scope. Scope discovery reports name and operations only. Summary string // Operations selects the standard handlers exposed for this scope. Operations []Operation // Acquire loads the selected configuration for one inspection invocation. Acquire func(context.Context, Request, I, S) (commandkit.Acquired[View], error) issues []error } // Selector binds a typed flag to the configuration scopes that use it. type Selector[I any] struct { // Binding is the original typed flag handle captured by the suite. Binding commandkit.Flag[I] // Scopes lists the scope names that receive this flag's value. Scopes []string } // Suite declares the typed input, shared state, selectors, and configuration // scopes used to assemble configuration commands. // // Input initialization is separate for each selected scope; state is shared // by that invocation's acquisitions. Factory results and callback effects remain // caller-owned: Command does not deep-copy arbitrary objects or repair aliases // returned by factories. Core-owned repeated flag collections are copied when // applied to separate inputs. Factories are not invoked during construction, // installation, help, version, or scope discovery, and need not run after failure. type Suite[I, S any] struct { // NewInput is called once for each selected scope reached after operation // preflight, before applying its selectors and calling CheckInput. // If nil, input is the zero value of I, including nil for pointer types. NewInput func() I // NewState is called once when acquisition is reached, after all selected // inputs pass their checks. The result is shared by selected acquisitions. // If nil, state is the zero value of S, including nil for pointer types. NewState func() S // Selectors declares typed flags and their applicable scopes. Selectors []Selector[I] // CheckInput validates one initialized scope input after applicable values are applied. CheckInput func(scope string, selection Selection, input I) error // Scopes declares the configuration scopes assembled by Command. Scopes []Scope[I, S] } // WithScopeError returns a copy of scope that retains err as a construction // issue for ckconfig.Command to report during installation. Existing issues // remain available to family assembly, and scope is not mutated. A nil error // returns scope unchanged. func WithScopeError[I, S any](scope Scope[I, S], err error) Scope[I, S] { if err == nil { return scope } issues := make([]error, len(scope.issues), len(scope.issues)+1) copy(issues, scope.issues) scope.issues = append(issues, err) return scope }