Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ jobs:
uses: actions/setup-go@v5
with:
go-version: '1.24'
cache-dependency-path: backend/go.sum
- name: Install dependencies
run: cd frontend && npm install
- name: Install Playwright Browsers
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ jobs:
with:
workspaces: frontend/tauri -> target

- name: Install protoc
uses: arduino/setup-protoc@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}


- name: Install frontend dependencies
run: cd frontend && npm install
Expand Down
137 changes: 31 additions & 106 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,118 +1,43 @@
# vstable
# Agent Context: vstable Root

## Quick commands
> **ATTENTION AI AGENTS & DEVELOPERS:**
> 本文件是 `vstable` 项目的**全局**开发指南。请作为所有子目录操作的最高纲领。各独立模块的详细业务逻辑与特定规则,请参阅对应目录下的 `AGENTS.md`。

- `cd frontend && npm run dev` (拉起双端开发环境:Tauri + Go Engine)
- `cd frontend && npm run dev-frontend` (仅启动前端 Vite,不启动 Tauri/Go,适合纯 UI 调试)
- `cd frontend && npm run build` (编译前端与后端二进制)
- `cd frontend && npm run test` (Vitest 单元测试)
- `cd frontend && npm run test:e2e` (Playwright 全链路测试,会先 build)
- `cd frontend && npm run check` (Biome 格式化与静态检查)
- `cd frontend && npm run docker:up` (启动测试所需的 PG/MySQL 容器)
- `cd frontend && npm run docker:down` (停止并清理测试容器)
- `cd backend && go test -v ./...` (后端集成测试,需 Docker)
- `cd backend && ./scripts/gen_proto.sh` (生成 gRPC 代码)

## Project overview

vstable 是一款专为开发者设计的现代数据库管理工具,支持可视化表结构设计与高性能 SQL 查询。其核心设计目标是“状态对齐”,即通过对比新旧 AST(抽象语法树)生成精确的数据库变更语句。

## Tech stack

- **Frontend**: React 19 (TypeScript), TailwindCSS 4.0, Monaco Editor
- **Desktop Runtime**: Tauri 2.0 (Rust), Vite
- **Backend Engine**: Go 1.24 (vstable-engine)
- **Communication**: gRPC, Protocol Buffers (Strict types)
- **Database Drivers**: `pgx/v5` (PostgreSQL), `go-sql-driver/mysql` (MySQL)
- **Testing**: Playwright (E2E), Vitest (Unit), Go test (Integration)
- **Infrastructure**: Docker Compose (Database testing environments)

## Architecture overview

该项目采用解耦的三层架构:
1. **Frontend (React)**: 基于 React 19、TailwindCSS 4.0 和 Monaco Editor 构建的现代用户界面。负责处理用户交互、SQL 编辑以及可视化的表结构设计。
2. **Desktop Runtime (Tauri)**: 作为操作系统与 Web 内容之间的桥梁。基于 Rust 的核心层负责管理 Go 引擎(Sidecar)的生命周期、处理由前端发起的高性能 IPC 请求,并通过原生的能力(Capabilities)系统提供持久化存储和窗口管理。
3. **Backend Engine (Go)**: 一个使用 Go 1.24 编写的高性能守护进程。它在本地作为 Tauri Sidecar 运行并向 Rust 核心暴露 gRPC API(定义于 `vstable.proto`)。它承担繁重的计算任务,包括数据库连接管理、AST 解析,以及基于状态对齐进行 Schema Diff 并生成精确的 DDL 语句。
## 1. Project Overview & Core Logic

## Major modules and interfaces
`vstable` 是一款专为开发者设计的现代数据库管理工具,支持可视化表结构设计与高性能 SQL 查询。

