# 8. API reference Everything kerf exports, organized by module. Imported via `import { … } from 'kerfjs'` unless noted. ## 8.1 Reactivity ### `signal(initial: T): Signal` A reactive value. `.value` reads / writes; reads inside `effect()` / `computed()` are tracked. ### `computed(fn: () => T): ReadonlySignal` A derived signal. Re-runs `fn` whenever any signal it reads changes. Read-only. ### `effect(fn: () => void): () => void` Run `fn` immediately, then re-run it whenever any signal it reads changes. Returns a disposer. ### `batch(fn: () => void): void` Run `fn`, deferring effect re-runs until `fn` returns. Multiple writes inside `fn` produce a single re-run. ### `Signal` (type) ```ts interface Signal { value: T } ``` ### `ReadonlySignal` (type) ```ts interface ReadonlySignal { readonly value: T } ``` ### `arraySignal(initial?: readonly T[]): ArraySignal` — `kerfjs/array-signal` subpath ```ts import { arraySignal } from 'kerfjs/array-signal'; const rows = arraySignal<{ id: number; label: string }>([]); ``` Granular collection signal. Lives in its own subpath — `import { arraySignal } from 'kerfjs/array-signal'` — so apps that don't use it shed ~1 KB from the main barrel. Pair with `each(...)` inside a `mount()` for O(patches)-not-O(N) reconciles. See `docs/2-reactivity.md` §2.6 for the rationale and gotchas, and `docs/4-render.md` §4.2 (granular reconcile) for how the binding works. ```ts class ArraySignal { readonly value: readonly T[]; // tracking read update(index: number, fn: (item: T) => T): void; // → 1 update patch insert(index: number, item: T): void; // → 1 insert patch push(item: T): void; // sugar for insert(length, item) remove(index: number): T; // → 1 remove patch (returns removed item) move(from: number, to: number): void; // → 1 move patch (no-op if from === to) replace(items: readonly T[]): void; // → 1 replace patch (forces snapshot reconcile) } ``` All mutators throw a descriptive `Error` on out-of-bounds indices. Reads on `arraySig.value` register a tracking dependency just like `signal.value` — `computed(() => arraySig.value.filter(...))` and `effect(() => render(arraySig.value))` work the same way. The `ArraySignal` class is detected via `Symbol.for('kerfjs.ArraySignal')`, not `instanceof`, so multiple bundle copies still interoperate. The brand symbol itself is also exported as **`ARRAY_SIGNAL_BRAND`** from `kerfjs/array-signal` for consumers who build their own collection types and want `each(...)` to recognize them via brand check. The mutator events are surfaced as the **`ArrayPatch`** type — a tagged-union covering `update` / `insert` / `remove` / `move` / `replace`: ```ts type ArrayPatch = | { type: 'update'; index: number; item: T } | { type: 'insert'; index: number; item: T } | { type: 'remove'; index: number } | { type: 'move'; from: number; to: number } | { type: 'replace'; items: readonly T[] }; ``` Most consumers never touch `ArrayPatch` directly — `each(...)` consumes the queue internally. Export the type when you want to observe patches from outside `each()` (e.g. logging, persistence layers, custom reconcilers). ## 8.2 Stores ### `defineStore(spec): Store` ```ts defineStore({ initial: () => TState, actions: (set: (next: TState) => void, get: () => Readonly) => TActions, }); ``` Creates a store with `state: ReadonlySignal`, `actions: TActions`, `reset(): void`. Registers in the global registry consumed by `resetAllStores()`. `set(next)` REPLACES state; it does NOT merge. Pass the full state object on every call, or use `set({ ...get(), ...patch })` to merge. In dev mode (`NODE_ENV !== 'production'`), `get()` returns a frozen snapshot so that `get().count = 42`-style mutations throw a native `TypeError` (KF-141). Opt in to the runtime narrow-set warning with `KERF_DEV_WARN_NARROW_SET=1` to catch partial-set bugs at the moment they happen (KF-212; see [docs/11-dev-warnings.md](11-dev-warnings.md) for the full dev-warn family). ### `resetAllStores(): void` Calls `reset()` on every store registered via `defineStore()`. ### `Store` (type) ```ts interface Store { readonly state: ReadonlySignal; readonly actions: TActions; reset(): void; } ``` ### `clearStoreRegistry(): void` — `kerfjs/testing` subpath Empties the global store registry. Used by unit tests to isolate cases. Imported via the `kerfjs/testing` subpath, **not** the main `kerfjs` entry, so production builds don't pull it in: ```ts import { clearStoreRegistry } from 'kerfjs/testing'; ``` ## 8.3 Render ### `mount(rootEl: HTMLElement, render: () => MountResult): () => void` ```ts type MountResult = SafeHtml | string | number | boolean | null | undefined; ``` Bind `render()` to `rootEl`'s children. Wraps `effect()` with kerf's segment-aware diff. Returns a disposer. If `rootEl` belongs to an *inert* document (no browsing context — e.g. a `DOMParser` result, a `