# TUI Backend Contract 日期:2026-03-27 作者:Senior Backend Engineer ## 1. 当前后端边界 - `crates/db-core`:数据库无关的领域对象与基础校验。 - `crates/db-config`:连接 profile、密码环境变量注入与脱敏摘要。 - `crates/db-drivers`:PostgreSQL / MySQL / SQLite 驱动实现与差异收敛。 - `crates/db-app`:`connect` / `inspect` / `query` / `export` 共享应用编排、结构化结果、统一错误对象,以及 TUI worker 可复用的执行状态。 - `apps/cli`:参数解析、stdout/stderr 渲染、退出码。 ## 2. 持久化边界 - 当前产品仍是单次命令执行模型,没有连接配置持久化、历史记录持久化或后台状态存储。 - 当前写路径只有: - `export` 明确指定的输出文件 - SQLite 目标数据库本身(由用户选择) - TUI 第二阶段 live integration 仍不引入新的数据库、本地缓存库或后台 daemon 存储契约。 ## 3. 共享请求对象 TUI worker 应直接构造共享 Rust 对象,不要拼接 CLI flags,更不要解析 CLI 文本。 ### Connect - 输入:`db_config::ConnectionProfile` - 说明: - `name` 用于当前会话内的目标标识 - `target` 复用 `db_core::ConnectionTarget` - `password_env_var` 只作为脱敏标签保留;secret 仍通过环境变量注入,不进入持久化 ### Inspect - 输入:`db_core::InspectRequest` - 字段: - `schema: Option` - `table: Option` - 约束: - `table.is_some()` 时必须同时提供 `schema` ### Query - 输入:`db_core::QueryRequest` - 字段: - `sql` - `source` - `parameters` - `source` 语义: - `QuerySource::Inline` - `QuerySource::File` ### Export - 输入: - `db_core::QueryRequest` - `db_core::ExportRequest` - `ExportRequest` 字段: - `format` - `output_path` - `overwrite` - 约束: - 只允许导出返回结果集的查询 - 不静默覆盖已有文件 - 不为 TUI 增加新的导出元数据存储 ## 4. 共享结构化结果 TUI 应优先直接调用 `crates/db-app`,不要解析 CLI 的人类可读文本。 ### Connect - 返回 `ConnectResponse` - 字段: - `target.profile_name` - `target.driver` - `target.endpoint` - `target.password_env_var` - `status` - 当前 `status` 固定为 `connected` ### Inspect - 返回 `InspectResponse` - 字段: - `target` - `scope.schema` - `scope.table` - `payload` - `payload.kind` 为: - `schemas` - `tables` - `columns` - `payload.items` 允许为空;空数组不是错误 ### Query - 返回 `QueryResponse` - 字段: - `target` - `source.kind`:`inline` / `file` - `source.label` - `source.path` - `result.columns` - `result.rows` - `result.rows_affected` - `result.row_count` - `rows_affected != null` 表示 command-style 执行成功但没有结果集 ### Export - 返回 `ExportResponse` - 字段: - `target` - `source` - `export.format` - `export.output_path` - `export.overwrite` - `row_count` ## 5. 错误模型 `db-app::AppError.kind` 当前分为: - `validation` - `connection` - `authentication` - `inspect` - `query` - `export` 这组分类是 TUI banner、QA 断言和未来 GUI 状态映射的当前稳定基础。 `AppError.target` 为可选字段: - 有目标上下文时返回脱敏后的 `ConnectionSummary` - 参数校验在目标尚未构成时可为 `null` ## 6. Worker / Channel 状态契约 `crates/db-app` 现提供: - `AppOperation`:`connect | inspect | query | export` - `OperationState`:`running | success | empty | error` - `AppEvent`:worker / channel 推荐 envelope 推荐发送顺序: 1. 先发 `AppEvent::running(operation)` 2. 成功后发送 `response.into_event()` 3. 失败时发送 `error.into_event()` 状态语义固定如下: - `connect` - `running`:正在测试连接 - `success`:连接成功 - `error`:连接失败 - `inspect` - `success`:返回非空 schema / table / column 集合 - `empty`:返回空集合,但请求本身成功 - `error`:inspect 失败 - `query` - `success`:返回至少一行,或 `rows_affected` 非空 - `empty`:返回零行且 `rows_affected == null` - `error`:执行失败 - `export` - `success`:文件写入成功;`row_count == 0` 仍算成功 - `error`:导出校验、查询或文件写入失败 示例: ```rust use db_app::{AppEvent, AppOperation}; sender.send(AppEvent::<()>::running(AppOperation::Query))?; match db_app::query(&profile, &request) { Ok(response) => sender.send(response.into_event())?, Err(error) => sender.send(error.into_event())?, } ``` ## 7. CLI 结构化输出 CLI 继续保留默认文本输出,同时新增: - `--result-format text` - `--result-format json` JSON 返回 envelope: ```json { "status": "success", "operation": "query", "data": {} } ``` 错误返回 envelope: ```json { "status": "error", "operation": "query", "error": { "operation": "query", "kind": "query", "message": "..." } } ``` CLI JSON envelope 继续作为跨入口回归样本,但 TUI live path 不应以调用 CLI 二进制作为主集成方式。 ## 8. Frontend 接入约束 - TUI 直接依赖 `crates/db-app` 与 `db-core`,不解析 CLI stdout/stderr - UI 状态映射应优先使用 `OperationState`,不要自行发明另一套 success/empty/error 语义 - `ConnectionSummary.endpoint` 与 `password_env_var` 仅用于展示脱敏上下文,不应用作 secret 来源 - `AppError.kind` 必须原样进入状态区 / inspector,避免把 `validation`、`connection`、`query` 混成统一“失败” - 若未来引入异步 worker 池,仍以共享 response/error 对象作为唯一 UI 数据源 ## 9. 当前回归边界 - `crates/db-app` 回归需覆盖: - response -> `OperationState` 映射 - `AppEvent` / `AppError` 序列化 - 空 inspect / 空 query / command query 语义 - `apps/cli` 回归继续覆盖: - `--result-format json` envelope - text/json 输出在相同 `db-app` 结果上的一致性 ## 10. 演进规则 - CLI 文本文案可小幅演进,但 `db-app` 结构化对象字段应保持兼容。 - 新增数据库驱动时,优先扩展 `db-drivers` 与 `db-app`,不要在 TUI/CLI 内复制数据库语义。 - 若未来引入本地持久化(例如连接历史),应先新增独立文档定义存储边界,再进入实现。