---
comet_change: migrate-to-turborepo
role: technical-design
canonical_spec: openspec
archived-with: 2026-07-02-migrate-to-turborepo
status: final
---

# Migrate to Turborepo Monorepo — Technical Design

## Architecture Overview

```
gongxue-base/
├── apps/
│   ├── server/                 # ← git mv backend → apps/server (NestJS API)
│   ├── admin/                  # ← git mv frontend → apps/admin (React + Vite)
│   └── student/                # 未来：学生端
├── packages/
│   └── typescript-config/      # 共享 TS 配置：base / nestjs / react-vite
├── package.json                # npm workspaces + turbo 根脚本
├── turbo.json                  # Turborepo 流水线
├── .oxfmtrc.json               # oxfmt 全局配置
├── oxlint.config.ts            # oxlint 全局配置（admin 前端）
└── docker-compose.yml          # 调整 build.context 路径
```

## Key Decisions

### 1. File Migration: `git mv`

`node_modules/` 从未被 Git 追踪，因此 `git mv backend apps/server` 和 `git mv frontend apps/admin` 可以干净执行，完整保留文件历史。

### 2. Package Manager: npm workspaces

用户指定沿用 npm。根 `package.json` 声明 `workspaces: ["apps/*", "packages/*"]`，所有根脚本委托 `turbo run` 执行。

### 3. Build Orchestration: Turborepo

`turbo.json` 定义六条流水线：

| Task | 配置 |
|------|------|
| `build` | `dependsOn: ["^build"]`, outputs: `dist/**` |
| `dev` | `cache: false`, `persistent: true` |
| `lint` | 无特殊配置，各 workspace 自行定义工具 |
| `test` | 无特殊配置 |
| `format` | `cache: false` (oxfmt) |
| `typecheck` | `dependsOn: ["^build"]` |

### 4. Toolchain: oxfmt + oxlint (mixed)

- **oxfmt**：根目录 `.oxfmtrc.json`，映射 Prettier 配置 `{ singleQuote: true, trailingComma: "all" }`
- **oxlint**：仅用于 `apps/admin`，覆盖 TypeScript + React 规则。`exhaustive-deps` 和 `react-refresh` 由 TypeScript compiler + code review 兜底
- **ESLint**：`apps/server` 保留，移除 Prettier 集成。保障 NestJS 装饰器类型检查

所有 workspace 统一使用 `lint` 脚本名，Turborepo 在 `turbo run lint` 时并行调度。

### 5. Shared TypeScript Config

`@gongxue/typescript-config` 包提供三个预设：

| 预设 | 继承 | 用途 |
|------|------|------|
| `base.json` | — | 通用选项：ES2023、strictNullChecks、skipLibCheck |
| `nestjs.json` | base | NestJS：nodenext module、experimentalDecorators、declaration |
| `react-vite.json` | base | Vite + React：bundler resolution、jsx: react-jsx、noEmit |

TypeScript 版本统一为 `~6.0.2`（从 server 5.7→6.0 和 admin 6.0 对齐）。

### 6. Docker Compose

容器名 `dorm_billing_backend` / `dorm_billing_frontend` 保持不变，仅调整 `build.context`：
- `backend: build: ./apps/server`
- `frontend: build: ./apps/admin`

## Data Flow

```
npm run dev (根)
    │
    ▼
turbo run dev
    │
    ├──▶ apps/server (NestJS, :3003)   ← ESLint, @gongxue/typescript-config/nestjs
    └──▶ apps/admin (Vite, :3002)      ← oxlint, @gongxue/typescript-config/react-vite
              │
              ▼ /api proxy → localhost:3003
```

## Testing Strategy

### Core Verification Chain

1. `npm install` — 所有 workspace 依赖正确安装，hoisting 无冲突
2. `npm run build` — server + admin 构建通过
3. `npm run lint` — server ESLint + admin oxlint 通过
4. `npm run format -- --check` — oxfmt 格式化检查通过
5. `npm run test --workspace=apps/server` — NestJS Jest 测试通过

### Runtime Verification

- `npm run dev` → server :3003 + admin :3002 并行启动
- admin Vite 代理 `/api` → `localhost:3003` 正常工作

### Docker Verification

- `docker compose build` — 所有镜像构建成功
- `docker compose up` — 所有服务启动并响应

## Risks & Mitigations

| Risk | Impact | Mitigation |
|------|--------|------------|
| `git mv` 后路径引用失效 | docker-compose、tsconfig extends、scripts | 逐文件验证，每步 commit |
| oxlint 规则覆盖不全 | `exhaustive-deps`、`react-refresh` 缺失 | TS compiler + code review 兜底，明确文档化 |
| TS 6.x + NestJS 生态兼容 | ts-jest、ts-node 可能报错 | 迁移后立即验证 build + test |
| npm hoisting 行为变化 | 子项目可能拿到不兼容版本 | 重新 install 后逐 workspace 验证 |
