mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-06 00:14:54 +00:00
* feat(plugins): contribute settings screens and shared controls * fix(plugins): localize settings and verify shared UI consumers * test(composer): unmount draft test roots after each case * test(app): keep launch terminals alive until cleanup The fixed ten-second profile lifetime could expire before a busy CI browser attached or finished revisiting the composer. Keep the real process waiting for input until project teardown terminates it. * test(server): await the initial snapshot before a buffered ref event Watcher setup can read checkout facts before the initial refresh publishes a snapshot. Wait for publication before injecting the event so the test consistently exercises a second refresh.
76 lines
2.3 KiB
TypeScript
76 lines
2.3 KiB
TypeScript
import { pluginSettingsKey } from "./settings/use-settings";
|
|
import { useEffect } from "react";
|
|
import type { DaemonClient } from "@getpaseo/client/internal/daemon-client";
|
|
import { useHostFeature } from "@/runtime/host-features";
|
|
import { useHostRuntimeIsConnected } from "@/runtime/host-runtime";
|
|
import { pluginRegistry } from "./registry";
|
|
|
|
export function PluginCatalogSync({
|
|
serverId,
|
|
client,
|
|
}: {
|
|
serverId: string;
|
|
client: DaemonClient;
|
|
}) {
|
|
const connected = useHostRuntimeIsConnected(serverId);
|
|
const supported = useHostFeature(serverId, "plugins");
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
let refreshQueue = Promise.resolve();
|
|
if (!supported) {
|
|
pluginRegistry.removeHost(serverId);
|
|
return;
|
|
}
|
|
if (!connected) {
|
|
pluginRegistry.removeHost(serverId);
|
|
return;
|
|
}
|
|
const refresh = (replacePluginId?: string) => {
|
|
refreshQueue = refreshQueue.then(() =>
|
|
client
|
|
.getPluginCatalog()
|
|
.then((catalog) => {
|
|
if (!cancelled) {
|
|
pluginRegistry.installCatalog(serverId, catalog, {
|
|
replacePluginId,
|
|
client,
|
|
});
|
|
}
|
|
return undefined;
|
|
})
|
|
.catch((error) => {
|
|
if (!cancelled) {
|
|
console.warn(`[Plugins] Failed to load catalog for ${serverId}`, error);
|
|
}
|
|
return undefined;
|
|
}),
|
|
);
|
|
return refreshQueue;
|
|
};
|
|
void refresh();
|
|
const unsubscribe = client.on("status", (message) => {
|
|
if (message.payload.status === "plugin_settings_changed") {
|
|
const { pluginId, settingsId } = message.payload;
|
|
if (typeof settingsId === "string") {
|
|
const plugin = pluginRegistry
|
|
.getSnapshot()
|
|
.find((item) => item.serverId === serverId && item.id === pluginId);
|
|
void plugin?.queryClient.invalidateQueries({ queryKey: pluginSettingsKey(settingsId) });
|
|
}
|
|
}
|
|
if (message.payload.status === "plugin_catalog_changed") {
|
|
const pluginId = message.payload.pluginId;
|
|
if (typeof pluginId === "string") void refresh(pluginId);
|
|
}
|
|
});
|
|
return () => {
|
|
cancelled = true;
|
|
unsubscribe();
|
|
};
|
|
}, [client, connected, serverId, supported]);
|
|
|
|
useEffect(() => () => pluginRegistry.removeHost(serverId), [serverId]);
|
|
return null;
|
|
}
|