feat(bgm): add dialog role and interaction affordances
Add the dialog role and the interaction affordances the free-interaction layer depends on: Setup.interactions, Package.dialogs, and the Interaction, DialogAction, and Dialog types. Wire the dialog role through the zod schemas, package collection (with duplicate checking), and vite serialization, and update the tabletop serializedToPackage and test fixtures to carry dialogs.
This commit is contained in:
+16
-13
@@ -15,17 +15,17 @@
|
||||
* be mistaken for real installed packages. Editing a game definition
|
||||
* hot-reloads the app via `addWatchFile`.
|
||||
*/
|
||||
import * as path from 'node:path';
|
||||
import { normalizePath, type ModuleNode, type Plugin } from 'vite';
|
||||
import { collectPackages, loadDefs } from './collect.js';
|
||||
import { readDefFiles } from './parse.js';
|
||||
import type { Package, SerializedPackage } from './types.js';
|
||||
import * as path from "node:path";
|
||||
import { normalizePath, type ModuleNode, type Plugin } from "vite";
|
||||
import { collectPackages, loadDefs } from "./collect.js";
|
||||
import { readDefFiles } from "./parse.js";
|
||||
import type { Package, SerializedPackage } from "./types.js";
|
||||
|
||||
const VIRTUAL_PREFIX = '\0bgm:';
|
||||
const VIRTUAL_PREFIX = "\0bgm:";
|
||||
/** Public specifier for the module that lists every package. */
|
||||
const PACKAGES = 'virtual:bgm/packages';
|
||||
const PACKAGES = "virtual:bgm/packages";
|
||||
/** Public specifier prefix for a single package module. */
|
||||
const PACKAGE = 'virtual:bgm/package/';
|
||||
const PACKAGE = "virtual:bgm/package/";
|
||||
|
||||
export interface BgmOptions {
|
||||
/** Absolute path to the games root (e.g. `<repo>/games`). */
|
||||
@@ -39,23 +39,23 @@ export function bgm(options: BgmOptions): Plugin {
|
||||
const root = normalizePath(options.root);
|
||||
|
||||
const collect = (): Package[] => {
|
||||
const defMap = loadDefs('', root);
|
||||
const defMap = loadDefs("", root);
|
||||
return collectPackages(defMap, root);
|
||||
};
|
||||
|
||||
return {
|
||||
name: 'bgm',
|
||||
name: "bgm",
|
||||
buildStart() {
|
||||
// Watch every real definition source under the games root so edits
|
||||
// trigger a re-collect. `defMap.files` only holds the virtual code-block
|
||||
// files plus real non-markdown files; the markdown files themselves are
|
||||
// consumed for their code blocks and never appear there, so watch the
|
||||
// real files on disk too (markdown and anything else the loader reads).
|
||||
const defMap = loadDefs('', root);
|
||||
const defMap = loadDefs("", root);
|
||||
for (const name of defMap.files.keys()) {
|
||||
this.addWatchFile(path.join(root, name));
|
||||
}
|
||||
for (const file of readDefFiles(root, '')) {
|
||||
for (const file of readDefFiles(root, "")) {
|
||||
this.addWatchFile(file.source);
|
||||
}
|
||||
},
|
||||
@@ -68,7 +68,9 @@ export function bgm(options: BgmOptions): Plugin {
|
||||
// changes, so edits hot-reload instead of requiring a manual refresh.
|
||||
if (!ctx.file.startsWith(root)) return;
|
||||
const invalidated: ModuleNode[] = [];
|
||||
const mod = ctx.server.moduleGraph.getModuleById(VIRTUAL_PREFIX + PACKAGES);
|
||||
const mod = ctx.server.moduleGraph.getModuleById(
|
||||
VIRTUAL_PREFIX + PACKAGES,
|
||||
);
|
||||
if (mod) {
|
||||
ctx.server.moduleGraph.invalidateModule(mod);
|
||||
invalidated.push(mod);
|
||||
@@ -102,5 +104,6 @@ function toJson(pkg: Package): SerializedPackage {
|
||||
parts: Object.fromEntries(pkg.parts),
|
||||
surfaces: Object.fromEntries(pkg.surfaces),
|
||||
setups: Object.fromEntries(pkg.setups),
|
||||
dialogs: Object.fromEntries(pkg.dialogs),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user