/** * Backup API client — database backup management. * * Features: * - List backups * - Create backup * - Restore backup * - Delete backup */ import { apiGet, apiPost, apiPut, apiDelete } from './client'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; // ─── Types ────────────────────────────────────────────────────────────────── export interface Backup { id: string; tenant_id: string; filename: string; size_bytes: number | null; status: 'pending' | 'completed' | 'failed'; error_message: string | null; created_by: string | null; created_at: string; completed_at: string | null; } export interface BackupListResponse { backups: Backup[]; total: number; } // ─── API Functions ────────────────────────────────────────────────────────── export async function fetchBackups(): Promise { return apiGet('/backups'); } export async function createBackup(): Promise { return apiPost('/backups'); } export async function restoreBackup(backupId: string): Promise { return apiPost(`/backups/${backupId}/restore`); } export async function deleteBackup(backupId: string): Promise { return apiDelete(`/backups/${backupId}`); } // ─── React Query Hooks ───────────────────────────────────────────────────── export function useBackups() { return useQuery({ queryKey: ['backups'], queryFn: fetchBackups, refetchInterval: (query) => { // Auto-refresh while any backup is pending const data = query.state.data; if (data && data.backups.some((b) => b.status === 'pending')) { return 3000; // Poll every 3 seconds } return false; }, }); } export function useCreateBackup() { const queryClient = useQueryClient(); return useMutation({ mutationFn: createBackup, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['backups'] }); }, }); } export function useRestoreBackup() { const queryClient = useQueryClient(); return useMutation({ mutationFn: restoreBackup, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['backups'] }); }, }); } export function useDeleteBackup() { const queryClient = useQueryClient(); return useMutation({ mutationFn: deleteBackup, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['backups'] }); }, }); } // ─── Backup Configuration ──────────────────────────────────────────────────── export interface BackupConfig { backup_enabled: boolean; backup_interval: string; backup_retention_days: number; backup_destination: string; } export interface BackupHistoryEntry { id: string; timestamp: string | null; action: string; success: boolean; destination: string; error: string; } export interface BackupHistoryResponse { history: BackupHistoryEntry[]; } export async function fetchBackupConfig(): Promise { return apiGet('/system-settings/backup-config'); } export async function updateBackupConfig(config: Partial): Promise { return apiPut('/system-settings/backup-config', config); } export async function triggerBackupNow(): Promise<{ message: string; job_id: string }> { return apiPost<{ message: string; job_id: string }>('/system-settings/backup-now'); } export async function fetchBackupHistory(): Promise { return apiGet('/system-settings/backup-history'); } export function useBackupConfig() { return useQuery({ queryKey: ['backup-config'], queryFn: fetchBackupConfig, }); } export function useUpdateBackupConfig() { const queryClient = useQueryClient(); return useMutation>({ mutationFn: updateBackupConfig, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['backup-config'] }); }, }); } export function useTriggerBackupNow() { const queryClient = useQueryClient(); return useMutation<{ message: string; job_id: string }, Error>({ mutationFn: triggerBackupNow, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['backups'] }); queryClient.invalidateQueries({ queryKey: ['backup-history'] }); }, }); } export function useBackupHistory() { return useQuery({ queryKey: ['backup-history'], queryFn: fetchBackupHistory, }); }