/** * API-Anbindung der Sicherungsauftraege (SYNCOVA_API.md ยง9). * * Das Modul kennt nur den Vertrag nach aussen. Die Gestalt der Anfrage folgt * dem Backend und nicht der Oberflaeche: Der Wizard fuehrt seinen eigenen * Entwurf und uebersetzt ihn erst beim Anlegen. Andernfalls muesste jede * Aenderung an der API sofort die Maske umbauen. */ import { requestApi } from '../../api/client'; /** Art eines Zeitplans (packages/scheduler). */ export type ScheduleType = | 'manual' | 'interval' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'cron'; /** Dringlichkeit eines Auftrags. */ export type JobPriority = 'critical' | 'high' | 'normal' | 'low'; /** Art einer Sicherungsquelle. */ export type SourceType = | 'filesystem' | 'proxmox_vm' | 'proxmox_container' | 'windows_system' | 'linux_system'; /** Zeitplan im Anfrage- und Antwortformat der API. */ export interface ScheduleDescriptor { /** Art des Zeitplans. */ type: ScheduleType; /** Abstand in Sekunden bei type=interval. */ interval_seconds?: number; /** Uhrzeit im Format HH:MM. */ time?: string; /** Wochentage, 0 = Sonntag. */ weekdays?: number[]; /** Tage des Monats; -1 bedeutet Monatsletzter. */ month_days?: number[]; /** Cron-Ausdruck bei type=cron. */ cron_expression?: string; /** Zeitzone der Uhrzeiten. */ time_zone?: string; } /** Quelle im Anfrage- und Antwortformat der API. */ export interface SourceDescriptor { /** Art der Quelle. */ type: SourceType; /** Kennung innerhalb ihrer Art, etwa ein Pfad. */ id: string; /** Sprechende Bezeichnung. */ name?: string; /** Einzuschliessende Muster. */ include_patterns?: string[]; /** Auszuschliessende Muster. */ exclude_patterns?: string[]; } /** Rumpf beim Anlegen eines Auftrags. */ export interface CreateJobRequest { /** Eindeutige Bezeichnung. */ name: string; /** Erlaeuterung des Zwecks. */ description?: string; /** Dringlichkeit. */ priority?: JobPriority; /** Zeitplan. */ schedule: ScheduleDescriptor; /** Zu sichernde Quellen. */ sources: SourceDescriptor[]; /** Ziel-Repository. */ repository_id: string; /** Zulaessiger Datenverlust in Sekunden. */ rpo_seconds?: number; /** Zulaessige Wiederherstellungsdauer in Sekunden. */ rto_seconds?: number; /** Bandbreitengrenze in Byte je Sekunde. */ bandwidth_limit_bps?: number; } /** Auftrag in der Antwort der API. */ export interface BackupJob { /** Oeffentlicher Bezeichner. */ id: string; /** Bezeichnung. */ name: string; /** Erlaeuterung. */ description?: string; /** Zustand. */ status: string; /** Dringlichkeit. */ priority: JobPriority; /** Zeitplan. */ schedule: ScheduleDescriptor; /** Erklaerung des Zeitplans in einem Satz. */ schedule_description: string; /** Quellen. */ sources: SourceDescriptor[]; /** Ziel-Repository. */ repository_id: string; /** Naechster Zeitpunkt in UTC. */ next_run_at?: string; /** Beginn des letzten Laufs in UTC. */ last_run_at?: string; /** Ausgang des letzten Laufs. */ last_outcome?: string; /** Bandbreitengrenze in Byte je Sekunde. */ bandwidth_limit_bps?: number; } /** Sicherungsziel in der Antwort der API. */ export interface BackupRepository { /** Oeffentlicher Bezeichner. */ id: string; /** Sprechende Bezeichnung. */ name: string; /** Ablageart. */ repository_type: string; /** Pfad oder Adresse der Ablage. */ location: string; /** Betriebszustand. */ status: string; /** * Meldet, ob dieses Ziel Sicherungen annimmt. * * Die Auskunft kommt vom Server. Die Oberflaeche muesste sonst wissen, welche * Zustaende schreibend sind - eine Regel, die dort nicht hingehoert. */ accepts_backups: boolean; /** Meldet den gehaerteten Modus. */ hardened: boolean; } /** * Laedt die bekannten Sicherungsziele. * * Das Abbruchsignal wird nur gesetzt, wenn es vorliegt: Bei * exactOptionalPropertyTypes ist ein ausdrueckliches undefined etwas anderes * als ein fehlendes Feld. */ export async function listRepositories(abortSignal?: AbortSignal): Promise { return requestApi('/repositories', abortSignal ? { signal: abortSignal } : {}); } /** Laedt die vorhandenen Sicherungsauftraege. */ export async function listJobs(abortSignal?: AbortSignal): Promise { return requestApi('/jobs?page_size=100', abortSignal ? { signal: abortSignal } : {}); } /** Legt einen Sicherungsauftrag an. */ export async function createJob(jobRequest: CreateJobRequest): Promise { return requestApi('/jobs', { method: 'POST', body: jobRequest }); }