Initial boilerplate scaffold for continuum-app

This commit is contained in:
2026-08-28 16:21:23 +00:00
commit 4cb2e82a92
25 changed files with 810 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
import { defineStore } from "pinia";
export interface PrinterTelemetry {
printerId: string;
farmId: string;
state: "idle" | "printing" | "paused" | "error" | "offline";
nozzleTempC: number;
bedTempC: number;
progressPct: number;
updatedAt: string;
}
interface TelemetryState {
socket: WebSocket | null;
connected: boolean;
printers: Record<string, PrinterTelemetry>;
reconnectAttempt: number;
}
export const useTelemetryStore = defineStore("telemetry", {
state: (): TelemetryState => ({
socket: null,
connected: false,
printers: {},
reconnectAttempt: 0,
}),
getters: {
printerList: (state) => Object.values(state.printers),
},
actions: {
connect() {
if (this.socket) return;
const config = useRuntimeConfig();
const client = useSupabaseClient();
client.auth.getSession().then(({ data }) => {
const token = data.session?.access_token ?? "";
const url = `${config.public.wsBase}/ws/telemetry?token=${encodeURIComponent(token)}`;
this.open(url);
});
},
open(url: string) {
const socket = new WebSocket(url);
socket.onopen = () => {
this.connected = true;
this.reconnectAttempt = 0;
};
socket.onmessage = (event) => {
try {
const payload = JSON.parse(event.data) as { type: string; data: PrinterTelemetry };
if (payload.type === "printer.telemetry") {
this.printers[payload.data.printerId] = payload.data;
}
} catch {
// Ignore malformed frames rather than crashing the UI.
}
};
socket.onclose = () => {
this.connected = false;
this.socket = null;
const delay = Math.min(30_000, 1_000 * 2 ** this.reconnectAttempt);
this.reconnectAttempt += 1;
setTimeout(() => this.connect(), delay);
};
socket.onerror = () => {
socket.close();
};
this.socket = socket;
},
disconnect() {
this.socket?.close();
this.socket = null;
this.connected = false;
},
},
});