THROWAWAY BRANCH — evidence for the Phase 1 contract, never merged. See
modules/uo/SPIKE.md and docs/website/MODULE_API.md Part 7.
The six public spawn-atlas routes now live in modules/uo/, reached only through
the ctx/register surface, with the client half loading as a prebuilt ESM chunk.
All three exit criteria met:
• zero internal-file imports from the module into core; the built chunk has
zero bare import specifiers and bundles no React
• routes.manifest.json AND routes.guards.json are byte-identical
• /uo/atlas renders from /modules/uo/entry.js under script-src 'self' with
zero CSP violation reports
729 core tests and 81 module tests pass. Verified end to end against the real
database: the schema fragment replays after core's, onBoot runs the atlas
refresh, and the six API URLs answer unchanged.
Two things the spike changed in the contract:
• ctx.express / ctx.validator. A module lives outside server/, so Node never
reaches server/node_modules and require('express') fails outright — the
server-side twin of the one-React rule, which §2.6 had only for the client.
• window.__rg.jsxRuntime, so a module can build with the automatic JSX
runtime its tooling already assumes rather than being forced to classic.
And it confirmed §6.1 empirically: regenerating the OpenAPI spec silently
deleted all 361 lines of the atlas paths with "Swagger-autogen: Success", while
the route manifest kept all six in the same run. That is exactly the
static-analysis-vs-runtime split the fragment merge exists to prevent.
Co-Authored-By: Claude <noreply@anthropic.com>
51 lines
2.5 KiB
Markdown
51 lines
2.5 KiB
Markdown
# module-uo — the Phase 1 spike
|
|
|
|
**This branch is evidence, not implementation.** `spike/module-atlas` is cut from `edge` and is
|
|
never merged. Phase 2 rebuilds the loader properly, with the `installed_modules` table, the full
|
|
state machine and the admin panel behind it; Phase 3 does the real extraction.
|
|
|
|
What it demonstrates, and the results, are written up in
|
|
[`docs/website/MODULE_API.md`](../../../docs/website/MODULE_API.md) Part 7. In one line: the six
|
|
public spawn-atlas routes now live in a module, at byte-identical URLs, with the client half loading
|
|
as a prebuilt ESM chunk under `script-src 'self'`.
|
|
|
|
## Reproducing it
|
|
|
|
```bash
|
|
# 1. build the module's client chunk (its CI would do this and ship the result)
|
|
cd modules/uo/client && npm install && npm run build # → dist/entry.js
|
|
|
|
# 2. build core's client
|
|
cd ../../../client && npm install && npm run build
|
|
|
|
# 3. run the server against the local MariaDB
|
|
cd ../server && npm start
|
|
```
|
|
|
|
Then:
|
|
|
|
- `/uo/atlas` and `/uo/atlas/lizardman` render from the module's chunk.
|
|
- `GET /api/v1/public/atlas/*` answers exactly as before — `npm run routes:manifest -- --check`
|
|
reports the surface unchanged.
|
|
- `npm test` in `server/` (core, 729) and `node --test` in `modules/uo/server/` (module, 81).
|
|
|
|
`dist/entry.js` is committed here **only** because this branch is the evidence for a design
|
|
decision and a reviewer should be able to inspect the built artifact without a toolchain. A real
|
|
module publishes it from CI into its release bundle and never commits it.
|
|
|
|
## What in here is not design
|
|
|
|
Three things are consequences of stopping at six routes, spelled out in MODULE_API.md §7.5:
|
|
|
|
1. **Core reaches into this module twice** — `server/src/router/v1/admin/shardAtlas.controller.js`
|
|
and `server/test/atlasController.test.js`. The five admin atlas routes sit inside the `/shard`
|
|
admin prefix core still owns, so they cannot move until the whole prefix does.
|
|
2. **`server/utils/visibility.js` is a copy** of core's `utils/shardVisibility.js`, which core still
|
|
needs for the shard routes not yet extracted. Two caches over one table, briefly.
|
|
3. **There is no `swagger-fragment.json`** — it needs core's merge helper on the other side, which
|
|
is Phase 2.
|
|
|
|
Also note the table names here are `shard_*`, not `uo_*`. That is deliberate and grandfathered by an
|
|
allowlist in the loader: renaming twenty-seven live tables is a data migration this workstream does
|
|
not do. Every module written after this one carries its id as a table prefix.
|