temporal97
Integrations

Graphology

Run graph algorithms on your temporal graph by keeping a Graphology instance in sync with temporal97.

Graphology is a graph data structure for JavaScript/TypeScript that ships with a standard library of algorithms: BFS/DFS traversal, shortest paths, connected components, centrality, and more — none of which temporal97 provides.

The combination gives you the best of both: temporal97 owns the history and time travel, Graphology owns the algorithms.

Installation

npm install graphology graphology-traversal graphology-shortest-path graphology-components

Syncing with Delta

Write a helper that applies a Delta to a Graphology instance:

import Graph from 'graphology';
import { TemporalGraph, type Delta } from 'temporal97';

type NodeAttrs = { label: string };
type EdgeAttrs = { source: string; target: string; weight: number };

const temporal = new TemporalGraph<NodeAttrs, EdgeAttrs>();
const gly = new Graph({ type: 'directed' });

function syncDelta(delta: Delta) {
  // Removals first — dropNode also removes connected edges in Graphology
  for (const id of delta.nodes.removed) {
    if (gly.hasNode(id)) gly.dropNode(id);
  }
  for (const id of delta.edges.removed) {
    if (gly.hasEdge(id)) gly.dropEdge(id);
  }

  for (const id of delta.nodes.added) {
    gly.addNode(id, temporal.getNode(id));
  }
  for (const id of delta.edges.added) {
    const e = temporal.getEdge(id)!;
    gly.addEdgeWithKey(id, e.source, e.target, e);
  }

  for (const id of delta.nodes.updated) {
    gly.replaceNodeAttributes(id, temporal.getNode(id)!);
  }
  for (const id of delta.edges.updated) {
    gly.replaceEdgeAttributes(id, temporal.getEdge(id)!);
  }
}

Pass the Delta from any temporal97 operation straight into syncDelta:

syncDelta(temporal.append({
  snapshot: 0,
  mutations: [
    { kind: 'node', op: 'set', id: 'alice', value: { label: 'Alice' } },
    { kind: 'node', op: 'set', id: 'bob',   value: { label: 'Bob' } },
    { kind: 'edge', op: 'set', id: 'alice->bob', value: { source: 'alice', target: 'bob', weight: 1 } },
  ],
}));

syncDelta(temporal.append({
  snapshot: 1,
  mutations: [
    { kind: 'node', op: 'set', id: 'charlie', value: { label: 'Charlie' } },
    { kind: 'edge', op: 'set', id: 'bob->charlie', value: { source: 'bob', target: 'charlie', weight: 2 } },
  ],
}));

// Rewind — Graphology mirrors the rollback
syncDelta(temporal.rewind(0));

Running algorithms

Once Graphology is in sync, run any algorithm from its standard library against the current temporal state.

BFS traversal

import { bfsFromNode } from 'graphology-traversal/bfs';

bfsFromNode(gly, 'alice', (nodeId, attrs, depth) => {
  console.log(`${nodeId} at depth ${depth}:`, attrs);
});

Shortest path

import { bidirectional } from 'graphology-shortest-path/unweighted';

const path = bidirectional(gly, 'alice', 'charlie');
// ['alice', 'bob', 'charlie']

Connected components

import connectedComponents from 'graphology-components';

const components = connectedComponents(gly);
// [['alice', 'bob', 'charlie']]

Time travel + algorithms

Because syncDelta works for cursor movements too, you can run algorithms at any point in history:

// Save where you are, then jump to a past snapshot
const savedSnapshot = temporal.currentSnapshot;

syncDelta(temporal.seekTo(0));
const path = bidirectional(gly, 'alice', 'bob');
console.log('Path at snapshot 0:', path);

// Jump back to where you were
syncDelta(temporal.seekTo(savedSnapshot));

For read-only lookups that don't need Graphology, use temporal97's historical queries instead — they don't move the cursor at all.

On this page