- **Go Engine (`backend/`)**:
- `internal/ast`: 核心 Schema Diff 引擎。提供 AST 类型定义以及特定数据库方言(PostgreSQL/MySQL)的编译器,用于基于状态对齐生成精确的 DDL Diff。
- `internal/db`: 数据库连接管理器和驱动程序抽象。
- `main.go`: 启动 gRPC Server,处理来自 Tauri Rust 核心的远程过程调用。
- `scripts/gen_proto.sh`: 构建脚本,用于从 `.proto` 文件生成 Go 代码。
- **Tauri Core (`frontend/tauri/`)**:
- `src/lib.rs`: Tauri 应用的核心库。初始化 gRPC 客户端池以通过严格类型的 Protobuf 协议与后端引擎通信;处理前端的 IPC 路由(如 `db_connect`, `db_query`),以及原生窗口控制和日志捕获。
- `src/main.rs`: 桌面应用启动入口。
- `tauri.conf.json`: 应用配置,包括构建指令、窗口属性以及 Sidecar (Go 引擎)的绑定声明。
- **React Renderer (`frontend/src/`)**:
- `features/`: 包含核心功能模块:
- `connection`: 数据库连接表单和管理。
- `navigator`: 数据库和数据表树形视图。
- `query-editor`: 基于 Monaco 的 SQL 执行环境。
- `schema-designer`: 可视化的表结构修改器。
- `table-viewer`: 用于查看和编辑表数据的数据网格。
- `api/`: 通过 IPC 与主进程进行通信的 API 客户端。
**全栈核心逻辑:基于 AST 的“状态对齐” (Schema Diff Engine)**
传统数据库工具通过手动拼接 `ALTER TABLE` 语句来修改表结构。`vstable` 的核心逻辑是“状态对齐”:
1. **解析 (Parse)**:将当前的数据库表结构拉取并解析为内部统一的抽象语法树 (AST)。
2. **修改 (Mutate)**:用户在前端可视化的 React Schema Designer 中修改表结构,产生一个目标 AST(New State)。
3. **对比与生成 (Diff & Generate)**:Go 后端比较 Old AST 与 New AST,针对不同的数据库方言(PostgreSQL/MySQL),精确生成对应的 DDL 变更语句。

## Repo map
## 2. Global Architecture: Direct Communication

- `backend/`: Go 后端引擎源码。
- `internal/ast/`: AST 类型、Diff 逻辑以及数据库方言编译器。
- `internal/db/`: 数据库驱动实现。
- `frontend/`: Tauri 应用与 React 前端。
- `e2e/`: 用于全链路验证的 Playwright E2E 测试。
- `tauri/`: Tauri 胶水代码,将 frontend 和 backend 粘合在一起。
- `src/`: React Web 应用。
- `components/`: 可复用的通用 UI 组件。
- `features/`: 特定领域的业务逻辑与视图。
- `hooks/`, `stores/`: 全局状态管理 (Zustand) 和自定义 React Hooks。
- `requirement/`: 产品需求、设计文档和待办事项列表。
项目采用解耦的三层架构,并**强制执行**“前端直连后端”的网络通信模型:

## Conventions and quality
1. **Frontend (React)**: 负责所有业务交互、可视化设计,并通过 gRPC-Web HTTP 直连后端。(详见 `frontend/AGENTS.md`)
2. **Desktop Runtime (Tauri)**: 降级为 “Thin Shell”,仅负责原生窗口控制与启动后台引擎。(详见 `frontend/tauri/AGENTS.md`)
3. **Backend Engine (Go)**: 本地守护进程(Sidecar),负责繁重的 AST 计算与数据库 I/O。(详见 `backend/AGENTS.md`)

- **代码风格**:
- 前端:TypeScript 严格模式,Biome。
- 后端:Go 1.24 标准风格。
- **测试驱动**:
- 新功能必须包含单元测试(Vitest)。
- DDL 方言修改必须通过后端集成测试(`go test`)。
- 关键路径(连接、查询、同步)必须覆盖 E2E 测试。
- **全链路验证**:
- 自动完成 Docker 环境拉起、引擎预编译、模拟用户操作。
- 双向对齐验证:在后端维护同步化的集成测试,确保生成的 DDL 在真实数据库中执行一致。
- **UI 渲染稳定性**:
- 对于包含 Monaco Editor 等对 DOM 物理位置敏感的组件,在实现排序功能时必须采用“稳定 DOM 排序”策略。
- 即 DOM 物理顺序按 ID 保持固定,与 UI 显示顺序解耦,仅通过切换可见性而非物理移动 DOM 节点来处理排序。
- **类型安全性**: 贯穿前端 UI 到后端 AST 编译器的强类型约束。
## 3. Global Hard Rules

## Git commit messages
在为本项目编写代码时,必须遵守以下全局铁律:

