feat(bgm): add vite plugin and build integration test
Move the bgm vite plugin into the package so it can be tested in isolation from the web app. Serve each package as a JSON module, serializing its maps, and verify resolution through a real vite build against a self-contained fixture.
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Vite plugin: resolve `bgm/<package>` imports to the package's JSON.
|
||||
*
|
||||
* The loader reads a games root (markdown code blocks + real
|
||||
* yaml/json/toml/csv files), collects packages, and this plugin serves each
|
||||
* package as a module whose default export is the assembled JSON. Editing a
|
||||
* game definition hot-reloads the app via `addWatchFile`.
|
||||
*/
|
||||
import * as path from 'node:path';
|
||||
import type { Plugin } from 'vite';
|
||||
import { collectPackages, loadDefs } from './collect.js';
|
||||
import type { Package } from './types.js';
|
||||
|
||||
const VIRTUAL_PREFIX = '\0bgm:';
|
||||
|
||||
export interface BgmOptions {
|
||||
/** Absolute path to the games root (e.g. `<repo>/games`). */
|
||||
root: string;
|
||||
}
|
||||
|
||||
export function bgm(options: BgmOptions): Plugin {
|
||||
const root = options.root;
|
||||
|
||||
const collect = (): Package[] => {
|
||||
const defMap = loadDefs('', root);
|
||||
return collectPackages(defMap, root);
|
||||
};
|
||||
|
||||
return {
|
||||
name: 'bgm',
|
||||
buildStart() {
|
||||
// Watch every source file so edits trigger a reload/re-collect.
|
||||
const defMap = loadDefs('', root);
|
||||
for (const name of defMap.files.keys()) {
|
||||
this.addWatchFile(path.join(root, name));
|
||||
}
|
||||
},
|
||||
resolveId(id) {
|
||||
if (id.startsWith('bgm/')) return VIRTUAL_PREFIX + id;
|
||||
},
|
||||
load(id) {
|
||||
if (!id.startsWith(VIRTUAL_PREFIX)) return;
|
||||
const name = id.slice(VIRTUAL_PREFIX.length + 'bgm/'.length);
|
||||
const pkg = collect().find((p) => p.meta.id === name);
|
||||
if (!pkg) {
|
||||
throw new Error(`bgm package "${name}" not found`);
|
||||
}
|
||||
return `export default ${JSON.stringify(toJson(pkg))}`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize a `Package` for JSON emission. The parts/surfaces/setups are
|
||||
* `Map`s, which `JSON.stringify` would otherwise turn into `{}`.
|
||||
*/
|
||||
function toJson(pkg: Package): Record<string, unknown> {
|
||||
return {
|
||||
meta: pkg.meta,
|
||||
parts: Object.fromEntries(pkg.parts),
|
||||
surfaces: Object.fromEntries(pkg.surfaces),
|
||||
setups: Object.fromEntries(pkg.setups),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user