Files
mesh-host/internal/compose/resolution/setting_defaults.go
T
jschoubben d68e241724 Take the catalogue's composition rules into the node-engine
ADR 0593 §7: the composer with its refusals leaves mesh-sdk, so mesh-sdk
carries no composition rule. The catalogue functions only the
node-engine's composition reaches (Resolve, Resolution's Compose,
Declaration, DataItems, LeftOut, Rules and the rest, the settings,
placeholder and template refusals, the rendering helpers) are copied
with their tests into internal/compose/resolution; a method of a
mesh-sdk shape becomes a function taking it first. The composition
calls its own copies, and the captured catalogue its tests read lives
here now, shared by mesh-compose's tests.

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
2026-11-02 19:15:55 +01:00

65 lines
2.2 KiB
Go

package resolution
import (
"sort"
mcat "git.novox.be/novox/mesh-sdk/go/catalogue"
)
// meshWords are the settings keys the mesh reads itself; a module declares none of them.
var meshWords = map[string]bool{mcat.PortsSetting: true, mcat.ExposeSetting: true, mcat.ReachSetting: true, mcat.EndpointsSetting: true, mcat.PlacesSetting: true, mcat.AccessesSetting: true, mcat.NetworksSetting: true}
// Defaults is the layer a module's own defaults make, or nothing when it gives none.
func Defaults(m mcat.Manifest) (mcat.Layer, bool) {
if len(m.Settings) == 0 {
return mcat.Layer{}, false
}
values := map[string]any{}
for key, d := range m.Settings {
if d.Default != nil {
values[key] = d.Default
}
}
return mcat.Layer{From: mcat.DefaultLayer, Values: values, Default: true}, len(values) > 0
}
// WithDefaults is a module's layers with its defaults under them, for filling `${setting:<key>}`.
func WithDefaults(m mcat.Manifest, layers []mcat.Layer) []mcat.Layer {
d, has := Defaults(m)
if !has {
return layers
}
return append([]mcat.Layer{d}, layers...)
}
// Effective is every key a module gives a default or a layer sets, with its value and where it came
// from: the default, then the mesh's layer, then the node's — later wins.
func Effective(m mcat.Manifest, layers []mcat.Layer) []mcat.SettingSource {
byKey := map[string]*mcat.SettingSource{}
for key, d := range m.Settings {
if d.Default == nil {
// A required config value has no default (ADR 0348 §4); a settings declaration always has one.
continue
}
byKey[key] = &mcat.SettingSource{Key: key, Value: d.Default, From: mcat.DefaultLayer, FromDefault: true,
Default: d.Default, HasDefault: true}
}
for _, layer := range layers {
// As the layer is said, placement too: `settings` answers it as a person set it.
for key, v := range layer.Whole() {
s, ok := byKey[key]
if !ok {
s = &mcat.SettingSource{Key: key}
byKey[key] = s
}
s.Value, s.From, s.FromDefault = v, layer.From, layer.Default
}
}
out := make([]mcat.SettingSource, 0, len(byKey))
for _, s := range byKey {
out = append(out, *s)
}
sort.Slice(out, func(i, j int) bool { return out[i].Key < out[j].Key })
return out
}