采用 Conventional Commits 格式:
- **[RULE 1] 杜绝“浅模块” (No Shallow Modules in Tauri)**:
- 遵循 John Ousterhout 的《A Philosophy of Software Design》。
- 严禁在 Tauri 的 Rust 核心层编写用于“透传”网络请求的中间件代码。前端必须直接向后端发起网络请求。
- **[RULE 2] Protobuf 驱动开发 (Proto-Driven)**:
- 任何前后端交互的 API 变更,必须首发修改 `backend/api/vstable.proto`,随后运行构建脚本重新生成双端接口代码。严禁单方面 Hardcode 接口数据结构。
- **[RULE 3] 强制全链路测试保护**:
- AST 编译或方言逻辑的变更必须通过 Go 集成测试。
- UI 核心链路(连接、设计器、数据网格)修改必须通过 Playwright 全链路测试。(详见 `frontend/e2e/AGENTS.md`)

```text
<type>(<scope>): <subject>
```
## 4. Quick Commands

Allowed types:
`feat`, `fix`, `test`, `refactor`, `chore`, `style`, `docs`, `perf`, `build`, `ci`, `revert`.

## Versioning

项目遵循语义化版本控制 (`MAJOR.MINOR.PATCH`):

- **Patch** 版本仅用于向后兼容的 Bug 修复。
- **Minor** 版本用于新增向后兼容的功能和改进。
- **Major** 版本用于破坏性或不兼容的 API 变更。

## Release workflow

1. 确保 `master` 分支代码已更新 (pull latest)。
2. 创建发布分支,如 `release-v1.2.0`。
3. 更新 `frontend/package.json`、`frontend/tauri/tauri.conf.json` 中的版本号。
4. 运行全链路测试 (`npm run test:e2e` 与 `go test ./...`) 确保版本稳定性。
5. 提交变更并创建 PR。
6. PR 合并后,切换回 `master` 分支并拉取最新代码。
7. 建立标签并推送:
- `git tag v1.2.0`
- `git push --tags`
8. GitHub Actions 或相关 CI/CD 流程在检测到 tag 推送后,自动构建双端产物(Tauri Mac/Windows/Linux 与 Go Engine 二进制)并执行发布。
- `cd frontend && npm run dev` (拉起双端开发环境:Tauri + Go Engine)
- `cd frontend && npm run build` (打包全平台产物)
- `cd frontend && npm run test:e2e` (执行端到端测试)
- `cd backend && go test -v ./...` (执行后端集成测试,需预先 `npm run docker:up`)
- `cd backend && ./scripts/gen_proto.sh` (生成 gRPC 代码)
51 changes: 51 additions & 0 deletions backend/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Agent Context: Go Engine (Backend)

> **ATTENTION AI AGENTS & DEVELOPERS:**
> 此目录 `backend/` 包含了 vstable 的核心计算引擎(Go 1.24)。这里承载了数据库直连、AST Diff 计算和网络服务的重任。在编写代码前,请牢记这里的核心逻辑与架构规则。

## 1. Core Logic & Responsibilities

**AST 状态对齐与 gRPC-Web 服务**
后端作为一个独立的二进制进程(Sidecar),承担着应用中最核心的“脏活累活”。

- **gRPC-Web Server (`main.go`)**:
- 核心逻辑:后端不使用 Envoy 代理,而是借助 `improbable-eng/grpc-web` 库将标准的 gRPC Server 包装为 `http.Server`,直接向浏览器的 Fetch API 提供服务。
- **Session Management (`internal/db`)**:
- 引擎内部通过 `db.Manager` 在内存中维护了一个以 `id` (Session ID) 为键的线程安全字典,确保前端同一连接复用对应的 DB Driver 实例。

## 2. Business Logic Map (业务逻辑快速定位导航)

遇到需求变更或修复 Bug 时,请根据以下模块分工快速定位代码:

