Files
hooks-lib/scripts/main.js
Kaysser Kayyali d038eb8c67 v0.3.0: rename module id hax-hooks-lib -> foundry-hooks-lib
User callout: 'Hax' is Kaysser's nickname. The module id should
not use it. Rename the Foundry module id from 'hax-hooks-lib' to
'foundry-hooks-lib'. Gitea repo name stays as 'hooks-lib' (kept
for the user-facing URL); the Gitea manifest URL is unchanged.

**Scope of rename:**
- module.json: id, title, version (0.2.0 -> 0.3.0), download URL
- package.json: name
- README.md, HOOK_CONTRACT.md, LICENSE: branding text
- All 6 production JS files: MODULE_ID constant + comments
- 4 active test files: console.log strings + test descriptions
- Rename of release zips in git: hooks-lib-X.Y.Z.zip ->
  foundry-hooks-lib-X.Y.Z.zip (preserves the v0.1.0 and v0.2.0
  zips as historical artifacts; the v0.3.0 zip is the new
  release artifact)
- .gitignore: glob + un-ignore lines updated to match

**Out of scope (deliberate):**
- Gitea repo name 'kaykayyali/hooks-lib' stays. Per the user's
  direction, only the module id is renamed; the Gitea URL path
  is preserved for the existing 'url', 'manifest', 'download'
  fields.
- scripts/_archive/v0.1.0/*: historical v0.1.0 code is left
  as-is. Those files tested 'hax-hooks-lib v0.1.0'; rewriting
  the history would be misleading.
- tests/_archive_v0.1.0_*.mjs: same reason, left untouched.
- .hermes/plans/* session-historian plans that reference
  'Hax's Tools split': session artifact, not a release asset.

**Verification:** 554/554 smoke assertions pass, 6/6 perf
assertions pass, median 0.0004ms/fire (well under 0.1ms
budget). No logic change; rename is string-only.

**Consumer action required:** battle-focus and its-achievable
both declare 'relationships.requires' pointing to
'hax-hooks-lib'. The next commits on those repos will update
their relationships to 'foundry-hooks-lib' + bump their
versions. Foundry instances with v0.2.0 of the old id
installed will need to be reinstalled as v0.3.0 of the new
id.
2026-06-20 16:53:37 -04:00

102 lines
2.5 KiB
JavaScript

// foundry-hooks-lib — module entry point (v0.2.0).
//
// Generic Foundry hook facade per HOOK_CONTRACT.md. No domain
// interpretation. Subscribes to every Foundry hook in the registered
// set (§6), emits a uniform {ts, hook, args} envelope, dispatches
// to consumers via the subscribe primitives (§3). System-specific
// knowledge lives in separate adapter repos (§5).
//
// Public API (mod.api):
// VERSION
// REGISTERED_HOOKS
// subscribe(hookName, fn)
// subscribeMany(map)
// subscribeAll(fn)
// unsubscribeAll()
// registerSystemAdapter(manifest)
// listActiveAdapters()
// listInstalledRawHooks()
// isReady()
import {
install,
uninstall,
evaluateAdaptersAtReady,
listInstalledRawHooks,
} from "./internal/lifecycle.js";
import {
subscribe,
subscribeMany,
subscribeAll,
unsubscribeAll,
listSubscribedHooks,
} from "./internal/subscribers.js";
import {
registerSystemAdapter,
listActiveAdapters,
} from "./internal/adapter-registry.js";
import { REGISTERED_HOOKS } from "./internal/registered-hooks.js";
const MODULE_ID = "foundry-hooks-lib";
const MODULE_VERSION = "0.2.0";
function isClient() {
return typeof ui !== "undefined" && !!ui;
}
// Public API — re-exported on mod.api so consumers can use either
// direct imports or the mod.api façade.
export const VERSION = MODULE_VERSION;
export { REGISTERED_HOOKS };
export {
subscribe,
subscribeMany,
subscribeAll,
unsubscribeAll,
registerSystemAdapter,
listActiveAdapters,
};
function isReady() {
return isClient() && !!game.ready;
}
Hooks.once("init", () => {
const mod = game.modules.get(MODULE_ID);
mod.api = {
MODULE_ID,
version: MODULE_VERSION,
REGISTERED_HOOKS: [...REGISTERED_HOOKS],
isReady,
subscribe,
subscribeMany,
subscribeAll,
unsubscribeAll,
registerSystemAdapter,
listActiveAdapters,
listInstalledRawHooks,
};
// Install Foundry hook listeners — every raw hook name in the registry.
install();
console.log(
`[${MODULE_ID} v${MODULE_VERSION}] init: ${listInstalledRawHooks().length} ` +
`Foundry hook listeners registered`
);
});
Hooks.once("ready", () => {
if (!isClient()) return;
// Evaluate system adapters against the current world.
evaluateAdaptersAtReady();
console.log(
`[${MODULE_ID} v${MODULE_VERSION}] ready (client=${isClient()})`
);
});
// Cleanup on module disable.
Hooks.on("unregisterModule", (moduleId) => {
if (moduleId === MODULE_ID) {
uninstall();
console.log(`[${MODULE_ID}] unregisterModule: cleaned up`);
}
});