GraphReFly is a synchronous reactive graph runtime for building inspectable data flows. Code defines the graph, the graph emits facts, and inspection APIs let tools, tests, UIs, and agents see what exists and why it changed.
This repository contains the current TypeScript implementation:
@graphrefly/ts.
npm install @graphrefly/tsimport { graph } from "@graphrefly/ts";
const g = graph({ name: "pricing" });
const price = g.state(100, { name: "price" });
const tax = g.derived([price], (p) => p * 0.0825, { name: "tax" });
const total = g.derived([price, tax], (p, t) => p + t, { name: "total" });
total.subscribe((msg) => {
if (msg[0] === "DATA") console.log(msg[1]);
});
price.set(120);
console.log(g.topology());
console.log(g.describe());@graphrefly/ts is self-contained: substrate, graph layer, operators, sources,
storage helpers, framework adapters, messaging, work queues, orchestration,
CQRS, renderers, testing helpers, and solution modules live in one package.
| Package | Status |
|---|---|
@graphrefly/ts |
Current TypeScript package. Use this for all new work. |
@graphrefly/graphrefly |
Retired root package name. Deprecated on npm; use @graphrefly/ts. |
@graphrefly/pure-ts |
Retired old TypeScript implementation. Deprecated on npm; use @graphrefly/ts. |
There is no compatibility layer for the retired packages. The clean-slate
package uses focused subpaths instead of the old root, utils, base,
compat, and presets surfaces.
- Graph-owned
state,derived,producer,effect, andmountsugar. - Glitch-free synchronous wave propagation through a dispatcher.
- Free-standing operator factories such as
map,filter,scan,switchMap,combine,buffer,debounceTime, andcatchError. - Sources for values, iterables, promises, timers, events, HTTP/SSE/WebSocket driver boundaries, webhooks, cron-like schedules, and Node-specific process or filesystem bindings.
- Inspectable graph structure via
topology(),describe(),observe(),observeTopology(), diagnostics, renderers, and optional profiling. - Passive storage helpers for strict JSON, KV, append logs, WAL frames, content-addressed storage, read-through tiers, and observe-event logs.
- Reactive collections:
reactiveMap,reactiveList,reactiveLog,reactiveIndex, views, persistence helpers, and cascading cache. - Focused framework/runtime adapters for React, Vue, Svelte, Solid, NestJS, observe-storage, wire bridge, tool-provider runtimes, and worker/work queues.
The graph core is synchronous. Async work belongs at source, adapter, executor, worker, storage, or wire-bridge boundaries and returns to the graph as explicit messages, facts, or commands.
Use the root for the common surface:
import { graph, map, memoryKv, describeToMermaid } from "@graphrefly/ts";Use focused subpaths when you want clearer ownership or better bundle shape:
import { graph } from "@graphrefly/ts/graph";
import { map, switchMap } from "@graphrefly/ts/operators";
import { fromPromise, timer } from "@graphrefly/ts/sources";
import { memoryKv } from "@graphrefly/ts/storage";
import { describeToMermaid } from "@graphrefly/ts/render";
import { useNodeValue } from "@graphrefly/ts/adapters/react";Node-only and browser-only helpers are split:
import { nodeProcessDriver } from "@graphrefly/ts/sources/node";
import { indexedDbKv } from "@graphrefly/ts/storage/browser";import { graph, map, scan } from "@graphrefly/ts";
const g = graph({ name: "counter" });
const count = g.state(0, { name: "count" });
const doubled = g.initNode(map((n: number) => n * 2), [count], { name: "doubled" });
const sum = g.initNode(scan((acc: number, n: number) => acc + n, 0), [doubled], {
name: "sum",
});
sum.subscribe((msg) => {
if (msg[0] === "DATA") console.log("sum", msg[1]);
});
count.set(1);
count.set(2);import { graph, timer } from "@graphrefly/ts";
const g = graph({ name: "clock" });
const tick = g.initNode(timer(1000), [], { name: "tick" });
tick.subscribe((msg) => {
if (msg[0] === "DATA") console.log("tick", msg[1]);
});import { describeToMermaid, graph } from "@graphrefly/ts";
const g = graph({ name: "flow" });
const input = g.state("hello", { name: "input" });
g.derived([input], (value) => value.toUpperCase(), { name: "upper" });
const topology = g.topology();
const snapshot = g.describe();
const mermaid = describeToMermaid(snapshot);import { defaultRestoreRegistry, graph, restoreGraph } from "@graphrefly/ts";
const g = graph({ name: "counter" });
const count = g.state(1, { name: "count", restore: { ref: "state" } });
count.set(2);
const checkpoint = g.checkpoint();
const restored = restoreGraph(checkpoint, { registry: defaultRestoreRegistry });| Path | Contents |
|---|---|
packages/ts/ |
The published @graphrefly/ts package. |
packages/ts/src/ |
TypeScript source for core, graph, operators, storage, adapters, and solutions. |
examples/ |
Runnable clean-slate examples that consume @graphrefly/ts. |
demos/ |
Current demo surfaces. Retired demos live under archive/. |
archive/ |
Historical code and retired examples kept out of active workspace ownership. |
website/ |
Astro/Starlight documentation site. |
The language-neutral protocol, decisions, conformance scenarios, and formal
model live in the sibling graphrefly authority repository. Sibling runtime
implementations are self-contained packages; cross-language compatibility is
behavioral conformance, not symbol-set parity.
pnpm install
pnpm test
pnpm run lint
pnpm run build
pnpm run docs:buildUseful package-local commands:
pnpm --filter @graphrefly/ts test
pnpm --filter @graphrefly/ts build
pnpm --filter @graphrefly/ts pack --pack-destination /tmp@graphrefly/ts is pre-1.0. The project intentionally does not preserve
backward compatibility with the retired @graphrefly/graphrefly or
@graphrefly/pure-ts APIs. Use current subpaths and examples as the migration
target.