Kaysser Kayyali 8aedb06dcd tests: PLAN.md for v0.2.0 (envelope, subscribers, lifecycle, perf)
Adds tests/PLAN.md — the test plan that implements HOOK_CONTRACT.md
section 14. Defines what we test (sections A-G: envelope shape,
subscriber API, error containment, lifecycle, anti-corruption,
performance budget, system adapter loading), what we don't test
(consumer domain logic, Foundry's correctness, system-specific
derived events, older Foundry versions), and the definition of
done (100% coverage of 'what we test', smoke <2s, Foundry <30s,
perf budget <0.1ms median per fire).

The v0.1.0 verify-hooks-lib.mjs (20 assertions) covers the wrong
shape — it's slated for archive when v0.2.0 test files ship.
Listed in 'future turns' as a git mv into tests/archive/v0.1.0/.

Push: Gitea only.
2026-06-20 02:12:25 -04:00

Hax's Tools — Hooks Lib

Foundry VTT module (id: hax-hooks-lib) that turns Foundry's hook soup (dnd5e, combat, token updates) into a clean, normalized event stream. Library-only — no UI, no settings, no chat output. Designed to be consumed by any module that wants Foundry events in a stable shape.

Part of the Hax's Tools umbrella. Consumers today:

  • battle-focus — encounter + journal + summary
  • Its-Achievable — achievements, rewards, wall, HUD

Status

v0.1.0 — initial extraction from battle-focus v0.5.0-alpha.12. The scripts/events/ and scripts/systems/ content is a verbatim copy of the battle-focus versions, with module-id log strings retagged from battle-focus to hax-hooks-lib.

Stage 1 of the split plan: ship this repo without changing battle-focus's behavior. Stage 2 will flip battle-focus to import from here and delete the local copy.

Event Shape

Every event is a plain object with at minimum:

{
  kind: "combat-start",  // stable string id
  ts:   1719000000000,   // epoch ms when handler fired
  // ... kind-specific fields
}

Handler functions in scripts/events/core/ and scripts/events/dnd5e/ return the event object (or null to drop it). The registry calls the consumer's onEvent(event) callback for any non-null return.

Event catalog

Core (system-agnostic, always loaded):

  • combat-start, combat-end, combat-inactive, combat-turn, combat-round
  • combatant-add, combatant-remove
  • pre-update-actor, update-actor, pre-update-token, update-token, pre-update-item, update-item
  • create-active-effect, delete-active-effect
  • token-avatar-change

D&D 5e (loaded when game.system.id === "dnd5e"):

  • attack-roll, damage-roll

Public API (on game.modules.get("hax-hooks-lib").api)

  • loadSystems({ currentSystemId, systemVersion }) → array of active system adapters ([{ id, label, match, events }]). The core adapter is always present; other adapters are filtered by match().
  • registerAllEvents(systems, onEvent) → registers every event from every active system via Hooks.on(...). The onEvent callback is invoked once per non-null handler return, awaited. Returns the array of registered event defs (for introspection).

Consumers should call registerAllEvents from their ready hook and provide their own onEvent(event) to drive their downstream pipeline.

Dependencies

None. This is a leaf library.

Architecture notes

  • Single chokepoint: registerEvent() is the only place that wraps a Foundry hook into the normalized shape. Adding a new event type = add one file + one line in the relevant system adapter.
  • System loader: scripts/systems/loader.js filters system adapters by game.system.id. Adding a new system = add one file in scripts/systems/ + one import line.
  • Context helper: $ctx() returns the active event's metadata for the duration of the handler call. Use it inside a handler to log with the event id, or to read which system emitted it.

Tests

tests/verify-hooks-lib.mjs is a minimal smoke test that exercises the registry + a single event without booting Foundry. Foundry-load verification happens in battle-focus's E2E suite (the test driver registers hooks-lib's events through battle-focus's consumer path and confirms the event stream flows end-to-end).

npm test

Maintained by Kaysser Taylor + Hermes

Description
Hax's Tools � Foundry VTT hook normalization library (battle-focus slice 1)
Readme 464 KiB
Languages
JavaScript 100%