rspace-online/shared/module.ts

61 lines
1.8 KiB
TypeScript

import { Hono } from "hono";
/**
* The contract every rSpace module must implement.
*
* A module is a self-contained feature area (books, pubs, cart, canvas, etc.)
* that exposes Hono routes and metadata. The shell mounts these routes under
* `/:space/{moduleId}` in unified mode. In standalone mode, the module's own
* `standalone.ts` mounts them at the root with a minimal shell.
*/
export interface RSpaceModule {
/** Short identifier used in URLs: 'books', 'pubs', 'cart', 'canvas', etc. */
id: string;
/** Human-readable name: 'rBooks', 'rPubs', 'rCart', etc. */
name: string;
/** Emoji or SVG string for the app switcher */
icon: string;
/** One-line description */
description: string;
/** Mountable Hono sub-app. Routes are relative to the mount point. */
routes: Hono;
/** Optional: standalone domain for this module (e.g. 'rbooks.online') */
standaloneDomain?: string;
/** Called when a new space is created (e.g. to initialize module-specific data) */
onSpaceCreate?: (spaceSlug: string) => Promise<void>;
/** Called when a space is deleted (e.g. to clean up module-specific data) */
onSpaceDelete?: (spaceSlug: string) => Promise<void>;
}
/** Registry of all loaded modules */
const modules = new Map<string, RSpaceModule>();
export function registerModule(mod: RSpaceModule): void {
modules.set(mod.id, mod);
}
export function getModule(id: string): RSpaceModule | undefined {
return modules.get(id);
}
export function getAllModules(): RSpaceModule[] {
return Array.from(modules.values());
}
/** Metadata exposed to the client for the app switcher */
export interface ModuleInfo {
id: string;
name: string;
icon: string;
description: string;
}
export function getModuleInfoList(): ModuleInfo[] {
return getAllModules().map((m) => ({
id: m.id,
name: m.name,
icon: m.icon,
description: m.description,
}));
}