feat: implement database backup and restore functionality in settings page
- Added UI components for downloading and restoring the application database, enhancing data management capabilities. - Integrated new API routes for system database operations in the backend. - Implemented state management for backup and restore processes, including loading indicators and user notifications.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import { ApiClientError } from "@/shared/api/http-client"
|
||||
|
||||
function trimBaseUrl(baseUrl: string): string {
|
||||
return baseUrl.replace(/\/$/, "")
|
||||
}
|
||||
|
||||
function parseFilename(contentDisposition: string | null, fallback: string): string {
|
||||
if (!contentDisposition) return fallback
|
||||
const utfMatch = /filename\*=UTF-8''([^;]+)/i.exec(contentDisposition)
|
||||
if (utfMatch?.[1]) {
|
||||
try {
|
||||
return decodeURIComponent(utfMatch[1])
|
||||
} catch {
|
||||
return utfMatch[1]
|
||||
}
|
||||
}
|
||||
const plainMatch = /filename="([^"]+)"/i.exec(contentDisposition)
|
||||
if (plainMatch?.[1]) return plainMatch[1]
|
||||
return fallback
|
||||
}
|
||||
|
||||
export async function downloadSystemDatabaseBackup(
|
||||
baseUrl: string,
|
||||
): Promise<{ blob: Blob; filename: string }> {
|
||||
const res = await fetch(`${trimBaseUrl(baseUrl)}/api/system/database/backup`)
|
||||
if (!res.ok) {
|
||||
const payload = await res.json().catch(() => undefined)
|
||||
const msg =
|
||||
typeof payload === "object" &&
|
||||
payload !== null &&
|
||||
"error" in payload &&
|
||||
typeof (payload as { error?: unknown }).error === "string"
|
||||
? (payload as { error: string }).error
|
||||
: res.statusText
|
||||
throw new ApiClientError(msg, res.status, payload)
|
||||
}
|
||||
const blob = await res.blob()
|
||||
const filename = parseFilename(res.headers.get("Content-Disposition"), "mikrotik-manager.db")
|
||||
return { blob, filename }
|
||||
}
|
||||
|
||||
export async function restoreSystemDatabaseBackup(baseUrl: string, file: File): Promise<void> {
|
||||
const body = await file.arrayBuffer()
|
||||
const res = await fetch(`${trimBaseUrl(baseUrl)}/api/system/database/restore`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/octet-stream" },
|
||||
body,
|
||||
})
|
||||
if (!res.ok) {
|
||||
const payload = await res.json().catch(() => undefined)
|
||||
const msg =
|
||||
typeof payload === "object" &&
|
||||
payload !== null &&
|
||||
"error" in payload &&
|
||||
typeof (payload as { error?: unknown }).error === "string"
|
||||
? (payload as { error: string }).error
|
||||
: res.statusText
|
||||
throw new ApiClientError(msg, res.status, payload)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user