4.3 KiB
4.3 KiB
bgm Loader — Status
WIP. What's built, what works, what's missing, and the known issues. Spec:
bgm-format.md.
What's built
packages/bgm — the loader core (new)
| File | Purpose |
|---|---|
src/types.ts |
Roles (Package, Part, Surface, Setup, Route, Stacking, …), SerializedPackage (the JSON the plugin emits), BgmError, DefFile, ParsedDef |
src/schemas.ts |
zod schemas + validate* for each role |
src/markdown.ts |
Virtual def files from markdown code blocks, via marked. file= naming + content-hash auto-naming (./<hash>.yaml); multiple blocks may share a file= name |
src/parse.ts |
yaml/json/toml → def objects (yaml, smol-toml); real-file walker (incl. .csv) |
src/variants.ts |
$variants expansion via typed-csv (typed-csv/csv-loader). Inline (newline) vs path; paths resolve against the virtual def map |
src/collect.ts |
loadDefs (real + virtual, virtual wins), collectPackages (package decl → include globs via picomatch → parts/surfaces/setups, type#id uniqueness, $variants on defs and route candidates) |
src/vite.ts |
The vite plugin (bgm()): resolves virtual:bgm/packages (all packages) and virtual:bgm/package/<id> (one package) imports to export default <json>, watches source files for reload. Serializes the package's Maps to objects (SerializedPackage); throws on unknown packages; re-collects per load (no stale cache). |
src/*.test.ts |
23 tests, all passing — markdown extractor, typed-csv parsing (incl. the spec's empty-array + crop tuple cases), full harbor collection, plugin unit tests (resolve/load/shape/watch), and a real vite build integration test covering two packages |
Deps: marked, typed-csv, yaml, smol-toml, picomatch, zod, vite, @types/picomatch.
games/harbor/harbor.md — example game (new)
Exercises the format end-to-end: package decl, two file=parts/tokens.yaml blocks, a surface with candidates: $variants against a virtual csv block, and a setup. Same content duplicated as the vitest fixture under packages/bgm/src/__fixtures__/harbor/.
apps/web — consumer (new)
vite.config.ts— wired withbgm({ root: <repo>/games }), importing the plugin from@tts/bgm.src/vite-env.d.ts— ambientdeclare module 'virtual:bgm/packages'(all packages) and'virtual:bgm/package/*'(one package).src/pages/BgmPage.tsx— list page: importsvirtual:bgm/packagesand shows every discovered package. Routed at/bgm.src/pages/BgmPackagePage.tsx— detail page: looks up a package by id frombgmand renders its parts/surfaces/setups. Routed at/bgm/:id.
The vite plugin itself lives in packages/bgm/src/vite.ts (exported from @tts/bgm), not in the web app — so the loader's plugin is tested in isolation from the web project.
Works
pnpm --filter @tts/bgm buildandtypecheckpass.- Root
pnpm test: 177 pass. pnpm --filter @tts/web buildsucceeds; config warnings fixed.src/vite.test.tsruns a realvite buildagainst a self-contained fixture (src/__fixtures__/vite-build/) and asserts the bundled output contains the package data — the plugin is proven end-to-end without touching the web app.
Known issues
Plugin emits empty maps— fixed:loadserializesMaps viaObject.fromEntries.Plugin— fixed: throws instead.loadusesthis.errorHMR cache not invalidated— fixed: dropped the closure cache; re-collects perload.— removed.tinyglobbyleftover depPackage-level test script finds no files— addedpackages/bgm/vitest.config.ts.
Not yet done
No consumer yet—apps/web/src/pages/BgmPage.tsxlists packages fromvirtual:bgm/packages;BgmPackagePage.tsxshows one at/bgm/:id.$variantsURL paths — spec mentions file/URL; URLs deferred.- zod
SerializedPackageshape for the emitted JSON — the plugin emitsSerializedPackageobjects; a zod schema for the emitted module would give runtime validation beyond the ambientdeclare module. setupvalue expansion —typewithoutid→ all parts of that type is documented but not implemented in the loader (it's a game-state init concern; noted as future).- Docs for the loader itself (this file is the start).