"use client"; const MANIFEST_URL = "/api/leptos-tiptap-runtime/manifest.json"; type RuntimeManifest = { bridgeRuntimePath: string | null; extensionModulePaths: string[]; generatedRootPath: string | null; entryScriptPath: string | null; wasmPath: string | null; }; type BridgeSuccess = { ok: true; value: T; }; type BridgeFailure = { ok: false; error: { kind: string; message: string; operation?: string; }; }; type BridgeResult = BridgeSuccess | BridgeFailure; type BridgeRuntimeModule = { init_bridge_runtime: () => void; create: ( request: unknown, onReady: (payload: { generation: number }) => void, onChange: () => void, onSelectionChange: (selection: Record) => void, onError: (error: { kind: string; message: string; operation?: string }) => void, ) => void; destroy: (id: string) => void; command: (request: unknown) => BridgeResult<{ kind: "empty" }>; document: (request: unknown) => BridgeResult<{ kind: "content"; content: { format: "json" | "html"; value: unknown } }>; }; export type LoadedLeptosTiptapRuntime = { manifest: RuntimeManifest; bridge: BridgeRuntimeModule; }; let runtimePromise: Promise | null = null; function toRuntimeAssetUrl(relativePath: string): string { return `/api/leptos-tiptap-runtime/${relativePath}`; } async function importRuntimeModule(relativePath: string): Promise { return import(/* webpackIgnore: true */ toRuntimeAssetUrl(relativePath)) as Promise; } function extractRegisterFunction(module: Record): (() => void) | null { for (const value of Object.values(module)) { if (typeof value === "function") { return value as () => void; } } return null; } async function fetchRuntimeManifest(): Promise { const response = await fetch(MANIFEST_URL, { cache: "no-store" }); if (!response.ok) { throw new Error(`读取 leptos-tiptap runtime manifest 失败(${response.status})`); } const manifest = (await response.json()) as RuntimeManifest; if (!manifest.bridgeRuntimePath) { throw new Error("runtime manifest 缺少 bridgeRuntimePath"); } return manifest; } async function loadRuntimeModules(): Promise { const manifest = await fetchRuntimeManifest(); const bridge = await importRuntimeModule(manifest.bridgeRuntimePath!); bridge.init_bridge_runtime(); for (const modulePath of manifest.extensionModulePaths) { const extensionModule = await importRuntimeModule>(modulePath); const register = extractRegisterFunction(extensionModule); register?.(); } return { manifest, bridge }; } export async function loadLeptosTiptapRuntime(): Promise { if (!runtimePromise) { runtimePromise = loadRuntimeModules().catch((error) => { runtimePromise = null; throw error; }); } return runtimePromise; }