Installation & Setup
Relevant source files
The following files were used as context for generating this wiki page:
@b2m9/keyfold is a zero-dependency TypeScript library designed to fold partial deltas into plain state trees, featuring identity-keyed list reconciliation. The library ensures immutability and deterministic behavior, returning the base reference for semantic no-ops and maintaining structural sharing for untouched branches.
The installation and setup process involves integrating the library into a Node.js environment (version 22 or higher) and configuring a merger function through createMerger. This function compiles path policies—such as keyed lists and replacement boundaries—once at creation time to ensure runtime efficiency and safety.
Sources: README.md:1-20, AGENTS.md:7-16
Environment Requirements
The project is built as an ESM-only package and requires a modern Node.js runtime.
| Requirement | Value | Source |
|---|---|---|
| Node.js Version | >= 22 | package.json:69 |
| Module System | ESM-only | AGENTS.md:13, package.json:28 |
| TypeScript Version | ^7.0.2 | package.json:62 |
| Language Target | ES2022 | tsconfig.json:3 |
The following diagram illustrates the toolchain and validation flow used during development and setup:
Sources: package.json:37-47, AGENTS.md:13-16
Library Installation
The library is published as a scoped package and can be installed via standard package managers.
npm install @b2m9/keyfold
Sources: README.md:37-39
Initializing the Merger
The core of the library is the createMerger function. It takes a MergeOptions object to define how different paths in the state tree should be handled. This configuration is validated and compiled into a PolicyNode tree during initialization.
Configuration Options
The MergeOptions interface allows developers to customize the behavior of the fold operation.
| Option | Type | Description |
|---|---|---|
keyBy | Record<string, string> | Maps a list path (e.g., items) to its identity field (e.g., id). |
replace | string[] | Specifies paths that should be swapped wholesale rather than merged. |
wireDeletes | boolean | Enables interpretation of DELETE_TOKEN ("@@keyfold/delete") as a field deletion. |
Sources: src/types.ts:3-19, src/paths.ts:24-40
Policy Compilation Flow
When createMerger is called, it triggers compileOptions to validate paths and ensure reachability.
Sources: src/merge.ts:16-26, src/paths.ts:24-83
Path Configuration Syntax
Paths are defined as dot-separated strings. A specific syntax [] is used to denote the entry into a keyed list's items.
- Object Path:
order.customer - Keyed List Path:
order.items(configured inkeyBy) - Keyed Item Path:
order.items[](used inreplacefor item-swap idiom) - Nested Keyed List:
order.items[].components
Path Validation Rules
- Reserved Keys: Paths cannot contain
__proto__,constructor, orprototype. - Keyed Context: A path using
[]must have a correspondingkeyBypolicy for the parent list. - Unreachable Policies: A
replacepath at a high level (e.g.,order) makes deeper policies (e.g.,order.items) unreachable and will throw aKeyfoldConfigError. - Identity Fields: Identity fields must be strings or numbers and cannot be
$deleteor other reserved keys.
Sources: src/paths.ts:85-156, README.md:105-115
TypeScript Setup
To leverage full type safety, the library provides the Delta<T, Atomic> utility type. This ensures that deltas are structurally valid according to the base state T.
Atomic Types
By default, the runtime treats class instances and built-ins (like Date, Map, Set) as atomic, meaning they are replaced rather than merged. For custom application classes, the Atomic type parameter should be used to prevent TypeScript from attempting a structural merge of the class properties.
import { createMerger, type Delta } from "@b2m9/keyfold";
class UserSession {
constructor(public id: string) {}
}
interface State {
session: UserSession;
}
// UserSession is passed as an Atomic type
const merge = createMerger<State, UserSession>();
Sources: src/types.ts:21-46, README.md:80-100
Summary
Setting up @b2m9/keyfold requires a Node.js 22+ environment and a clear definition of state paths. By configuring keyBy and replace policies during the initialization of createMerger, developers establish a deterministic and immutable reconciliation logic that is compiled once for optimal performance. The library’s reliance on explicit path configuration and strict identity matching provides a safe alternative to standard merge utilities for complex, nested state trees.
Sources: AGENTS.md:7-12, README.md:117-130