feat: harden plugin api for separate repos, signed updates and generic external login

This commit is contained in:
LukeGus committed 2026-09-29 18:11:59 -05:00
1 parent fb9c168b6b
commit 80944301dd
310 files changed
+6577 -4927

No files matched your search

+15 -2
View File
@@ -6,14 +6,27 @@
"scripts": {
"build": "termix-plugin build",
"test": "termix-plugin test",
"typecheck": "tsc -b ../../tsconfig.plugins.backend.json ../../tsconfig.plugins.frontend.json",
"typecheck": "tsc -p .",
"validate": "termix-plugin validate"
},
"dependencies": {
"cytoscape": "^3.34.3",
"lucide-react": "^1.33.0",
"react-cytoscapejs": "^2.0.0"
},
"devDependencies": {
"@termix/plugin-sdk": "*"
"@termix/plugin-sdk": "^1.0.0",
"@types/node": "^26.2.0",
"@types/react": "^19.2.18",
"@types/react-dom": "^19.2.4",
"better-sqlite3": "^13.0.3",
"jsdom": "^30.0.1",
"vitest": "^4.1.11"
},
"peerDependencies": {
"@termix/plugin-sdk": "^1.0.0",
"drizzle-orm": "^0.45.2",
"express": "^5.2.1",
"react": "^19.2.8"
}
}
@@ -31,6 +31,8 @@ import {
useTranslation,
usePluginApi,
useHosts,
useTabs,
getHostStatusColorScheme,
useHostActions,
type PluginHostRecord,
} from "@termix/plugin-sdk/frontend";
@@ -101,24 +103,6 @@ interface NetworkGraphCardProps {
type NetworkElement = NetworkTopologyNode | NetworkTopologyEdge;
type StatusColorScheme = "accent" | "status";
/** Reads the sidebar preferences cache directly, same as core's status dots do. */
function readStatusColorScheme(): StatusColorScheme {
try {
const raw = localStorage.getItem("hostSidebarPreferences");
if (!raw) return "accent";
const parsed = JSON.parse(raw) as {
display?: { statusColorScheme?: string };
};
return parsed?.display?.statusColorScheme === "status"
? "status"
: "accent";
} catch {
return "accent";
}
}
function resolveCssVar(varName: string, fallback: string): string {
const raw = getComputedStyle(document.documentElement)
.getPropertyValue(varName)
@@ -151,7 +135,7 @@ function buildNodeSvg(
): string {
const isOnline = status === "online";
const isOffline = status === "offline";
const useRealColors = readStatusColorScheme() === "status";
const useRealColors = getHostStatusColorScheme() === "status";
let statusColor: string;
if (isOnline) {
statusColor = useRealColors
@@ -583,10 +567,10 @@ export function NetworkGraphCard({
const hideMenu = () => setContextMenu((p) => ({ ...p, visible: false }));
const shellTabs = useTabs();
const fireOpen = (hostId: string, type?: string) => {
window.dispatchEvent(
new CustomEvent("termix:open-tab", { detail: { hostId, type } }),
);
const host = liveHosts.find((candidate) => String(candidate.id) === hostId);
if (host) shellTabs.connectHost(host, type);
};
const handleContextAction = (action: string) => {
@@ -38,7 +38,7 @@ describe("network-topology activate", () => {
const service = server.mock.services.get("network-topology.graph") as {
get: () => Promise<unknown>;
};
const result = await server.mock.ctx.asUser("user-1", () => service.get());
const result = await server.mock.actAs("user-1", () => service.get());
expect(result).toEqual({ nodes: [{ data: { id: "1" } }], edges: [] });
});
@@ -47,7 +47,7 @@ describe("network-topology activate", () => {
const service = server.mock.services.get("network-topology.graph") as {
get: () => Promise<unknown>;
};
const result = await server.mock.ctx.asUser("user-1", () => service.get());
const result = await server.mock.actAs("user-1", () => service.get());
expect(result).toBeNull();
});