59 lines
1.7 KiB
TypeScript
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,
|
|
};
|