Procyon|Docs
Configuration

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.

property_sources.go
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.

property_sources.go
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:

property_sources.go
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:

property_sources.go
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.

property_sources.go
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.

vault_source.go
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:

environment.go
env.PropertySources().PushFront(vaultSource)