Files
kandev/apps/web/lib/plugins/boot.ts
T
2026-08-08 02:12:44 +02:00

35 lines
1.4 KiB
TypeScript

/**
* Boots the plugin host from the app's boot payload
* (docs/plans/plugins/PLUGIN-API.md). Called once from the app
* bootstrap once the store + boot payload are both available.
*/
import type { StoreApi } from "zustand";
import type { AppState } from "@/lib/state/store";
import type { BootPayload } from "@/src/boot-payload";
import { buildHostApi } from "./host-api";
import { installPluginGlobal, loadPlugins } from "./host";
/** Store instances that have already had `loadPlugins` triggered — boot is a one-shot per store. */
const bootedStores = new WeakSet<StoreApi<AppState>>();
/**
* Installs `window.registerKandevPlugin` and loads every plugin in
* `bootPayload.plugins`, building each one's `PluginHostApi` from `storeApi`.
*
* No-op when the boot payload carries no plugins. Idempotent per `storeApi`
* instance — repeated calls (re-renders, StrictMode double-invoke, HMR
* remounts of the calling component) never re-install the global or re-import
* a bundle for a store that has already booted.
*/
export function bootPlugins(
bootPayload: Pick<BootPayload, "plugins">,
storeApi: StoreApi<AppState>,
): void {
if (!bootPayload.plugins || bootPayload.plugins.length === 0) return;
if (bootedStores.has(storeApi)) return;
bootedStores.add(storeApi);
installPluginGlobal();
void loadPlugins(bootPayload.plugins, (pluginId) => buildHostApi(pluginId, storeApi));
}