diff options
| author | Adam Malczewski <[email protected]> | 2026-09-05 04:42:20 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-09-05 04:42:20 +0900 |
| commit | 5e5f02c67d0c165dd93f8277a3815d51a540d996 (patch) | |
| tree | 2b98579d25f3f16204feaf25ddac2746e4bbb934 /src/features/plugins/logic/view-model.ts | |
| parent | 2f282f1a5c784dff97af7c936ccb43ca2b63f03f (diff) | |
| download | dispatch-web-5e5f02c67d0c165dd93f8277a3815d51a540d996.tar.gz dispatch-web-5e5f02c67d0c165dd93f8277a3815d51a540d996.zip | |
feat(layout): plan 03 — frontend plugin ABI + handshake + load lifecycle
Diffstat (limited to 'src/features/plugins/logic/view-model.ts')
| -rw-r--r-- | src/features/plugins/logic/view-model.ts | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/src/features/plugins/logic/view-model.ts b/src/features/plugins/logic/view-model.ts index 20d7d68..5a66ffa 100644 --- a/src/features/plugins/logic/view-model.ts +++ b/src/features/plugins/logic/view-model.ts @@ -1,4 +1,5 @@ import type { PluginListResponse } from "@dispatch/transport-contract"; +import type { FrontendPluginState } from "../../../core/plugin-abi"; import { normalizeTier, type PluginNode, type PluginSection, TIER_ORDER } from "./types"; /** @@ -79,6 +80,34 @@ export function pluginNodes(response: PluginListResponse): readonly PluginNode[] } /** + * Merge the frontend-plugin (plan 03) per-plugin FE states into the node + * list — the manager rows' `frontendIssue` line. Pure input → output: + * - `incompatible` → the plan-mandated "incompatible frontend plugin" + * grammar (the backend apiVersion-mismatch wording, FE half); + * - `failed` → the activation error (the FE half failed; the backend half + * stays loaded). + * Loaded rows only — the FE states never apply to discovered/missing rows. + */ +export function withFrontendStates( + nodes: readonly PluginNode[], + states: ReadonlyMap<string, FrontendPluginState>, +): readonly PluginNode[] { + if (states.size === 0) return nodes; + return nodes.map((node) => { + if (node.section !== "loaded") return node; + const state = states.get(node.id); + if (state === undefined) return node; + const issue = + state.kind === "incompatible" + ? "incompatible frontend plugin" + : state.kind === "failed" + ? `frontend failed: ${state.error}` + : null; + return issue === null ? node : { ...node, frontendIssue: issue }; + }); +} + +/** * Cluster nodes for one manager table: tier groups in display order (Core → * Providers → Standard), each tier's rows sorted by id. Tiers with no rows * are omitted. Used by the loaded table's tier grouping (plan 07 §7.2). |