- **网络入口与拦截器 (`main.go`)**
- **职责**: 端口监听 (默认 `:39082`),gRPC-Web 协议转换。
- **跨域**: `rs/cors` 跨域策略配置。
- **拦截器**: `UnaryInterceptor` 用于全局请求的 `panic` 捕捉与耗时、错误日志打印。
- **数据库驱动层 (`internal/db/driver.go`)**
- **职责**: 底层依赖 `pgx/v5` 和 `go-sql-driver/mysql`。
- **逻辑**: 执行纯文本 SQL 并解析动态数据结构;获取数据库系统元数据 (Meta queries)。
- **抽象语法树模型 (`internal/ast/types.go`)**
- **职责**: 跨方言的统一数据结构。
- **逻辑**: 定义 Table, Column, Index 等实体,作为前后端状态对齐的媒介。
- **状态对齐与差异计算 (`internal/ast/diff.go`)**
- **职责**: 比较 Old AST 和 New AST。
- **逻辑**: 识别出需要增加、删除或修改的列与约束。
- **方言 DDL 生成器 (`internal/ast/compiler_pg.go` & `compiler_mysql.go`)**
- **职责**: 将 diff 结果翻译为特定数据库的 SQL 语句。
- **逻辑**: 处理诸如修改非空约束、更改数据类型等具体方言的 SQL 拼接。修改此类文件极易引发线上 Bug。
- **Protobuf 转换映射 (`internal/mapper/`)**
- **职责**: 将 gRPC 传入的 Protobuf struct (`pb.*`) 转换为内部 AST 原生结构。

## 3. Hard Rules for AI Agents (Go Layer)

修改后端代码时,必须遵守以下防翻车铁律:

- **[RULE 1] 跨域安全红线 (CORS Gotchas)**:
- **致命警告 (Wildcard vs. Credentials Conflict)**:当 `main.go` 中的 `AllowedOrigins` 包含 wildcard `*` 时,`AllowCredentials` **必须且只能设置为 `false`**。
- **排障特征**:一旦错误配置,浏览器会拦截 Preflight 请求,并在前端抛出晦涩的 `/vstable.EngineService/DbConnect UNKNOWN: Transport error: Load failed` 错误。
- **[RULE 2] 标准化错误处理 (gRPC Status Codes)**:
- 必须使用 `google.golang.org/grpc/status` 包装对外返回的 error,以便前端的 Interceptor 能够精准拦截和归类(如 `codes.NotFound`, `codes.InvalidArgument`)。
- **[RULE 3] 防御性编程与 Panic 恢复**:
- `UnaryInterceptor` 已提供全局 `recover()`,但在编写业务逻辑时,必须显式返回 `error`,严禁滥用 `panic`。
- **[RULE 4] AST/DDL 变更的测试覆盖要求**:
- 涉及 `internal/ast`(SQL 生成逻辑)或 `internal/db`(方言特化适配)的任何改动,**必须**补充对应的集成测试(如 `diff_integration_pg_test.go`),且必须在真实 Docker 数据库中验证执行。
9 changes: 4 additions & 5 deletions backend/api/vstable.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package vstable;
option go_package = "vstable-engine/internal/pb";

import "google/protobuf/struct.proto";
import "google/protobuf/wrappers.proto";

service EngineService {
rpc Ping(PingRequest) returns (PingResponse);
Expand Down Expand Up @@ -61,11 +60,11 @@ message ColumnDefinition {
string name = 2;
string type = 3;
repeated string enum_values = 4;
google.protobuf.Value length = 5;
google.protobuf.Value precision = 6;
google.protobuf.Value scale = 7;
optional int64 length = 5;
optional int64 precision = 6;
optional int64 scale = 7;
bool nullable = 8;
google.protobuf.StringValue default_value = 9;
optional string default_value = 9;
bool is_default_expression = 10;
bool is_primary_key = 11;
bool is_auto_increment = 12;
Expand Down
17 changes: 11 additions & 6 deletions backend/go.mod
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
module vstable-engine

go 1.24.0
go 1.25.0

require (
github.com/go-sql-driver/mysql v1.9.3
github.com/golang/protobuf v1.5.4
github.com/improbable-eng/grpc-web v0.15.0
github.com/jackc/pgx/v5 v5.8.0
github.com/rs/cors v1.7.0
google.golang.org/grpc v1.79.2
google.golang.org/protobuf v1.36.11
)

require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/cenkalti/backoff/v4 v4.1.1 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
golang.org/x/net v0.48.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/text v0.32.0 // indirect
github.com/klauspost/compress v1.11.7 // indirect
golang.org/x/net v0.53.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.43.0 // indirect
golang.org/x/text v0.36.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
nhooyr.io/websocket v1.8.6 // indirect
)
Loading
Loading