From 834ad772c6ff206282bf37d1282e3d308483a2a5 Mon Sep 17 00:00:00 2001 From: zipg Date: Mon, 20 Jul 2026 00:53:49 +0800 Subject: [PATCH] feat(elasticsearch): support Kibana proxy connections --- .../connection/ConnectionDialog.vue | 65 ++++- apps/desktop/src/i18n/locales/en.ts | 4 + apps/desktop/src/i18n/locales/es.ts | 4 + apps/desktop/src/i18n/locales/it.ts | 4 + apps/desktop/src/i18n/locales/ja.ts | 4 + apps/desktop/src/i18n/locales/pt-BR.ts | 4 + apps/desktop/src/i18n/locales/zh-CN.ts | 4 + apps/desktop/src/i18n/locales/zh-TW.ts | 4 + .../connection/elasticsearchKibanaProxy.ts | 33 +++ crates/dbx-core/src/connection.rs | 1 + .../dbx-core/src/db/elasticsearch_driver.rs | 235 ++++++++++++++++-- .../elasticsearchKibanaProxy.test.ts | 23 ++ src-tauri/src/commands/connection.rs | 2 + 13 files changed, 362 insertions(+), 25 deletions(-) create mode 100644 apps/desktop/src/lib/connection/elasticsearchKibanaProxy.ts create mode 100644 packages/app-tests/elasticsearchKibanaProxy.test.ts diff --git a/apps/desktop/src/components/connection/ConnectionDialog.vue b/apps/desktop/src/components/connection/ConnectionDialog.vue index 51fcf8aa3..4b4b7efc8 100644 --- a/apps/desktop/src/components/connection/ConnectionDialog.vue +++ b/apps/desktop/src/components/connection/ConnectionDialog.vue @@ -88,6 +88,7 @@ import { oceanbaseModeConnectionPatch, oceanbaseSubModeFromConfig } from "@/lib/ import { translateBackendError } from "@/i18n/backend-errors"; import { applyHiveKerberosSubmitConfig, hiveKerberosFormConfig, type HiveKerberosAuthMode } from "@/lib/database/hiveKerberosOptions"; import { hasCloudflareD1Credentials, isCloudflareD1Connection, normalizeCloudflareD1Connection } from "@/lib/connection/cloudflareD1"; +import { buildElasticsearchExternalConfig, elasticsearchConnectionModeFromConfig, elasticsearchKibanaBasePathFromConfig, type ElasticsearchConnectionMode } from "@/lib/connection/elasticsearchKibanaProxy"; type DbOption = { value: string; label: string }; type DbCategory = { key: string; title: string; options: DbOption[] }; @@ -251,6 +252,31 @@ const defaultForm = (): ConnectionForm => ({ visible_databases: undefined, }); +const elasticsearchConnectionMode = ref("direct"); +const elasticsearchKibanaBasePath = ref(""); +const elasticsearchConnectionPorts = ref>({ + direct: 9200, + kibana: 5601, +}); + +function resetElasticsearchProxyFields(externalConfig?: unknown) { + const mode = elasticsearchConnectionModeFromConfig(externalConfig); + elasticsearchConnectionMode.value = mode; + elasticsearchKibanaBasePath.value = elasticsearchKibanaBasePathFromConfig(externalConfig); + elasticsearchConnectionPorts.value = { + direct: mode === "direct" ? form.value.port : 9200, + kibana: mode === "kibana" ? form.value.port : 5601, + }; +} + +function switchElasticsearchConnectionMode(mode: ElasticsearchConnectionMode) { + if (mode === elasticsearchConnectionMode.value) return; + elasticsearchConnectionPorts.value[elasticsearchConnectionMode.value] = form.value.port; + form.value.port = elasticsearchConnectionPorts.value[mode]; + elasticsearchConnectionMode.value = mode; + resetTestState(); +} + function defaultSshTunnel(): SshTunnelConfig { return { id: uuid(), @@ -1481,6 +1507,7 @@ function applyProfile(val: string, preserveConnectionFields = false) { const profile = driverProfiles[val]; if (!profile) return; + const previousDatabaseType = form.value.db_type; selectedType.value = val; form.value.db_type = profile.type; form.value.driver_profile = val; @@ -1488,6 +1515,9 @@ function applyProfile(val: string, preserveConnectionFields = false) { if (profile.type !== "sqlserver") { form.value.external_config = undefined; } + if (profile.type !== "elasticsearch" || previousDatabaseType !== "elasticsearch") { + resetElasticsearchProxyFields(); + } if (!preserveConnectionFields) { form.value.port = profile.port; @@ -1652,6 +1682,7 @@ watch( } else { resetInfluxDbFields(); } + resetElasticsearchProxyFields(config.db_type === "elasticsearch" ? config.external_config : undefined); resetHiveKerberosFields(config.db_type === "hive" ? config : undefined); h2ConnectionMode.value = h2ConnectionModeForConfig(config); customColorInput.value = config.color || ""; @@ -1688,6 +1719,7 @@ watch( resetMqFields(); resetNacosFields(); resetInfluxDbFields(); + resetElasticsearchProxyFields(); resetHiveKerberosFields(); oceanbaseSubMode.value = "mysql"; h2ConnectionMode.value = "file"; @@ -2657,6 +2689,8 @@ function connectionConfigForSubmit(id: string, generatedName = ""): ConnectionCo config.password = config.password.trim(); config.database = config.database?.trim() || undefined; } + } else if (config.db_type === "elasticsearch") { + config.external_config = buildElasticsearchExternalConfig(elasticsearchConnectionMode.value, elasticsearchKibanaBasePath.value); } else if (config.db_type === "sqlserver") { config.external_config = sqlServerPortExplicitFromConfig(config) ? { portExplicit: true } : undefined; } else { @@ -5086,12 +5120,41 @@ function openExternalUrl(url: string) {