Plugin SDK API Reference
Complete API reference for
@framework-m/plugin-sdkand@framework-m/vite-plugin.
@framework-m/plugin-sdk
Types
FrameworkMPlugin
The main plugin contract. Every plugin must export an object matching this interface.
interface FrameworkMPlugin {
/** Unique plugin name */
name: string;
/** Semantic version */
version: string;
/** Menu items to register in the sidebar */
menu?: MenuItem[];
/** Route definitions for lazy-loaded pages */
routes?: RouteDefinition[];
/** Service factories for dependency injection */
services?: Record<string, ServiceFactory>;
}
MenuItem
Navigation items displayed in the sidebar.
interface MenuItem {
/** Unique identifier (e.g., "wms.dashboard") */
name: string;
/** Display label */
label: string;
/** Navigation route path */
route?: string;
/** Icon identifier */
icon?: string;
/** Top-level module group (e.g., "WMS") */
module?: string;
/** Category within module (e.g., "Operations") */
category?: string;
/** Sort order (lower numbers appear first) */
order?: number;
/** Nested children (auto-populated by registry) */
children?: MenuItem[];
}
RouteDefinition
Route configuration for plugin pages.
interface RouteDefinition {
/** URL path (e.g., "/wms/dashboard") */
path: string;
/** Component or lazy loader */
element: React.ComponentType | (() => Promise<{ default: React.ComponentType }>);
}
ServiceFactory
Factory function for dependency injection services.
type ServiceFactory<T = unknown> = () => T | Promise<T>;
Classes
PluginRegistry
Central registry for managing plugins, menus, and routes.
class PluginRegistry {
/** Register a plugin. Validates and stores plugin data. */
register(plugin: FrameworkMPlugin): Promise<void>;
/** Get a registered plugin by name. Returns undefined if not found. */
getPlugin(name: string): FrameworkMPlugin | undefined;
/** Get all registered plugins. */
getPlugins(): FrameworkMPlugin[];
/** Get merged menu tree from all plugins. Organized by module → category → items. */
getMenu(): MenuItem[];
/** Get all routes from all plugins, flattened. */
getRoutes(): RouteDefinition[];
/** Access the service container. */
getServiceContainer(): ServiceContainer;
}
ServiceContainer
Lazy singleton dependency injection container.
class ServiceContainer {
/** Register a service factory. */
register<T>(name: string, factory: ServiceFactory<T>): void;
/** Get a service instance. Factory called once (lazy singleton). */
get<T>(name: string): T | Promise<T>;
/** Check if a service is registered. */
has(name: string): boolean;
/** Get all registered service names. */
getAll(): string[];
}
React Context
PluginRegistryProvider
React context provider that makes the registry available to hooks.
import { PluginRegistryProvider, PluginRegistry } from "@framework-m/plugin-sdk";
const registry = new PluginRegistry();
await registry.register(myPlugin);
<PluginRegistryProvider registry={registry}>
<App />
</PluginRegistryProvider>
Hooks
usePluginMenu(): MenuItem[]
Returns the merged menu tree from all registered plugins.
import { usePluginMenu } from "@framework-m/plugin-sdk";
function Sidebar() {
const menu = usePluginMenu();
// menu: MenuItem[] — tree of module → category → items
return menu.map(module => <MenuGroup key={module.name} {...module} />);
}
Throws: Error if used outside PluginRegistryProvider.
usePlugin(name: string): FrameworkMPlugin | undefined
Returns a specific registered plugin by name.
import { usePlugin } from "@framework-m/plugin-sdk";
function PluginInfo({ name }: { name: string }) {
const plugin = usePlugin(name);
if (!plugin) return <span>Plugin not found</span>;
return <span>{plugin.name} v{plugin.version}</span>;
}
Throws: Error if used outside PluginRegistryProvider.
useService<T>(name: string): { service: T | null; loading: boolean; error: Error | null }
Retrieves a service from the DI container with loading/error states.
import { useService } from "@framework-m/plugin-sdk";
function StockLevel() {
const { service, loading, error } = useService<InventoryService>("inventoryService");
if (loading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;
return <div>{service.getStockLevel()}</div>;
}
Throws: Error if used outside PluginRegistryProvider.
@framework-m/vite-plugin
frameworkMPlugin(options?): VitePlugin
Vite plugin that auto-discovers workspace plugins at build time.
import { frameworkMPlugin } from "@framework-m/vite-plugin";
export default defineConfig({
plugins: [react(), frameworkMPlugin()],
});
What it does:
- Build start: Scans workspace for
package.jsonfiles with"framework-m"metadata - Virtual module: Generates
virtual:framework-m-pluginswith import/export statements - HMR: Watches plugin config files for hot reload during development
Virtual module output (auto-generated):
// virtual:framework-m-plugins
import plugin_0 from "@wms/frontend/src/plugin.config.ts";
import plugin_1 from "@personnel/frontend/src/plugin.config.ts";
export default [plugin_0, plugin_1];
scanWorkspacePlugins(root?): Promise<PluginInfo[]>
Scans the workspace for packages with "framework-m" metadata.
import { scanWorkspacePlugins } from "@framework-m/vite-plugin";
const plugins = await scanWorkspacePlugins("/path/to/workspace");
// [{ name: "@wms/frontend", configPath: "./src/plugin.config.ts" }, ...]
generateVirtualModule(plugins): string
Generates the virtual module source code for discovered plugins.
import { generateVirtualModule } from "@framework-m/vite-plugin";
const code = generateVirtualModule(plugins);
// "import plugin_0 from '...'; export default [plugin_0];"