34 lines
2.2 KiB
TypeScript
34 lines
2.2 KiB
TypeScript
import type { ComponentType } from "react";
|
|
|
|
import type { PluginBridgeHostContext, PluginPageContract } from "../contracts/pluginBridge";
|
|
import type { PluginPageWorkspaceActions } from "../contracts/pluginPageHost";
|
|
|
|
export interface PluginPageBundleModule {
|
|
pluginPageBundle: { key: string; version: string; integritySha256: string };
|
|
renderPluginPage: (react: typeof import("react"), input: { page: PluginPageContract; context: PluginBridgeHostContext; workspace?: unknown; workspaceActions?: PluginPageWorkspaceActions; availability: PluginPageAvailability }) => ReturnType<typeof import("react").createElement>;
|
|
}
|
|
|
|
export type PluginPageAvailability = { available: boolean; reason?: string; features?: Array<{ key: string; available: boolean; reason?: string }> };
|
|
|
|
const pageBundles = import.meta.glob<PluginPageBundleModule>("../../plugins/examples/*/page-bundle/index.ts");
|
|
|
|
export async function loadPluginPageBundle(page: PluginPageContract): Promise<ComponentType<{ context: PluginBridgeHostContext; workspace?: unknown; workspaceActions?: PluginPageWorkspaceActions; availability: PluginPageAvailability }>> {
|
|
if (!page.bundleKey || !page.bundleVersion || !page.bundleIntegritySha256) throw new Error("插件没有声明受验证的页面 bundle。");
|
|
const match = Object.entries(pageBundles).find(([path]) => path.endsWith(`/${page.bundleKey}/page-bundle/index.ts`));
|
|
if (!match) throw new Error("已声明的插件页面 bundle 未安装。");
|
|
const module = await match[1]();
|
|
if (module.pluginPageBundle.key !== page.bundleKey || module.pluginPageBundle.version !== page.bundleVersion || module.pluginPageBundle.integritySha256 !== page.bundleIntegritySha256) throw new Error("插件页面 bundle 完整性或版本校验失败。");
|
|
return ({ context, workspace, workspaceActions, availability }) => module.renderPluginPage(awaitReact(), { page, context, workspace, workspaceActions, availability });
|
|
}
|
|
|
|
function awaitReact(): typeof import("react") {
|
|
// React is supplied by the authenticated platform shell; bundles never own a second runtime.
|
|
return requireReact();
|
|
}
|
|
|
|
function requireReact(): typeof import("react") {
|
|
return globalThis.__PLUGIN_PAGE_REACT__;
|
|
}
|
|
|
|
declare global { var __PLUGIN_PAGE_REACT__: typeof import("react"); }
|