# Backend TypeScript 迁移计划

最后更新：2026-04-14

## 结论

当前后端不建议整体重写为 Go。

更合适的路线是：

1. 保留 Node.js + Express + Playwright + PostgreSQL 主栈
2. 先把后端渐进迁移到 TypeScript
3. 同时拆分超大 service 文件
4. 补足核心业务链路测试

这样可以先解决“可维护性”和“改动风险”问题，而不会额外引入一次高成本的跨语言重写。

## 为什么现在不直接重写 Go

当前后端的主要复杂度并不来自语言本身，而是来自：

- 订单、任务、库存、领取、自动发货、webhook 多条链路同时演进
- Playwright 浏览器自动化本身就天然偏 Node 生态
- 若整体换成 Go，浏览器自动化大概率仍需保留 Node worker
- 这样会把系统变成 Go + Node + Python 三段式，边界更多，联调更难

所以现阶段最有效的动作，不是换语言，而是先把现有 Node 后端“类型化、分层化、可测试化”。

## 当前主要维护痛点

从当前仓库状态看，风险主要集中在：

- 少数超大编排文件已经承担过多职责
  - `apps/backend/src/services/admin/admin-service.js`
  - `apps/backend/src/services/claim/claim-session-service.js`
  - `apps/backend/src/services/order/webhook-service.js`
  - `apps/backend/src/services/session/session.js`
- 领域对象靠运行时约定在 routes / services / repositories 之间传递
- 当前自动化测试覆盖还偏薄，跨链路改动缺少回归保护

## 迁移目标

本次迁移不是为了“全部改成 .ts 才算完成”，而是为了达到下面几个目标：

1. 让核心领域对象具备稳定的静态类型
2. 让新增改动优先进入类型系统，而不是继续扩大纯 JS 面积
3. 让超大 service 文件拆分时有类型边界可依赖
4. 让 typecheck 和测试一起成为后端的标准校验步骤

## 分阶段计划

### 阶段 1：建立类型基础设施

目标：

- 引入后端 `tsconfig`
- 增加 `npm run typecheck`
- 先从最核心的共享配置和基础领域对象开始建类型
- 暂不改变现有运行方式，不引入编译产物，不影响 Docker 启动

范围：

- `runtimeConfig`
- 公共配置对象
- 后续会继续补：
  - admin DTO
  - order / task / inventory 基础类型
  - webhook 解析结果类型

验收标准：

- 后端可以执行 `npm run typecheck`
- 现有 `npm run dev` / `npm run start` / Docker 启动流程不受影响

### 阶段 2：按领域拆分超大 service

目标：

- 保持运行逻辑不变
- 先把“巨石编排文件”拆成更小的用例编排模块

建议拆分顺序：

1. `admin-service.js`
   - `admin-order-service`
   - `admin-task-service`
   - `admin-inventory-service`
   - `admin-webhook-service`
2. `claim-session-service.js`
   - `claim-session-lifecycle`
   - `claim-role-service`
   - `claim-redeem-orchestrator`
3. `webhook-service.js`
   - `webhook-parse`
   - `webhook-validate`
   - `webhook-process`

### 阶段 3：扩大类型覆盖

目标：

- 新增模块优先使用 `.ts`
- 旧模块逐步迁移，而不是一次性全改
- 让 routes / services / repositories 之间共享同一套领域类型

建议优先顺序：

1. `src/types/` 下沉淀共享领域模型
2. repository 返回值显式类型化
3. service 入参 / 出参类型化
4. 再迁移最稳定的新模块到 `.ts`

### 阶段 4：补核心回归测试

优先补这些主链路：

1. webhook 入单与重放
2. 库存预占 / 释放 / 换码
3. claim 会话创建 / 关闭 / 切换
4. 腾讯兑换结果分类
5. 自动发货触发条件

## 已开始执行的第一步

本轮已经落地：

