import { useApi } from '@/composables/useApi' export type UpdateState = | 'idle' | 'downloading' | 'verifying' | 'ready' | 'restarting' | 'succeeded' | 'failed' export interface UpdateNotes { version: string released_at: string items: string[] } export interface UpdateProgress { percent: number downloaded_bytes: number total_bytes: number } export type UpdateErrorKind = 'download' | 'verification' | 'rolled_back' | 'install' export type RestartKind = 'update' | 'restart' export interface UpdateStatus { current: string latest: string available: boolean release_url: string | null notes: UpdateNotes | null checked_at: string | null can_apply: boolean state: UpdateState progress: UpdateProgress | null error: UpdateErrorKind | null started_at: string | null finished_at: string | null container: boolean } export function useUpdate() { const { request } = useApi() function getUpdateStatus(): Promise { return request('/v1/system/update') } function checkForUpdate(): Promise { return request('/v1/system/update/check', { method: 'POST' }) } function startUpdateDownload(): Promise { return request('/v1/system/update/download', { method: 'POST' }) } function requestRestart(kind: RestartKind): Promise { return request('/v1/system/update/restart', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ kind }), }) } function pollUpdateStatus(): Promise { return request('/v1/system/update', { onUnauthorized: 'passthrough', onForbidden: 'passthrough', }) } async function isSiteUp(): Promise { try { const response = await fetch('/healthz', { cache: 'no-store' }) return response.status === 200 } catch { return false } } return { getUpdateStatus, checkForUpdate, startUpdateDownload, requestRestart, pollUpdateStatus, isSiteUp, } }