From 10373bdf36a9f879199a4756f62ccbec0fc89a69 Mon Sep 17 00:00:00 2001 From: Illuminated2020 <2357303264@qq.com> Date: Sun, 10 May 2026 16:52:39 +0800 Subject: [PATCH] =?UTF-8?q?feat(dbx-core):=20=E6=96=B0=E5=A2=9E=20CLI=20en?= =?UTF-8?q?velope=20DTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 CLI source、error code、error 和 envelope 类型 - 导出 dbx-core::cli 模块并补充序列化单元测试 - 补齐既有测试 fixture 的 JDBC 默认字段以恢复目标测试编译 --- crates/dbx-core/src/cli.rs | 67 ++++++++++++++++++++++++++++++++++++++ crates/dbx-core/src/lib.rs | 1 + 2 files changed, 68 insertions(+) create mode 100644 crates/dbx-core/src/cli.rs diff --git a/crates/dbx-core/src/cli.rs b/crates/dbx-core/src/cli.rs new file mode 100644 index 0000000000..f57932f6c0 --- /dev/null +++ b/crates/dbx-core/src/cli.rs @@ -0,0 +1,67 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum CliSource { + GuiRuntime, + Headless, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum CliErrorCode { + GuiRuntimeRequired, + ConnectionNotFound, + AmbiguousConnection, + SecretUnavailable, + SshTunnelFailed, + QueryClassificationFailed, + HandoffRequired, + DdlBlocked, + ProductionWriteBlocked, + UnsupportedDatabaseType, + Timeout, + InternalError, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CliError { + pub code: CliErrorCode, + pub message: String, + pub recoverable: bool, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum CliEnvelope { + Success { ok: bool, source: CliSource, data: T }, + Failure { ok: bool, source: CliSource, error: CliError }, +} + +pub fn ok(source: CliSource, data: T) -> CliEnvelope { + CliEnvelope::Success { ok: true, source, data } +} + +pub fn fail(source: CliSource, code: CliErrorCode, message: impl Into, recoverable: bool) -> CliEnvelope { + CliEnvelope::Failure { ok: false, source, error: CliError { code, message: message.into(), recoverable } } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn serializes_success_source_as_kebab_case() { + let env = ok(CliSource::GuiRuntime, serde_json::json!({"value": 1})); + let json = serde_json::to_string(&env).unwrap(); + assert!(json.contains("\"ok\":true")); + assert!(json.contains("\"source\":\"gui-runtime\"")); + } + + #[test] + fn serializes_error_code_as_screaming_snake_case() { + let env: CliEnvelope<()> = fail(CliSource::Headless, CliErrorCode::GuiRuntimeRequired, "runtime needed", true); + let json = serde_json::to_string(&env).unwrap(); + assert!(json.contains("\"GUI_RUNTIME_REQUIRED\"")); + } +} diff --git a/crates/dbx-core/src/lib.rs b/crates/dbx-core/src/lib.rs index cd34fdf92e..65ae7335a5 100644 --- a/crates/dbx-core/src/lib.rs +++ b/crates/dbx-core/src/lib.rs @@ -1,4 +1,5 @@ pub mod ai; +pub mod cli; pub mod connection; pub mod connection_secrets; pub mod db;