Everything the extraction needed from core that ctx did not already offer. Additions only, so minor. ctx.activity.log, because an admin action a module performs has to land in core's one audit log or the trail has a hole exactly where a module operates the game -- a module keeping its own log would be a second place to look, which in practice means a place nobody looks. Write-only; reading the log is the admin panel's job and it spans every actor. ctx.users.getById, one function for one caller: the admin.users.detail slot router needs the user its prefix names. ctx.site.baseUrl, because a module has to build absolute links and §2.7 forbids it reading core's APP_BASE_URL -- a getter, not a captured string, so it cannot go stale against the env. ctx.middleware.rateLimit is core's makeLimiter, plus accountChangeLimiter handed over whole. The split is deliberate: a module states its own window and cap because it knows what its endpoints cost, and takes the plumbing from core so there is one express-rate-limit in the process and one place a breach is logged. accountChangeLimiter is shared policy -- core's /auth/me and /player/account sit behind the same counter -- so a module's account-change route has to land IN it rather than beside it. marketLimiter was UO policy living in core's file and leaves with the route it guards. registerPostHook is the fourth registry, and the last thing binding core to the module. Core's post controller called newsGump.syncPost directly: core's CMS naming a UO file. It now publishes what it already knows and a subscriber decides what to do with it. Not folded into registerAnnounceLeg, which fires on the same transition, because a leg is a one-shot DELIVERY with retry and classification while a post hook maintains idempotent STATE, runs on delete as well as save, and refreshes silently on an edit. Also fixes a real loader defect the extraction exposed: schema table names were matched against the RAW file, so a fragment whose header says "every CREATE TABLE carries IF NOT EXISTS" was rejected for a prefix violation on a table called `carries`. module-uo's fragment hit exactly that. Both scans now read split statements, which strip comments -- the same class of bug as a boundary check failing on its own documentation. Co-Authored-By: Claude <noreply@anthropic.com>
20 lines
1.2 KiB
JavaScript
20 lines
1.2 KiB
JavaScript
// The client's copy of MODULE_API_VERSION. It must equal the server's
|
|
// (server/src/modules/version.js) — the two halves version ONE contract
|
|
// (docs/website/MODULE_API.md §1.1), and a module checks whichever half it is
|
|
// talking to: `coreApi` against the server's at load time, `window.__rg.version`
|
|
// against the client's before it registers anything.
|
|
//
|
|
// Duplicated rather than fetched, and that is deliberate. The value has to be on
|
|
// `window.__rg` before the first module chunk evaluates, which is earlier than
|
|
// any network round trip could answer — a fetched version would mean either an
|
|
// await before render or a module reading `undefined`. The cost of the copy is
|
|
// that the two files can drift, so a test asserts they agree
|
|
// (client/test/moduleRegistry.test.js) rather than trusting a bump to remember
|
|
// both.
|
|
// 1.1.0 — the server's ctx gained activity.log, users.getById, site.baseUrl and
|
|
// the rate-limit factory (MODULE_API.md §2.3). Nothing on window.__rg changed,
|
|
// but the two halves state ONE version: a module declares a single coreApi range
|
|
// and is served one chunk, so a client that claimed 1.0.0 while the server
|
|
// answered 1.1.0 would be two answers to one question.
|
|
export const MODULE_API_VERSION = '1.1.0'
|