6.5 KiB
6.5 KiB
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::ConnectionTargetpassword_env_var只作为脱敏标签保留;secret 仍通过环境变量注入,不进入持久化
Inspect
- 输入:
db_core::InspectRequest - 字段:
schema: Option<String>table: Option<String>
- 约束:
table.is_some()时必须同时提供schema
Query
- 输入:
db_core::QueryRequest - 字段:
sqlsourceparameters
source语义:QuerySource::InlineQuerySource::File
Export
- 输入:
db_core::QueryRequestdb_core::ExportRequest
ExportRequest字段:formatoutput_pathoverwrite
- 约束:
- 只允许导出返回结果集的查询
- 不静默覆盖已有文件
- 不为 TUI 增加新的导出元数据存储
4. 共享结构化结果
TUI 应优先直接调用 crates/db-app,不要解析 CLI 的人类可读文本。
Connect
- 返回
ConnectResponse - 字段:
target.profile_nametarget.drivertarget.endpointtarget.password_env_varstatus
- 当前
status固定为connected
Inspect
- 返回
InspectResponse - 字段:
targetscope.schemascope.tablepayload
payload.kind为:schemastablescolumns
payload.items允许为空;空数组不是错误
Query
- 返回
QueryResponse - 字段:
targetsource.kind:inline/filesource.labelsource.pathresult.columnsresult.rowsresult.rows_affectedresult.row_count
rows_affected != null表示 command-style 执行成功但没有结果集
Export
- 返回
ExportResponse - 字段:
targetsourceexport.formatexport.output_pathexport.overwriterow_count
5. 错误模型
db-app::AppError.kind 当前分为:
validationconnectionauthenticationinspectqueryexport
这组分类是 TUI banner、QA 断言和未来 GUI 状态映射的当前稳定基础。
AppError.target 为可选字段:
- 有目标上下文时返回脱敏后的
ConnectionSummary - 参数校验在目标尚未构成时可为
null
6. Worker / Channel 状态契约
crates/db-app 现提供:
AppOperation:connect | inspect | query | exportOperationState:running | success | empty | errorAppEvent<T>:worker / channel 推荐 envelope
推荐发送顺序:
- 先发
AppEvent::running(operation) - 成功后发送
response.into_event() - 失败时发送
error.into_event()
状态语义固定如下:
connectrunning:正在测试连接success:连接成功error:连接失败
inspectsuccess:返回非空 schema / table / column 集合empty:返回空集合,但请求本身成功error:inspect 失败
querysuccess:返回至少一行,或rows_affected非空empty:返回零行且rows_affected == nullerror:执行失败
exportsuccess:文件写入成功;row_count == 0仍算成功error:导出校验、查询或文件写入失败
示例:
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:
{
"status": "success",
"operation": "query",
"state": "success",
"data": {}
}
status继续只区分 envelope 级成功/失败state对齐共享应用层状态:connect:successinspect:success | emptyquery:success | emptyexport:success
错误返回 envelope:
{
"status": "error",
"operation": "query",
"state": "error",
"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<T>/AppError序列化- 空 inspect / 空 query / command query 语义
- response ->
apps/cli回归继续覆盖:--result-format jsonenvelope- text/json 输出在相同
db-app结果上的一致性
10. 演进规则
- CLI 文本文案可小幅演进,但
db-app结构化对象字段应保持兼容。 - 新增数据库驱动时,优先扩展
db-drivers与db-app,不要在 TUI/CLI 内复制数据库语义。 - 若未来引入本地持久化(例如连接历史),应先新增独立文档定义存储边界,再进入实现。