From 71a63ae5e89f4077e28261a8122d5543c6e1dbbf Mon Sep 17 00:00:00 2001 From: ZacharyZcR Date: Thu, 16 Jul 2026 11:52:53 +0800 Subject: [PATCH] fix: restore database import in embedded desktop mode (#1060) --- src/ui/lib/database-transfer-url.test.ts | 54 ++++++++++++++++++++++++ src/ui/lib/database-transfer-url.ts | 33 +++++++++++++++ src/ui/sidebar/AdminSettingsPanel.tsx | 35 ++++++--------- 3 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 src/ui/lib/database-transfer-url.test.ts create mode 100644 src/ui/lib/database-transfer-url.ts diff --git a/src/ui/lib/database-transfer-url.test.ts b/src/ui/lib/database-transfer-url.test.ts new file mode 100644 index 00000000..bdbd3b37 --- /dev/null +++ b/src/ui/lib/database-transfer-url.test.ts @@ -0,0 +1,54 @@ +import { describe, expect, it } from "vitest"; +import { getDatabaseTransferUrl } from "./database-transfer-url"; + +const productionLocation = { + protocol: "https:", + host: "termix.example.com", + hostname: "termix.example.com", + port: "", +}; + +describe("getDatabaseTransferUrl", () => { + it("uses the embedded backend for Electron without a remote server", () => { + expect( + getDatabaseTransferUrl("import", { + electron: true, + configuredServerUrl: null, + location: productionLocation, + }), + ).toBe("http://localhost:30001/database/import"); + }); + + it("uses the configured Electron server without duplicate slashes", () => { + expect( + getDatabaseTransferUrl("export", { + electron: true, + configuredServerUrl: "https://termix.example.com/", + location: productionLocation, + }), + ).toBe("https://termix.example.com/database/export"); + }); + + it("uses the browser base path in production", () => { + expect( + getDatabaseTransferUrl("import", { + electron: false, + location: productionLocation, + }), + ).toBe("https://termix.example.com/database/import"); + }); + + it("uses the backend development port for the Vite frontend", () => { + expect( + getDatabaseTransferUrl("export", { + electron: false, + location: { + protocol: "http:", + host: "localhost:5173", + hostname: "localhost", + port: "5173", + }, + }), + ).toBe("http://localhost:30001/database/export"); + }); +}); diff --git a/src/ui/lib/database-transfer-url.ts b/src/ui/lib/database-transfer-url.ts new file mode 100644 index 00000000..e0f3c5fd --- /dev/null +++ b/src/ui/lib/database-transfer-url.ts @@ -0,0 +1,33 @@ +import { getBasePath } from "./base-path"; + +type BrowserLocation = Pick< + Location, + "protocol" | "host" | "hostname" | "port" +>; + +interface DatabaseTransferUrlOptions { + electron: boolean; + configuredServerUrl?: string | null; + location: BrowserLocation; +} + +export function getDatabaseTransferUrl( + operation: "export" | "import", + { electron, configuredServerUrl, location }: DatabaseTransferUrlOptions, +): string { + if (electron) { + const serverUrl = configuredServerUrl || "http://localhost:30001"; + return `${serverUrl.replace(/\/$/, "")}/database/${operation}`; + } + + const development = + location.port === "5173" || + location.hostname === "localhost" || + location.hostname === "127.0.0.1"; + + if (development) { + return `http://localhost:30001/database/${operation}`; + } + + return `${location.protocol}//${location.host}${getBasePath()}/database/${operation}`; +} diff --git a/src/ui/sidebar/AdminSettingsPanel.tsx b/src/ui/sidebar/AdminSettingsPanel.tsx index 161ec413..6c04a640 100644 --- a/src/ui/sidebar/AdminSettingsPanel.tsx +++ b/src/ui/sidebar/AdminSettingsPanel.tsx @@ -33,6 +33,7 @@ import { getCommandHistoryEnabled, updateCommandHistoryEnabled, isElectron, + getConfiguredServerUrl, getUserRoles, } from "@/main-axios"; import { @@ -69,7 +70,7 @@ import { type AdminUser, } from "./AdminManagementSections"; import { toast } from "sonner"; -import { getBasePath } from "@/lib/base-path"; +import { getDatabaseTransferUrl } from "@/lib/database-transfer-url"; import { AdminDatabaseSection, AdminGeneralSettingsSection, @@ -717,17 +718,11 @@ export function AdminSettingsPanel() { async function handleExportDatabase() { setExportLoading(true); try { - const isDev = - !isElectron() && - (window.location.port === "5173" || - window.location.hostname === "localhost" || - window.location.hostname === "127.0.0.1"); - - const apiUrl = isElectron() - ? `${window.configuredServerUrl}/database/export` - : isDev - ? `http://localhost:30001/database/export` - : `${window.location.protocol}//${window.location.host}${getBasePath()}/database/export`; + const apiUrl = getDatabaseTransferUrl("export", { + electron: isElectron(), + configuredServerUrl: getConfiguredServerUrl(), + location: window.location, + }); const response = await fetch(apiUrl, { method: "POST", @@ -769,17 +764,11 @@ export function AdminSettingsPanel() { } setImportLoading(true); try { - const isDev = - !isElectron() && - (window.location.port === "5173" || - window.location.hostname === "localhost" || - window.location.hostname === "127.0.0.1"); - - const apiUrl = isElectron() - ? `${window.configuredServerUrl}/database/import` - : isDev - ? `http://localhost:30001/database/import` - : `${window.location.protocol}//${window.location.host}${getBasePath()}/database/import`; + const apiUrl = getDatabaseTransferUrl("import", { + electron: isElectron(), + configuredServerUrl: getConfiguredServerUrl(), + location: window.location, + }); const formData = new FormData(); formData.append("file", importFile);