import { defineStore } from "pinia"; import { ref } from "vue"; import { api, type DaemonStatus, type NodeInfo, type SidecarConfig } from "@/lib/api"; import { Events, on } from "@/lib/events"; export type Phase = "idle" | "starting" | "ready" | "error"; export const useNodeStore = defineStore("node", () => { const phase = ref("idle"); const status = ref(null); const info = ref(null); const error = ref(null); let exitedUnlisten: (() => void) | null = null; let readyUnlisten: (() => void) | null = null; async function bootstrap() { if (!exitedUnlisten) { exitedUnlisten = await on(Events.SidecarExited, (e) => { error.value = `daemon exited (code ${e.payload})`; phase.value = "error"; status.value = { running: false, apiUrl: null, keyPath: null, configPath: null }; info.value = null; }); } if (!readyUnlisten) { readyUnlisten = await on(Events.SidecarReady, async () => { await refresh(); }); } const cur = await api.daemonStatus(); status.value = cur; if (cur.running) { phase.value = "ready"; try { info.value = await api.nodeInfo(); } catch (e) { error.value = String(e); } } } async function start(config?: SidecarConfig) { phase.value = "starting"; error.value = null; try { const s = await api.startDaemon(config); status.value = s; info.value = await api.nodeInfo(); phase.value = "ready"; } catch (e) { error.value = String(e); phase.value = "error"; throw e; } } async function stop() { try { const s = await api.stopDaemon(); status.value = s; info.value = null; phase.value = "idle"; } catch (e) { error.value = String(e); throw e; } } async function refresh() { status.value = await api.daemonStatus(); if (status.value.running) { info.value = await api.nodeInfo(); phase.value = "ready"; } else { info.value = null; phase.value = "idle"; } } function dispose() { exitedUnlisten?.(); readyUnlisten?.(); exitedUnlisten = null; readyUnlisten = null; } return { phase, status, info, error, bootstrap, start, stop, refresh, dispose, }; });