Documentation
¶
Index ¶
- func Discover(sources []string) ([]string, error)
- func IsAncestorOf(candidate, anchor ParsedFile) bool
- func LeafKey(dotPath string) string
- func MapDepth(data map[string]interface{}) int
- func MarkShadowed(tree map[string]*Node)
- func Merge(files []ParsedFile, mode config.MergeMode, scopePrefix string) (map[string]*Node, error)
- func ToEnvEntries(tree map[string]*Node) map[string]EnvEntry
- func ToEnvEntriesFromAnchor(tree map[string]*Node, anchorData map[string]interface{}) map[string]EnvEntry
- func ToEnvVars(tree map[string]*Node) map[string]string
- func ToEnvVarsFromAnchor(tree map[string]*Node, anchorData map[string]interface{}) map[string]string
- func ToFlatEnvEntries(tree map[string]*Node, preferPrefix string) (map[string]EnvEntry, error)
- type Conflict
- type ConflictError
- type EnvConflict
- type EnvConflictError
- type EnvEntry
- type LineMap
- type Node
- type Origin
- type ParsedFile
- func FilterByAnchor(anchor ParsedFile, all []ParsedFile) []ParsedFile
- func Load(path string, dec sops.Decryptor) (ParsedFile, error)
- func LoadAll(paths []string, dec sops.Decryptor) ([]ParsedFile, error)
- func SortBySpecificity(files []ParsedFile) []ParsedFile
- func TrimToScope(ancestor ParsedFile, dirFiles []ParsedFile) ParsedFile
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Discover ¶
Discover returns all *.ward files found recursively under each source path. Order within each source is deterministic (lexicographic).
func IsAncestorOf ¶
func IsAncestorOf(candidate, anchor ParsedFile) bool
isAncestorOf returns true if every map-valued key in candidate exists in anchor recursively. Leaf-valued keys in candidate are ignored — an ancestor may declare attributes that the anchor doesn't have. What matters is that the anchor covers all structural branches the candidate declares.
Example: candidate has company.sectors.one.name (leaf) → ancestor of staging.ward Example: candidate has company.production (map) → NOT ancestor of staging.ward IsAncestorOf is the exported version of isAncestorOf.
func MarkShadowed ¶
MarkShadowed walks the tree and sets Overrides=true on any leaf that would be shadowed by a deeper leaf with the same key name (same as shadow rule in ToFlatEnvEntries). This lets view display shadowed leafs in orange.
func Merge ¶
Merge merges a sequence of ParsedFiles in config order (index 0 = first vault, last = last vault). Conflict rule: if two files define the exact same leaf dot-path → conflict (in MergeModeError). If they define different dot-paths they coexist in the tree regardless of depth. When scopePrefix is non-empty, conflicts outside that dot-path prefix are silently overridden.
func ToEnvEntries ¶
ToEnvEntries is like ToEnvVars but preserves origin information.
func ToEnvEntriesFromAnchor ¶
func ToEnvEntriesFromAnchor(tree map[string]*Node, anchorData map[string]interface{}) map[string]EnvEntry
ToEnvEntriesFromAnchor is like ToEnvVarsFromAnchor but preserves origin information.
func ToEnvVars ¶
ToEnvVars converts all leaf nodes of a merged tree into env var pairs with full path. Example: company.sectors.one.staging.database_url → COMPANY_SECTORS_ONE_STAGING_DATABASE_URL
func ToEnvVarsFromAnchor ¶
func ToEnvVarsFromAnchor(tree map[string]*Node, anchorData map[string]interface{}) map[string]string
ToEnvVarsFromAnchor returns env vars scoped to the anchor's container level, using relative names (stripping the common ancestor prefix). Example: anchor at company.sectors.one → NAME, STAGING_DATABASE_URL, etc.
func ToFlatEnvEntries ¶
ToFlatEnvEntries returns only the leaf values as env vars using just the leaf key name (uppercased), without any path prefix. Used by ward envs/exec without --prefixed.
Shadow rule: when two dot-paths share the same leaf key name and one is a descendant of the other (e.g. app.log_level and app.config.log_level), the deeper one wins silently — the shallower is shadowed (dropped). This is NOT a conflict.
Collision: same leaf key name at unrelated dot-paths → EnvConflictError, unless preferPrefix is set — then the entry whose dot-path is under preferPrefix wins, and all other entries for that env key are discarded. Other (non-colliding) vars from the full tree are still included.
Types ¶
type ConflictError ¶
type ConflictError struct {
Conflicts []Conflict
}
ConflictError is returned when one or more keys are defined in multiple files at the same level.
func (*ConflictError) Error ¶
func (e *ConflictError) Error() string
type EnvConflict ¶
type EnvConflict struct {
EnvKey string
DotPaths [2]string
CaseCollision bool // true when keys are the same name but different case
}
EnvConflict holds a single env var name collision between two dot-paths.
type EnvConflictError ¶
type EnvConflictError struct {
Conflicts []EnvConflict
}
EnvConflictError is returned when flat env var names collide across different dot-paths.
func (*EnvConflictError) Error ¶
func (e *EnvConflictError) Error() string
type EnvEntry ¶
type EnvEntry struct {
Value string
Origin Origin
Overrides bool // true when this value replaced a value from an ancestor file
}
EnvEntry holds an env var's value and the origin node it came from.
type Node ¶
type Node struct {
Value interface{}
Origin Origin
Overrides bool // true when this value replaced a value from a less-specific (ancestor) file
Children map[string]*Node
}
Node is either a leaf value with an origin, or a nested map.
type ParsedFile ¶
type ParsedFile struct {
File string
Data map[string]interface{}
Lines LineMap // dot-path → line number
RawLines []string // source lines for snippet display
}
ParsedFile holds the decoded content of a .ward file before merging.
func FilterByAnchor ¶
func FilterByAnchor(anchor ParsedFile, all []ParsedFile) []ParsedFile
FilterByAnchor returns files that share at least one root key with the anchor, plus the anchor itself, ordered from least specific to most specific. A file is only included as an ancestor if it is strictly less deep than the anchor (its map-branch depth is shallower than the anchor's deepest map branch).
func Load ¶
func Load(path string, dec sops.Decryptor) (ParsedFile, error)
Load decrypts and parses a .ward file into a ParsedFile.
func LoadAll ¶
func LoadAll(paths []string, dec sops.Decryptor) ([]ParsedFile, error)
LoadAll loads all files using the given decryptor.
func SortBySpecificity ¶
func SortBySpecificity(files []ParsedFile) []ParsedFile
SortBySpecificity sorts files from least specific to most specific. Specificity = total number of dot-paths across all keys (more = more specific).
func TrimToScope ¶
func TrimToScope(ancestor ParsedFile, dirFiles []ParsedFile) ParsedFile
TrimToScope removes from ancestor's data any map branches that do not exist in any of the dir files. This prevents sibling-sector data from leaking into an unrelated dir anchor scope. Example: company.ward has sectors.one and sectors.two — when used as ancestor of a dir anchor for sectors/two, sectors.one should be stripped.