Hypergraph is Mercury's state kernel: the package @fiberfx/hypergraph, version 4.0.0, with no dependencies. A model is a graph of units, and Hypergraph runs it.
What Hypergraph is
Hypergraph is a scheduler and graph executor. It runs a model's wiring to quiescence, glitch-free and batched, with fork scopes, effects and one observation surface. Three things set it apart:
- Identity belongs to the compiler. Each unit has a stable identity, its sid, and a shape beside it. The compiler gives the sid, so a store can be found again across an edit, a server render or another runtime. Until the compiler emits shapes too, the kernel reads each store's shape from its initial value.
- The wiring is data. A model's units and edges are a graph the kernel loads, so a browser, a server and a test can all run one description of it.
- The semantics are vectors. What the kernel must do is stated as conformance vectors: 467 of them, in 19 families. Every runtime that holds a scope runs the same files, and a count against them is the claim.
The names
- Units take the names of their kinds:
store,eventandeffect. An effect takes its handler directly. - Wiring:
sampleis the one composition primitive.combinebatches its sources through a barrier.split,attach,mergeandrestorecomplete it, withon,reset,map,filter,filterMapandprependon units. - Scopes:
forkmakes an isolated scope,allSettledsteps it, andscopeBindbinds a function to it.snapshotreturns a frame with each value's shape,applybrings a scope to a frame,diffnames what changed between two frames, anddisposeends a scope. - Watching:
watch(unit, fn, {scope})is owned by its generation. When a model's graph is swapped, the old generation's watchers end with it. - Kinds:
kindOfanswersstore,event,effect,scopeor nothing.
import { event, store } from "@fiberfx/hypergraph";
const increment = event<number>();
export const $count = store(0, { name: "$count" }).on(increment, (count, by) => count + by);
Subpaths
@fiberfx/hypergraph: the units, the wiring, the scope's frames and the types.@fiberfx/hypergraph/node:nodeCarrier, which carries a scope across anawaiton a JavaScript server. It is its own entry, so code for the browser never imports a server's modules.@fiberfx/hypergraph/inspect:inspectanddescribe, and the typesObservation,Declaration,KindandResetReason.
Two more subpaths are planned and not exported yet: /hyperscript, the bindings for Mercury Hyperscript (useUnit, Provider), and /hmr, hot replacement.
How an edit behaves under mx dev
Once mx dev delivers the swap, a saved edit to a model swaps its graph instead of reloading the page. An edit that changes only the bodies of functions is swapped in place, so the scope, its values and any effect in flight stay as they are. Any other edit loads a new generation of the graph, carries over every store whose sid and shape both match, and then retires the old generation with its watchers.
Every store that does not carry over is named, with a reason:
- removed: no store in the new graph claims its sid;
- shape changed: its sid is there with another shape, and both shapes are named;
- renamed: a hint only, never applied, when exactly one removed store and one new store share a name;
- positional: its key came from its position in the file, which is no evidence of the same store once the file changed.
A store that only the new graph declares is new: it starts from its initial value and nothing was lost, so it is reported as information, not as a reset.
What is shipped
The kernel, its API and the swap are built inside @fiberfx/hypergraph. Version 4.0.0 is not published to a registry yet. mx dev does not deliver the swap yet: that is the next step, and until then an edit to a model reloads the page.