Files
skills/docs/gaming/games/game-server/src/engine/session-node/session-node.md
2026-05-29 08:20:56 +01:00

4.2 KiB

SessionGraphNode

(no submodules)

Purpose

SessionGraphNode is the internal mutable graph node powering the hierarchical session tree at the heart of @suaveplan/game-server. Every node holds a stable id, a closed-vocabulary session type, a metadata bag, the mutable bidirectional parent/children links that form the tree, and the two timestamps that mark when the node was created and last touched.

The class is named SessionGraphNode deliberately — Wave A's public SessionNode interface (in core/types) is a read-only structural view of exactly this shape. exposes the read-only interface to consumers and uses the mutable class internally, so callers cannot accidentally mutate the tree by reaching into node.children.push(...) through the public manager surface.

Features

  • Implements Wave A's SessionNode interface structurally (the class is the canonical implementation; the interface is the read-only view).
  • Injectable Clock — no Date.now() calls; the entire tree is deterministic under FakeClock.
  • Bidirectional parent/children link maintenance via addChild / removeChild with idempotent attach/detach semantics.
  • Tree-walking helpers: getDepth, getDescendants (DFS pre-order), getAncestors, getRoot, isAncestorOf, isDescendantOf.
  • toJSON() returning a SerializedSessionNode shape for SessionStore persistence.

Usage: Basic

import { SessionGraphNode } from "../session-node/index.js";

const clock = () => 1700000000000;
const root = new SessionGraphNode(
    "venue1",
    "venue",
    { createdAt: 0, updatedAt: 0 },
    clock
);

const table = new SessionGraphNode(
    "table1",
    "table",
    { createdAt: 0, updatedAt: 0 },
    clock,
    root
);
root.addChild(table);
console.log(table.getDepth()); // 1
console.log(table.getRoot().id); // "venue1"

Usage: Advanced

import { SessionGraphNode } from "../session-node/index.js";

// Persistence round-trip: serialise, then restore with original timestamps.
const node = new SessionGraphNode("s1", "game", meta, clock);
const json = node.toJSON();
const restored = new SessionGraphNode(
    json.id,
    json.type,
    json.metadata,
    clock,
    null,
    { createdAt: json.createdAt, updatedAt: json.updatedAt }
);

// Removing a child clears the bidirectional link.
root.removeChild(table);
console.log(table.parent); // null
console.log(root.children.length); // 0

API Reference

Constructor

new SessionGraphNode(id, type, metadata, clock, parent?, timestamps?)

timestamps is optional — passed only when restoring from persistence to preserve the original createdAt / updatedAt stamps.

Methods

  • addChild(child) — attach a child; idempotent (re-adding is a no-op).
  • removeChild(child) — returns true if removed, false if not a child.
  • updateMetadata(patch) — shallow-merge patch; refreshes updatedAt.
  • getDepth() — 0 for a root, otherwise the distance to the root.
  • getDescendants() — depth-first pre-order array, excluding this.
  • getAncestors() — parent-to-root array.
  • getRoot() — the topmost ancestor (or this).
  • isAncestorOf(other) / isDescendantOf(other) — strict ancestry tests.
  • toJSON() — serialised plain object suitable for storage adapters.

Read-only properties

id, type, createdAt, updatedAt.

Mutable properties

parent (managed by addChild/removeChild), children, metadata.

Implementation Notes

The bidirectional parent/children invariant is held by addChild and removeChild. Direct mutation of node.children or node.parent is discouraged — callers should always go through these methods so the counterpart link stays in sync. The class is internal to the engine package and is not part of the public re-export surface; consumers should import SessionNode from core/types instead.

The constructor accepts an optional timestamps parameter solely for the persistence round-trip path — without it, a freshly restored node would have its createdAt set to the moment of restoration, losing the original creation time. With it, SessionStore.restore produces nodes that are byte-equivalent to the ones that were originally persisted.