feat(api): cn-app skeleton, toolchain, env loading convention
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -286,7 +286,7 @@ export interface OutboxEvent<T = unknown> {
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 单测**:类型测试——合法 `OutboxEvent{type:'photo.published'}` 编译通过,非法 type 用 `@ts-expect-error` 验证编译期拒绝;**枚举同步测试**(Task 4 审查遗留):断言 `ErrorCode` 与 `components['schemas']['Error']['code']` 的 enum 双向可赋值。
|
||||
- [x] **Step 2: 单测**:类型测试——合法 `OutboxEvent{type:'photo.published'}` 编译通过,非法 type 用 `@ts-expect-error` 验证编译期拒绝;**枚举同步测试**(Task 4 审查遗留):断言 `ErrorCode` 与 `components['schemas']['Error']['code']` 的 enum 双向可赋值。(完成:8/8 通过,两护栏经变异验证真实生效)
|
||||
|
||||
```bash
|
||||
pnpm --filter @photo/contracts test
|
||||
@@ -294,8 +294,8 @@ pnpm --filter @photo/contracts test
|
||||
|
||||
Expected: PASS。
|
||||
|
||||
- [ ] **Step 3: ⏸ 用户确认点:请用户过目 openapi.yaml(接口形态、字段命名、分页方式)后再进入 M2。**
|
||||
- [ ] **Step 4: Commit** `feat(contracts): outbox event contract types`
|
||||
- [x] **Step 3: ⏸ 用户确认点:请用户过目 openapi.yaml(接口形态、字段命名、分页方式)后再进入 M2。**(完成:用户于 2026-09-17 确认"确认,继续 M2")
|
||||
- [x] **Step 4: Commit** `feat(contracts): outbox event contract types`(完成:f77ab5a)
|
||||
|
||||
---
|
||||
|
||||
@@ -306,10 +306,10 @@ Expected: PASS。
|
||||
**Files:**
|
||||
- Create: `services/api/package.json`(name `@photo/api-cn`)、`tsconfig.json`、`nest-cli.json`、`src/main-cn.ts`、`src/app-cn.module.ts`、`src/health.controller.ts`、`src/request-id.middleware.ts`、`src/all-exceptions.filter.ts`、`services/api/jest.config.ts`、`services/api/test/load-env.ts`、`services/api/test/reset.ts`、根 `eslint.config.js`
|
||||
|
||||
- [ ] **Step 1: env 加载约定(全仓库唯一机制,解决 pnpm --filter cwd 在包目录的问题)**:根 `.env` 为唯一 env 文件。开发/迁移脚本经根 `dotenv-cli` 注入(Task 2 scripts 已配置);Jest 经 `services/api/test/load-env.ts`(`dotenv.config({ path: join(__dirname, '../../../.env') })`)作为 `setupFiles` 载入;运行时代码只读 `process.env`。
|
||||
- [ ] **Step 2: 依赖与入口**:deps `@nestjs/common @nestjs/core @nestjs/platform-express nest-pino pino-http`;devDeps `jest ts-jest @types/jest supertest @types/supertest @nestjs/testing`;scripts:`test`(`*.spec.ts` 单测)、`test:e2e`(`test/*.e2e-spec.ts`,前置 compose 依赖)、`typecheck`、`lint`、`start`。`test/reset.ts` 为 e2e 共用隔离工具:每个 e2e spec `beforeAll` 调用——truncate 全部 cn 表 + 删除 MinIO `photo-live/dev` 前缀对象(防止 spec 间唯一约束冲突与脏数据)。入口监听 `PORT`(默认 8080),`app.setGlobalPrefix('v1')`,注册 request-id 中间件(无则生成 cuid,挂 `res.setHeader('x-request-id')`)、全局异常过滤器(映射 `ErrorCodes`,响应 `{code,message,requestId}`,不泄露堆栈)、`/v1/health` 返回 `{status:'ok'}`。
|
||||
- [ ] **Step 3: 根 ESLint flat config**(eslint + typescript-eslint,覆盖 packages/services/apps),各包(contracts、storage、db-cn、api、worker)`lint` 脚本接 `eslint .`,确保 turbo 不静默跳过。ts-jest 保持类型检查模式(非 isolatedModules),使 `@ts-expect-error` 负向断言生效。
|
||||
- [ ] **Step 4: 启动验证**
|
||||
- [x] **Step 1: env 加载约定(全仓库唯一机制,解决 pnpm --filter cwd 在包目录的问题)**:根 `.env` 为唯一 env 文件。开发/迁移脚本经根 `dotenv-cli` 注入(Task 2 scripts 已配置);Jest 经 `services/api/test/load-env.ts`(`dotenv.config({ path: join(__dirname, '../../../.env') })`)作为 `setupFiles` 载入;运行时代码只读 `process.env`。(完成:2026-09-17)
|
||||
- [x] **Step 2: 依赖与入口**:deps `@nestjs/common @nestjs/core @nestjs/platform-express nest-pino pino-http`(实际:`nest-pino` 上游已更名 `nestjs-pino`,取 ^4.6.1 兼容 Nest 10);devDeps `jest ts-jest @types/jest supertest @types/supertest @nestjs/testing`;scripts:`test`(`*.spec.ts` 单测)、`test:e2e`(`test/*.e2e-spec.ts`,前置 compose 依赖)、`typecheck`、`lint`、`start`。`test/reset.ts` 为 e2e 共用隔离工具:每个 e2e spec `beforeAll` 调用——truncate 全部 cn 表 + 删除 MinIO `photo-live/dev` 前缀对象(防止 spec 间唯一约束冲突与脏数据)。入口监听 `PORT`(默认 8080),`app.setGlobalPrefix('v1')`,注册 request-id 中间件(无则生成 cuid,挂 `res.setHeader('x-request-id')`)、全局异常过滤器(映射 `ErrorCodes`,响应 `{code,message,requestId}`,不泄露堆栈)、`/v1/health` 返回 `{status:'ok'}`。
|
||||
- [x] **Step 3: 根 ESLint flat config**(eslint + typescript-eslint,覆盖 packages/services/apps),各包(contracts、storage、db-cn、api、worker)`lint` 脚本接 `eslint .`,确保 turbo 不静默跳过。ts-jest 保持类型检查模式(非 isolatedModules),使 `@ts-expect-error` 负向断言生效。(完成:contracts 与 api 已接入,storage/db-cn/worker 待各自任务建包时接入)
|
||||
- [x] **Step 4: 启动验证**(完成:curl -i 见 x-request-id 响应头;单测 6/6、e2e 3/3、根 lint/typecheck/test/build/e2e 全绿)
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
@@ -318,7 +318,7 @@ pnpm dev:api &
|
||||
until curl -s localhost:8080/v1/health; do sleep 1; done # 等待启动 → {"status":"ok"}
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Commit** `feat(api): cn-app skeleton, toolchain, env loading convention`
|
||||
- [x] **Step 5: Commit** `feat(api): cn-app skeleton, toolchain, env loading convention`
|
||||
|
||||
### Task 8: Prisma cn schema —— 身份与审计域
|
||||
|
||||
|
||||
Reference in New Issue
Block a user