8.9 KiB
8.9 KiB
name, description
| name | description |
|---|---|
| sync-backend-api | Sync this Next.js frontend with backend API documentation |
sync-backend-api
根据后端文档同步当前 Next.js / TypeScript 项目的前端代码。
使用场景
当后端 API 新增、删除、字段结构调整、响应语义变化时,使用本 skill 更新:
- 网络层
- schema / 不可变纯数据
- repository
- storage
- XState store
- UI 调用逻辑
- mock 数据
- 单元测试
当前项目结构
| 层级 | 路径 | 说明 |
|---|---|---|
| API Path | src/data/services/api/api_path.ts |
统一维护接口路径 |
| API Service | src/data/services/api/*_api.ts |
调用 httpClient 并解析响应 |
| Schema Model | src/data/schemas/<module>/*.ts |
Zod schema 与不可变纯数据类型,负责解析和归一化 |
| Repository Interface | src/data/repositories/interfaces/i*_repository.ts |
仓库接口 |
| Repository | src/data/repositories/*_repository.ts |
业务仓库实现 |
| Storage | src/data/storage/* |
本地持久化 |
| Store | src/stores/<module>/* |
XState 状态机、actors、helpers、sync |
| UI | src/app/** |
Next.js app router UI |
| Mock | src/data/mock/<module>/** |
模拟请求 / 响应数据 |
| Tests | **/__tests__/*.test.ts |
schema model、helper、machine transition 测试 |
后端文档来源
优先读取用户指定的文档或文件片段。
常见文档:
FRONTEND_VIP_CREDIT_API.mdPAYWALL_API.mddocs-change.mddocs/backend/openapi.json
如果用户没有指定文档,先搜索相关 API 路径或模块名,再选择最相关文档。
更新流程
1. 检查工作区
开始前必须执行:
git status --short
如果存在无关未提交改动:
- 不要回退。
- 不要覆盖。
- 修改前先确认本次任务需要触碰的文件。
- 提交时只暂存本次任务相关文件。
2. 阅读后端文档
确认:
- API method
- API path
- 请求参数
- 响应结构
- 字段是否可空
- 旧字段是否废弃
- 是否需要认证 token
- 是否影响本地持久化
- 是否影响状态机或 UI
如果用户明确要求“不兼容旧字段,彻底更新”,不要保留旧字段 fallback。
否则 schema 应尽量防御性解析,例如:
z.string()
.nullable()
.transform((v) => v ?? "")
.default("");
项目已有通用 helper:
src / data / schemas / nullable - defaults.ts;
3. 更新 API Path
新增或修改:
src / data / services / api / api_path.ts;
示例:
static readonly userEntitlements = `${ApiPath._user}/entitlements`;
4. 更新 Schema Model
在对应模块下新增或修改:
src/data/schemas/<module>/*.ts
要求:
- 使用 Zod。
- 输出类型用
z.output<typeof Schema>。 - 输入类型用
z.input<typeof Schema>。 - 对后端可能返回
null的字段做防御性处理。 - 不要在 schema 中写 UI 逻辑。
- Schema 输出必须是纯数据,不要定义 class 或工厂对象。
- 对象 Schema 使用
.readonly();已知嵌套对象、数组和 Record 也必须逐层 readonly。 - transform 应先完成归一化,再在最终输出应用
.readonly()。 - 容器默认值必须经过 Schema 解析;使用
prefault或在最外层应用 readonly,不能让.default()返回未冻结对象。 - 后端返回但前端既不读取、也不透传的字段,不要加入 Schema。
- 仅用于请求序列化、响应兼容或内部透传的字段直接保留在 Schema 中。
- 统一使用
XxxSchema.parse()构造请求与解析响应,不增加from()、fromJson()或toJson()包装。 - 不要再创建独立的数据传输对象层。
示例:
export const XxxResponseSchema = z
.object({
id: z.string(),
tags: z
.array(z.string())
.default(() => [])
.readonly(),
count: z.number().default(0),
})
.readonly();
export type XxxResponseInput = z.input<typeof XxxResponseSchema>;
export type XxxResponseData = z.output<typeof XxxResponseSchema>;
export type XxxResponse = XxxResponseData;
5. 更新 API Service
修改:
src/data/services/api/<module>_api.ts
统一调用方式:
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.xxx, {
method: "POST",
body: request,
});
return XxxResponseSchema.parse(unwrap(env));
注意:
- 不要直接返回
unknown。 - 不要在 API 层处理 UI 行为。
- multipart 仍使用
FormData。
6. 更新 Repository
修改:
src/data/repositories/interfaces/i<module>_repository.ts
src/data/repositories/<module>_repository.ts
Repository 返回项目通用 Result<T>:
async getXxx(): Promise<Result<XxxResponse>> {
return Result.wrap(() => this.api.getXxx());
}
Repository 可以做轻量编排,例如:
- request schema 解析
- 多接口组合
- 本地 storage 同步
- 本地模型与接口模型转换
不要把 React / UI 逻辑放进 repository。
7. 更新 Storage
如果接口影响本地持久化,修改:
src/data/storage/storage_keys.ts
src/data/storage/<module>/*
原则:
- 只持久化业务需要的最小字段。
- 不要为了接口响应完整而盲目存完整 payload。
- storage 使用
SpAsyncUtil和 Zod schema 校验。
示例:
getEntitlementSnapshot(): Promise<Result<UserEntitlementSnapshotData | null>> {
return SpAsyncUtil.getJson(
StorageKeys.userEntitlementSnapshot,
UserEntitlementSnapshotSchema,
);
}
8. 更新 Store / 状态机
如果接口影响状态流,修改:
src/stores/<module>/<module>-state.ts
src/stores/<module>/<module>-events.ts
src/stores/<module>/<module>-machine.ts
src/stores/<module>/<module>-machine.actors.ts
src/stores/<module>/<module>-machine.helpers.ts
src/stores/<module>/<module>-context.tsx
src/stores/<module>/*-sync.tsx
项目约定:
- API 调用放在
actors.ts。 - 纯函数转换放在
helpers.ts。 - 跨 store 监听放在
*-sync.tsx。 - 页面组件不承担全局监听职责。
- 状态机事件应表达业务事实,而不是 UI 操作细节。
9. 更新 UI
只有在接口变更影响展示或用户明确要求时,才修改:
src/app/**
原则:
- UI 只负责渲染和派发事件。
- 不在页面组件里直接写复杂业务编排。
- 全局监听逻辑优先放到
stores/*/*-sync.tsx。
10. 更新桶文件
如果新增 schema model 或 component,更新对应 index.ts:
src/data/schemas/<module>/index.ts
src/app/**/components/index.ts
如果项目使用 barrelsby 生成,不要手动破坏现有导出格式。
11. 更新 Mock 数据
如果新增或调整数据结构,按一个结构一个文件的原则放到:
src/data/mock/<module>/requests
src/data/mock/<module>/responses
src/data/mock/<module>/websocket-events
不要把多个结构塞进一个大 JSON。
12. 更新测试
优先补充:
- schema model 解析与序列化测试
- helper 纯函数测试
- XState transition 测试
- repository 编排测试(如已有测试基础)
常见位置:
src/data/schemas/<module>/__tests__/*.test.ts
src/stores/<module>/__tests__/*.test.ts
13. 验证
至少运行:
pnpm exec tsc --noEmit
pnpm exec eslint <changed files>
pnpm exec vitest run <related tests>
如果没有相关测试,需要说明未覆盖的风险。
常见任务模板
新增接口
- 文档确认 path / method / payload。
api_path.ts新增路径。- 在同一文件新增 readonly schema 与输入/输出类型。
- API service 新增方法。
- repository interface + implementation 新增方法。
- 如需要,接入 store actor / event。
- 补 mock 和测试。
- 运行验证。
修改响应字段
- 更新 schema。
- 更新同文件输入/输出类型及相关 parse 调用。
- 更新 mapper/helper。
- 更新 UI 或状态机依赖字段。
- 更新 mock 和测试。
- 运行验证。
删除旧接口
- 搜索所有引用。
- 删除 API path / API method / repository method。
- 删除 schema model、mock 和测试。
- 更新状态机和 UI 调用。
- 运行
rg确认无残留引用。 - 运行验证。