API Reference

Complete reference for all exported functions and types.

input(value)

Creates a leaf input node. External code sets the value.

Signature

TYPESCRIPT
function input<T>(value: T): InputNode<T>

Parameters

ParameterTypeDescription
valueTInitial value of any type

Returns

An InputNode<T> with methods:

  • get(): T — returns current value
  • set(value: T): void — updates value, marks dependents dirty
  • invalidate(): void — forces invalidation of dependents
  • isDirty(): false — inputs are never dirty
  • inspect(): InspectInfo — debug information
  • dispose(): void — disconnect from graph

Example

input-example.ts TYPESCRIPT
const width = input(800)
width.get()     // 800
width.set(600)  // marks dependents dirty

node(options)

Creates a computed node with declared dependencies. Lazy evaluation, cached results.

Signature

TYPESCRIPT
function node<DependsOn extends Record<string, Node<any>>, R>(
  options: {
    dependsOn: DependsOn
    compute: (values: ResolvedValues<DependsOn>) => R
  }
): ComputedNode<R>

Options

PropertyTypeDescription
dependsOnRecord<string, Node>Map of names to dependency nodes
compute(values) => RFunction that computes the result from resolved dependency values

Returns

A ComputedNode<R> with methods:

  • get(): R — returns cached value or recomputes if dirty
  • isDirty(): boolean — true if any dependency changed
  • invalidate(): void — forces recompute on next get()
  • inspect(): InspectInfo — debug information
  • dispose(): void — disconnect from graph

Example

node-example.ts TYPESCRIPT
const width = input(800)
const height = input(600)

const area = node({
  dependsOn: { w: width, h: height },
  compute: ({ w, h }) => w * h
})

area.get()    // 480000
area.get()    // 480000 (cached)
width.set(1000)
area.get()    // 600000 (recomputed)

Important

The compute function must be pure. No side effects. It may be called multiple times or not at all depending on cache state.

batch(fn)

Executes a function atomically. All input sets within the batch trigger a single invalidation walk. Returns the set of changed nodes.

Signature

TYPESCRIPT
function batch<T>(fn: () => T): T | Set<Node<any>>

Example

batch-example.ts TYPESCRIPT
const changed = batch(() => {
  width.set(1000)
  height.set(800)
})
// changed = Set of all dirtied nodes

why(node)

Traces the invalidation path for a node. Returns an array of node names from the target back to the source inputs that caused invalidation.

Signature

TYPESCRIPT
function why(node: Node<any>): string[]

Example

why-example.ts TYPESCRIPT
const cardHeight = node({
  dependsOn: { textHeight, padding },
  compute: ({ textHeight, padding }) => textHeight + padding
})

width.set(400)  // triggers textHeight recompute
why(cardHeight) // ['cardHeight', 'textHeight', 'width']

ancestors(node) / descendants(node)

Navigate the dependency graph. ancestors returns all upstream dependencies. descendants returns all downstream dependents.

Signature

TYPESCRIPT
function ancestors(node: Node<any>): Set<Node<any>>
function descendants(node: Node<any>): Set<Node<any>>

Example

graph-nav.ts TYPESCRIPT
const a = input(1)
const b = node({ dependsOn: { a }, compute: ({ a }) => a * 2 })
const c = node({ dependsOn: { b }, compute: ({ b }) => b + 1 })

ancestors(c)   // Set { b, a }
descendants(a) // Set { b, c }

toDot(nodes)

Exports the dependency graph as Graphviz DOT format for visualization.

Signature

TYPESCRIPT
function toDot(nodes: Node<any>[]): string

Example

dot-example.ts TYPESCRIPT
console.log(toDot([area]))
// Output:
// digraph G {
//   "width" -> "area"
//   "height" -> "area"
// }
// Paste to graphviz.online to visualize

stats(nodes)

Returns statistics about the dependency graph.

Signature

TYPESCRIPT
function stats(nodes: Node<any[]>): {
  nodeCount: number
  inputCount: number
  computedCount: number
  edgeCount: number
  totalComputeCalls: number
}

Example

stats-example.ts TYPESCRIPT
stats([root])
// {
//   nodeCount: 5,
//   inputCount: 2,
//   computedCount: 3,
//   edgeCount: 4,
//   totalComputeCalls: 12
// }

TypeScript Types

InputNode<T>

TYPESCRIPT
interface InputNode<T> {
  get(): T
  set(value: T): void
  invalidate(): void
  isDirty(): false
  inspect(): InspectInfo
  dispose(): void
}

ComputedNode<T>

TYPESCRIPT
interface ComputedNode<T> {
  get(): T
  isDirty(): boolean
  invalidate(): void
  inspect(): InspectInfo
  dispose(): void
}

InspectInfo

TYPESCRIPT
interface InspectInfo {
  id: string
  name: string
  type: 'input' | 'computed'
  value?: any
  dirty: boolean
  dependencyCount: number
  dependentCount: number
}