rspace-online/modules/canvas/mod.ts

59 lines
1.7 KiB
TypeScript

/**
* Canvas module — the collaborative infinite canvas.
*
* This is the original rSpace canvas restructured as an rSpace module.
* Routes are relative to the mount point (/:space/canvas in unified mode,
* / in standalone mode).
*/
import { Hono } from "hono";
import { resolve } from "node:path";
import { renderShell } from "../../server/shell";
import { getModuleInfoList } from "../../shared/module";
import type { RSpaceModule } from "../../shared/module";
const DIST_DIR = resolve(import.meta.dir, "../../dist");
const routes = new Hono();
// GET / — serve the canvas page wrapped in shell
routes.get("/", async (c) => {
const spaceSlug = c.req.param("space") || c.req.query("space") || "demo";
// Read the canvas page template from dist
const canvasFile = Bun.file(resolve(DIST_DIR, "canvas-module.html"));
let canvasBody = "";
if (await canvasFile.exists()) {
canvasBody = await canvasFile.text();
} else {
// Fallback: serve full canvas.html directly if module template not built yet
const fallbackFile = Bun.file(resolve(DIST_DIR, "canvas.html"));
if (await fallbackFile.exists()) {
return new Response(fallbackFile, {
headers: { "Content-Type": "text/html" },
});
}
canvasBody = `<div style="padding:2rem;text-align:center;color:#64748b;">Canvas loading...</div>`;
}
const html = renderShell({
title: `${spaceSlug} — Canvas | rSpace`,
moduleId: "canvas",
spaceSlug,
body: canvasBody,
modules: getModuleInfoList(),
theme: "light",
scripts: `<script type="module" src="/canvas-module.js"></script>`,
});
return c.html(html);
});
export const canvasModule: RSpaceModule = {
id: "canvas",
name: "Canvas",
icon: "🎨",
description: "Collaborative infinite canvas",
routes,
};