package configkit import ( "encoding/json" "fmt" "io" "reflect" "strconv" "gitea.maximumdirect.net/eric/ConfigKit/internal/engine" ) // Secret is an opaque reference to an environment variable. Its name is public // configuration; its resolved value is available only through Value. type Secret struct { name, value string specified, resolved bool } // SecretEnv constructs an unresolved environment-backed secret reference. // Invalid names are reported if the reference survives a configuration load. func SecretEnv(name string) Secret { return Secret{name: name, specified: true} } // EnvName returns the public environment-variable name. func (s Secret) EnvName() string { return s.name } // Value returns the resolved credential, or an empty string when unresolved. func (s Secret) Value() string { if !s.resolved { return "" } return s.value } // IsResolved reports whether this reference resolved to a nonempty value during its configuration load. func (s Secret) IsResolved() bool { return s.resolved } // Format renders only the public reference name for every formatting verb. func (s Secret) Format(state fmt.State, _ rune) { _, _ = io.WriteString(state, "configkit.SecretEnv("+strconv.Quote(s.name)+")") } // MarshalJSON emits only the public environment-variable name. func (s Secret) MarshalJSON() ([]byte, error) { return json.Marshal(s.name) } func secretBinding() engine.SecretBinding { return engine.SecretBinding{Type: reflect.TypeFor[Secret](), Read: func(value reflect.Value) engine.SecretState { secret := value.Interface().(Secret) return engine.SecretState{Name: secret.name, Value: secret.value, Specified: secret.specified, Resolved: secret.resolved} }, Make: func(state engine.SecretState) reflect.Value { return reflect.ValueOf(Secret{name: state.Name, value: state.Value, specified: state.Specified, resolved: state.Resolved}) }} }