// server/services/machineState.ts import { randomUUID } from "node:crypto"; import { db, schema } from "../db/client.js"; import type { UpdateSnapshot } from "@shared/types.js"; export interface AptDerivedState { status: string; aptStatus: string; aptUpdatesCount: number; aptRebootRequired: number; aptLastAnalyzeAt: string; } /** Dérive le bloc APT de l'état courant depuis un snapshot (fonction pure). */ export function deriveAptState(snapshot: UpdateSnapshot): AptDerivedState { return { status: snapshot.status, aptStatus: snapshot.status, aptUpdatesCount: snapshot.apt.count, aptRebootRequired: snapshot.apt.rebootRequired ? 1 : 0, aptLastAnalyzeAt: snapshot.checkedAt, }; } type MachineStateInsert = typeof schema.machineState.$inferInsert; /** Insère ou met à jour les champs fournis de machine_state pour une machine. */ export function upsertMachineState( machineId: string, fields: Partial> & { status: string }, ): void { const now = new Date().toISOString(); db.insert(schema.machineState) .values({ machineId, updatedAt: now, ...fields }) .onConflictDoUpdate({ target: schema.machineState.machineId, set: { ...fields, updatedAt: now }, }) .run(); } /** Ajoute une ligne à la timeline machine_events. */ export function recordEvent(input: { machineId: string; eventType: string; severity: "info" | "warning" | "error"; actorType?: string; snapshotId?: string; executionId?: string; message?: string; }): void { db.insert(schema.machineEvents).values({ id: randomUUID(), machineId: input.machineId, eventType: input.eventType, severity: input.severity, createdAt: new Date().toISOString(), actorType: input.actorType ?? "system", snapshotId: input.snapshotId, executionId: input.executionId, message: input.message, }).run(); }