Documentation
¶
Overview ¶
Package transform provides composable, post-merge / pre-decode transformations on the merged configuration tree.
FastConf's reload pipeline is conceptually:
discover → decode → merge/patch → [TRANSFORMERS] → decodeInto(*T)
→ validate → publish
A Transformer is a pure function `func(map[string]any) error` that may mutate the in-place merged map before it is decoded into the user's strongly-typed struct. Built-in transformers cover the most common cases (defaults, env interpolation, key aliasing, deletion). Users can also write their own.
Transformers run in declaration order and are wired via `fastconf.WithTransformers(...)`. Failures abort the reload and the previously committed state is preserved (same guarantee as every other stage).
Design notes:
- Transformers operate on `map[string]any` rather than `*T` so they remain decoupled from the user type and can be reused across multiple Manager[T] instances.
- Path syntax used by helpers below is dotted: "a.b.c". Numeric indices into slices are NOT supported (config trees are usually small maps; complex array surgery belongs in RFC 6902 patches).
- All helpers tolerate a nil root map (treated as empty); they never panic on missing intermediate nodes.
Index ¶
- Variables
- func Wrap(name string, err error) error
- type ExpandMergeMode
- type LabelExpandOptions
- type RawCapture
- type Transformer
- func Aliases(mapping map[string]string) Transformer
- func Defaults(values map[string]any) Transformer
- func DeletePaths(paths ...string) Transformer
- func EnvSubst() Transformer
- func EnvSubstWith(lookup func(string) string) Transformer
- func ExpandLabels(at, to string, opts LabelExpandOptions) Transformer
- func MergeByKey(dotPath, keyField string) Transformer
- func SetIfAbsent(path string, value any) Transformer
- type TransformerFunc
Constants ¶
This section is empty.
Variables ¶
var ErrTransform = errors.New("fastconf/internal/transform")
ErrTransform is returned wrapped by built-in transformers on failure.
Functions ¶
Types ¶
type ExpandMergeMode ¶
type ExpandMergeMode uint8
ExpandMergeMode selects how ExpandLabels grafts its expanded tree.
const ( // ExpandReplace overwrites the value at To with the expanded subtree. ExpandReplace ExpandMergeMode = iota // ExpandOverlay deep-merges the expanded subtree on top of existing keys. ExpandOverlay // ExpandUnderlay deep-merges the expanded subtree beneath existing keys. ExpandUnderlay )
type LabelExpandOptions ¶
type LabelExpandOptions struct {
// Prefix, when non-empty, restricts expansion to labels whose key starts
// with this prefix (e.g. "traefik.").
Prefix string
// StripPrefix removes Prefix from each key before expansion.
StripPrefix bool
// Separator splits a flat key into nested segments. Default ".".
Separator string
// Coerce, when true, converts "true"/"false"/int/float strings into typed
// values. Default false: values are kept verbatim (matches Traefik /
// Compose label semantics).
Coerce bool
// KeepSource, when true, leaves the original source list at At untouched.
// Default false: the source list is removed after expansion so the
// downstream struct does not need to model it.
KeepSource bool
// MergeMode controls how the expanded tree is grafted onto root at To:
// ExpandReplace (default) — set the expanded subtree at To, overwriting
// any pre-existing scalar/map at that path
// ExpandOverlay — deep-merge the expanded subtree on top of
// any pre-existing map at To (label wins)
// ExpandUnderlay — deep-merge the expanded subtree underneath
// any pre-existing map at To (pre-existing wins)
MergeMode ExpandMergeMode
}
LabelExpandOptions controls ExpandLabels behavior. Mirrors mappath.LabelOptions so callers do not need to import two packages.
type RawCapture ¶
type RawCapture struct {
// contains filtered or unexported fields
}
RawCapture is a Transformer that snapshots one or more dotted-path values as json.RawMessage after the merge phase but before decoding into *T. This is the recommended solution for map[string][]json.RawMessage protocol blocks: register a RawCapture transformer, decode *T normally, then call rawCapture.Get(path) to retrieve the opaque bytes.
RawCapture is safe for concurrent reads (Get/All) after a reload.
Usage:
rc := transform.CaptureRaw("listeners", "upstreams")
mgr, _ := fastconf.New[Config](ctx,
fastconf.WithTransformers(rc),
// ... other options
)
cfg := mgr.Get()
raw, _ := rc.Get("listeners") // raw is json.RawMessage
func CaptureRaw ¶
func CaptureRaw(paths ...string) *RawCapture
CaptureRaw returns a new RawCapture transformer that will snapshot the values at the given dotted paths on every reload.
func (*RawCapture) All ¶
func (r *RawCapture) All() map[string]json.RawMessage
All returns a snapshot of all captured path → JSON bytes. The returned map is a copy and is safe for the caller to retain.
func (*RawCapture) Get ¶
func (r *RawCapture) Get(path string) (json.RawMessage, bool)
Get returns the most recently captured JSON bytes for the given path. Returns false if the path was not registered or was missing at last reload.
type Transformer ¶
Transformer mutates the merged configuration tree. Returning an error aborts the reload. Implementations MUST be safe to call concurrently with reads of unrelated Manager instances but are guaranteed to be invoked serially within a single reload.
func Aliases ¶
func Aliases(mapping map[string]string) Transformer
Aliases returns a Transformer that rewrites legacy keys to their new home. If the target path already has a value the new world wins and the alias is dropped.
func Defaults ¶
func Defaults(values map[string]any) Transformer
Defaults returns a Transformer that recursively merges the supplied values into the tree, only filling keys that are missing.
func DeletePaths ¶
func DeletePaths(paths ...string) Transformer
DeletePaths returns a Transformer that removes the specified dotted-path keys from the tree. Missing paths are silently ignored.
func EnvSubst ¶
func EnvSubst() Transformer
EnvSubst returns a Transformer that walks every string value in the tree and substitutes occurrences of ${VAR} or ${VAR:-default}.
func EnvSubstWith ¶
func EnvSubstWith(lookup func(string) string) Transformer
EnvSubstWith is like EnvSubst but reads variables through the supplied lookup function.
func ExpandLabels ¶
func ExpandLabels(at, to string, opts LabelExpandOptions) Transformer
ExpandLabels returns a Transformer that reshapes a Traefik / Docker / K8s style label list found at the dotted-path `at` into a nested subtree grafted at the dotted-path `to`. When `to` is empty the expanded tree is grafted at the configuration root.
Accepted input shapes at `at`:
- []string{"a.b=1", "a.c=2"} — Compose / docker CLI
- []any{"a.b=1", "a.c=2"} — YAML-decoded form
- map[string]string / map[string]any — engine API / annotation form
Example with the Compose deploy.labels shape:
# input.yaml
deploy:
labels:
- "traefik.http.services.dummy.loadbalancer.server.port=9999"
- "traefik.enable=true"
transform.ExpandLabels("deploy.labels", "", transform.LabelExpandOptions{})
// Result (deploy.labels removed by default; KeepSource=true to keep it):
traefik:
http:
services:
dummy:
loadbalancer:
server:
port: "9999"
enable: "true"
Malformed entries (no '=' separator, empty key after prefix trim) are silently dropped, matching Traefik's lenient behavior. A missing source path is also silently ignored (the transformer is a no-op).
func MergeByKey ¶
func MergeByKey(dotPath, keyField string) Transformer
MergeByKey returns a Transformer that merges an array of maps by a key field, enabling overlay files to modify individual entries without replacing the entire array.
The array at the given dotted path is expected to contain map[string]any items each with a distinguishing field (keyField). Items from the current array are merged on top of items from the same-keyed base item. If a key appears only once the item is kept as-is.
This is useful for protocol-block patterns where each entry has an identifier:
listeners:
- name: http
port: 80
- name: https
port: 443
A subsequent overlay with only the https entry will update port 443 without discarding the http entry.
func SetIfAbsent ¶
func SetIfAbsent(path string, value any) Transformer
SetIfAbsent sets a single dotted-path key only when it has no value.
type TransformerFunc ¶
TransformerFunc adapts a plain function to the Transformer interface.
func (TransformerFunc) Name ¶
func (t TransformerFunc) Name() string