Path Syntax & Validation
Relevant source files
The following files were used as context for generating this wiki page:
The Path Syntax & Validation system in keyfold is responsible for parsing and verifying the configuration strings provided during the creation of a merger. These paths define how the library navigates nested state trees to apply reconciliation policies (via keyBy) or wholesale replacement rules (via replace).
Validation occurs strictly at configuration time within createMerger, ensuring that malformed or contradictory policies are caught before any data processing begins. This early validation maintains the library's guarantee of failure-safety and determinism.
Sources: src/paths.ts:25, README.md:162-167, AGENTS.md:37-38
Path Syntax Overview
Paths in keyfold are dot-separated strings representing property names within a nested object structure. A special [] suffix is used to denote movement into the items of a keyed list.
Grammar Rules
- Property Names: Must be dot-separated identifiers.
- List Item Marker: The
[]suffix indicates recursion into the items of the preceding list. - Limitations: There are no wildcards, array indices (e.g.,
items[0]), root tokens, or escaping mechanisms. Properties containing characters like.,[, or]are currently unaddressable.
Sources: src/paths.ts:11, README.md:154-160, test/config.test.ts:10
| Syntax Segment | Meaning | Example |
|---|---|---|
prop | A plain object property | "order.customer" |
list[] | Recursion into items of a keyed list | "items[].components" |
prop.list | A list located at a nested property | "order.items" |
Sources: src/paths.ts:31-38, README.md:156-158
Configuration Compilation
When createMerger is called, it invokes compileOptions to transform the user-provided MergeOptions into a CompiledOptions object containing a PolicyNode tree. This tree is a compiled representation of the merging rules.
The diagram shows the sequence of validation and tree construction steps performed during configuration compilation.
Sources: src/paths.ts:25-83, src/merge.ts:19-21
Data Structures
The system uses a recursive tree structure to store compiled policies.
The diagram illustrates the recursive relationship of PolicyNodes used to navigate state during a merge.
Sources: src/paths.ts:10-21
Validation Rules
The compiler enforces strict rules to prevent contradictory or impossible merge scenarios.
1. Identity Field Safety
Identity fields specified in keyBy must be strings and cannot use reserved keys that might interfere with JavaScript internals or library operators.
- Reserved Keys:
$delete,__proto__,constructor,prototype. - Format: Must match the
PROPERTYregex (no dots or brackets).
Sources: src/paths.ts:22-23, src/paths.ts:117-121, test/config.test.ts:16-21
2. Policy Reachability
A replace policy at a specific path creates a boundary. Since replacement is a wholesale operation that does not recurse, any policy nested beneath a replaced path is considered "dead config" and causes a KeyfoldConfigError.
- Redundancy: Duplicate
replacepaths are rejected. - Shadowing: A broader
replace(e.g.,a) makes a narrowerreplace(e.g.,a.b) unreachable. - Nesting: A
keyBypolicy cannot exist inside a path marked for wholesalereplace. - Exception: The "item-swap idiom" (
items[]marked for replacement under a listitemskeyed byid) is permitted.
Sources: src/paths.ts:57-78, test/config.test.ts:31-45, README.md:112-117
3. Keyed List Integrity
The compiler ensures that the [] marker is used correctly in relation to defined keys.
- Trailing
[]inkeyBy: AkeyBypath addresses the list itself, not its items, so it must not end in[]. - Missing Keys: Stepping through a list using
[]requires that the list has an associatedkeyBypolicy. - Missing Suffix: Stepping through a keyed list without using the
[]suffix is an error.
Sources: src/paths.ts:48-52, src/paths.ts:124-140, test/config.test.ts:23-25, test/config.test.ts:53-61
Implementation Details
The path parsing utilizes a specific regex to identify property segments and optional item markers.
// src/paths.ts:22-23
const SEGMENT = /^([^.[\]]+)(\[\])?$/;
const PROPERTY = /^[^.[\]]+$/;
Path Parsing Logic
The parsePath function splits the input string by . and processes each segment. If a segment includes the [] suffix, it is pushed into the segments array as two distinct entries: the property name and a special ITEM constant ("[]").
Sources: src/paths.ts:11, src/paths.ts:86-106
Summary
The Path Syntax & Validation system ensures that all merge behaviors are deterministic and statically valid before data is processed. By rejecting malformed segments, reserved property names, and unreachable policies, it protects the library's immutable and failure-safe invariants.