1. backend 新增 `tsconfig.json`
2. backend 新增 `npm run typecheck`
3. 新增 `src/types/runtime-config.js`
4. `src/config/runtime.js` 已接入第一批类型检查
5. 新增 `src/types/admin-read-models.js`
6. `src/services/admin/admin-service.js` 的订单 / 任务 / 库存 / webhook 读取返回模型已接入第二批类型检查
7. 新增 `src/types/repository-rows.js`
8. `admin-service.js` 的核心读取映射函数参数，已开始明确依赖 repository 行模型
9. `order / task / inventory / webhook / order-item / task-inventory-binding` repository 已补第一批返回类型
10. backend `tsconfig.json` 已将上述 repository 纳入显式 `typecheck` 范围
11. `npm --prefix apps/backend run typecheck` 已在 repository 扩围后通过
12. 新增 `src/types/repository-inputs.js`
13. `order / task / inventory / webhook / order-item` repository 已开始显式使用共享输入类型
14. `npm --prefix apps/backend run typecheck` 已在输入类型接入后继续通过
15. 新增 `src/services/admin/admin-read-service.js`，开始承接后台查询型接口
16. `orders / tasks / inventory / webhook-events` 管理路由已优先切到 `admin-read-service`
17. 读服务首轮拆分后，backend `typecheck` 继续通过
18. 新增 `src/services/admin/admin-read-helpers.js`，开始承接读侧共享 helper
19. `admin-read-service.js` 已改为优先依赖 `admin-read-helpers.js`，不再直接依赖 `admin-service.js`
20. helper 下沉后，backend `typecheck` 继续通过
21. `admin-service.js` 已开始复用 `admin-read-helpers.js`，并删除首批重复的读侧 helper
22. `order / task / inventory / webhook` repository 已补共享查询参数类型
23. `npm --prefix apps/backend run typecheck` 已在查询参数类型接入后继续通过
24. 新增 `src/types/admin-read-inputs.js`，开始承接后台读接口的 service 入参边界
25. `admin-read-service.js` 的订单 / 任务 / 库存 / webhook 查询与详情入口已接入共享输入类型
26. `npm --prefix apps/backend run typecheck` 已在 service 输入类型接入后继续通过
27. 新增 `src/services/admin/admin-write-service.js`，开始承接后台库存写接口
28. `inventory` 管理路由已切到 `admin-write-service`，`admin-service.js` 删除首批库存写侧实现
29. 新增 `src/types/admin-write-inputs.js`，库存写接口已开始复用共享输入类型
30. backend `typecheck` 已覆盖 `admin-write-service.js`
31. 新增 `src/types/admin-write-models.js`，库存写接口返回结构已接入共享响应类型
32. `admin-write-service.js` 的 create / import / release / invalidate 已补返回值 JSDoc
33. `webhook replay` 与 `Agiso 店铺配置保存` 已下沉到 `admin-write-service.js`
34. `webhook-events / platform-config` 写路由已切到 `admin-write-service`
35. `admin-service.js` 删除第二批可独立的写侧实现，并保留兼容导出
36. `task` 生命周期写操作第一批已下沉到 `admin-write-service.js`
37. `tasks` 管理路由已切换首批 task 写接口到 `admin-write-service`
38. 新增 task 写侧共享响应类型，task action / binding release 已接入 JSDoc
39. `retryAdminTask` 与 `completeAdminTaskManualDispatch` 已下沉到 `admin-write-service.js`
40. `tasks` 管理路由已全部切到 `admin-write-service` 承接 task 写接口
41. `admin-service.js` 已删除 task 写侧主体实现，仅保留兼容导出
42. 新增 `admin-platform-config-service.js`，开始承接 platform-config 整块能力
43. `platform-config` 路由已切换到独立 service，不再经过 `admin-service.js`
44. `admin-service.js` 已删除平台配置相关读写与 helper，实现进一步收敛
45. 新增 `admin-dashboard-service.js`，后台概览已独立
46. 新增 `admin-message-delivery-service.js`，消息发送记录查询已独立
47. `dashboard / message-deliveries` 路由已直接依赖独立 service
48. `admin-service.js` 已收敛为兼容导出层，不再直接承载后台业务实现
49. 后台读 / 写 / 平台配置 / 概览 / 消息记录已分散到独立 service 模块
50. 新增 `src/types/admin-route-inputs.js`，开始承接 `admin` 路由层的 query / body / params 共享输入边界
51. `dashboard / inventory / orders / tasks / platform-config / message-deliveries / webhook-events` 路由已显式接入 `@ts-check` 与共享路由输入类型
52. `src/routes/admin/shared.js` 已补齐通用 handler 的请求 / 审计签名，`adminSession` 扩展请求字段进入路由层类型检查
53. 后台 `admin` 路由层首批已纳入 backend `typecheck` 范围，并验证通过
54. 新增 `src/services/admin/admin-read-shared-helpers.js`，开始承接 viewer / task context / 权限判定 / 订单展示等跨读写共享 helper
55. `admin-read-service / admin-write-service / admin-platform-config-service / admin-service` 已改为优先依赖共享 helper 模块，`admin-read-helpers.js` 职责继续收敛
56. `npm --prefix apps/backend run typecheck` 已在共享 helper 拆分后继续通过
57. 新增 `src/services/admin/admin-task-read-helpers.js`，开始承接任务映射、binding summary、任务动作 payload 与订单绑定汇总
58. `admin-read-service / admin-write-service / admin-service` 已将 task 相关 helper 改为直接依赖独立 task helper 模块
59. `admin-read-helpers.js` 已进一步收敛到 webhook / inventory / order-list 三类能力
60. `npm --prefix apps/backend run typecheck` 已在 task helper 拆分后继续通过
61. `admin-read-helpers.js` 已完成最终拆分，并删除过渡文件
62. 新增 `src/services/admin/admin-inventory-read-helpers.js`，库存读取映射与必需实体校验已独立
63. 新增 `src/services/admin/admin-order-read-helpers.js` 与 `src/services/admin/admin-webhook-read-helpers.js`，订单列表汇总与 webhook 事件映射已按领域独立
64. `admin-read-service / admin-write-service / admin-service` 已全部改为直接依赖 inventory / order / webhook / task / shared 五类 helper，读侧 helper 拆分阶段可以收口

这一步的设计原则是“只加静态约束，不动运行链路”，所以不会影响：

- `npm run dev`
- `npm run start`
- Docker 开发 / 部署

## 下一步建议

第一批继续推进时，建议按这个顺序：

1. 为 `admin` 路由层继续补响应模型与审计 payload 的共享类型，减少 `unknown` 到处就地断言
2. 继续补 repository / service 的边界约束，但不急着改 `.ts` 扩展名
3. 恢复并固定 `npm --prefix apps/backend run typecheck` 为日常校验步骤，确保本地与 CI 环境都能直接执行
4. 为 webhook、库存换码、自动发货补测试

## 执行原则

- 不为迁移而迁移，优先迁移最常改、最容易改坏的链路
- 不追求一口气全量改 `.ts`
- 优先建立“新代码进入类型系统”的机制
- 每一步都要求可回滚、可验证、不中断现有开发流
