Property Sources
Understand how Procyon stores, orders, and resolves configuration values.
A property source is a named collection of configuration values. Procyon keeps
all sources in PropertySources and checks them in order when resolving a key.
sources := config.NewPropertySources()
sources.PushBack(config.NewMapPropertySource("defaults", map[string]any{
"server.port": 8080,
"server.host": "0.0.0.0",
}))Source order
The first source that contains a key wins.
Use PushFront for higher-priority overrides and PushBack for lower-priority
defaults.
sources.PushBack(defaults)
sources.PushFront(overrides)Procyon uses the same ordering model during startup. Command-line arguments are placed at the front, environment variables are added as another source, and configuration files are applied by the environment customizer.
Managing sources
PropertySources gives you basic operations for runtime composition:
if sources.Has("defaults") {
existing, _ := sources.Get("defaults")
index := sources.IndexOf(existing)
sources.Replace("defaults", config.NewMapPropertySource("defaults", map[string]any{
"server.port": 9090,
}))
log.Printf("replaced defaults property source at index %d", index)
}You can also remove a source when a temporary override should no longer affect resolution:
removed := sources.Remove("testOverrides")
if removed {
log.Print("temporary test overrides removed")
}Map sources
NewMapPropertySource accepts nested maps and flattens them into dot-separated
properties.
source := config.NewMapPropertySource("app", map[string]any{
"database": map[string]any{
"host": "localhost",
"port": 5432,
},
})The source exposes database.host and database.port.
Custom property sources
Implement config.PropertySource when values come from a place that is not a
static map or file.
type VaultPropertySource struct {
values map[string]string
}
func (s *VaultPropertySource) Name() string {
return "vault"
}
func (s *VaultPropertySource) Origin() string {
return "vault://application"
}
func (s *VaultPropertySource) Value(name string) (any, bool) {
value, ok := s.values[name]
return value, ok
}
func (s *VaultPropertySource) ValueOrDefault(name string, defaultValue any) any {
if value, ok := s.Value(name); ok {
return value
}
return defaultValue
}
func (s *VaultPropertySource) PropertyNames() []string {
names := make([]string, 0, len(s.values))
for name := range s.values {
names = append(names, name)
}
return names
}Add it to the environment when it should participate in normal lookup and binding:
env.PropertySources().PushFront(vaultSource)