feat: add mono photo APIs#1667
Conversation
Add character and person photo album endpoints for preview lists, paged lists, photo details, and photo comments. Wire subject photo schema and related photo comment fields into Drizzle, response/request schemas, image conversion, and comment creation/filtering. Add route coverage and refresh the generated OpenAPI snapshot.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #1667 +/- ##
==========================================
+ Coverage 55.98% 56.40% +0.41%
==========================================
Files 143 145 +2
Lines 6589 6686 +97
Branches 1462 1479 +17
==========================================
+ Hits 3689 3771 +82
- Misses 2200 2210 +10
- Partials 700 705 +5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Remove the spoiler query filter from character and person photo list APIs so clients can decide how to present spoiler photos from the returned state. Keep spoiler in the response model and update tests and OpenAPI snapshots to cover the client-controlled behavior.
Match the legacy character and person album pages by keeping photo lists ordered by photo id descending. Remove the public orderBy query parameter and the associated request enum schema to avoid exposing sorting choices that the old UI did not support.
trim21
left a comment
There was a problem hiding this comment.
Code Review
整体结构很好,新 photo endpoints 和现有 character/person comment 模式一致,测试覆盖也全面。以下是几个需要关注的问题:
1. lib/comment.ts — create 中查询 parent 改成了 select() 全列
原代码只 select 了 { id, state },PR 改成了 select() 拉全部列。建议保持最小列集,如果需要 relatedPhotoID,在 hasRelatedPhoto() 分支内单独查询或做类型收窄,避免 'relatedPhotoID' in parent 这种 runtime 检查。
2. lib/comment.ts — Object.assign(reply, { relatedPhotoID }) 绕过类型系统
Object.assign 绕过了 $inferInsert 的类型检查。虽然运行时能工作(hasRelatedPhoto() 保证了表有字段),但违反严格类型原则。建议在 hasRelatedPhoto() 分支内构造带 relatedPhotoID 的 insert 对象,或使用类型断言。
3. lib/comment.ts — if (relatedPhotoWhere) 永远为 true
Drizzle 的 op.and() 总是返回 truthy 值,这个 if 不会走 else。可以直接赋值 where = op.and(where, op.eq(...)) 去掉条件。
4. lib/comment.ts — photo type 魔数 1 和 2
create 中 op.eq(schema.chiiSubjectPhotos.type, 1) 和 type, 2 应该导入使用已定义的 MonoPhotoType.Character / MonoPhotoType.Person,而不是硬编码。
5. lib/person/photo.ts — MonoPhotoType 缺少 as const
export const MonoPhotoType = Object.freeze({
Character: 1,
Person: 2,
});没有 as const 会导致 MonoPhotoType 类型退化为 number。规范要求 Object.freeze({ ... } as const)。(注:项目中已有的 freeze 常量也有同样问题,可以另开 PR 批量修复)
6. lib/comment.ts — 'relatedPhotoID' in d runtime 检查不够类型安全
relatedPhotoID: 'relatedPhotoID' in d ? d.relatedPhotoID : undefined,用 in 检查如果后续有表新增同名字段但语义不同会错误匹配。建议用 this.hasRelatedPhoto() 做类型守卫。
7. lib/types/convert.ts — photo.type === 1 硬编码
同第 4 点,应该使用 MonoPhotoType.Character。当前代码如果新增 photo type 3 会默认走 'person' 分支。
8. lib/images.ts — baseMonoPhotoPath 缺少尾部 /
const baseMonoPhotoPath = `pic/photos`;其他 base path(如 basePersonImagePath = 'pic/crt/l')已包含子路径,baseMonoPhotoPath 需要拼接时再加 /,风格不一致。
Tighten mono photo type handling and comment photo linkage after review. Use a shared MonoPhotoType constant with literal types, keep imports explicit at call sites, simplify parent comment lookup control flow, and avoid defaulting unknown photo types to person images.
Move parent comment lookup into a small helper so the comment creation path stays readable while still selecting related photo metadata only for character and person comments.
Move mono photo DB type to image path type mapping into a small helper so response conversion remains focused on shaping the API payload.
Summary
Add a shared mono-photo helper around
chii_subject_photos, then wire character and person routes through the same list/detail/comment behavior. Photo comments reuse the existing comment service while carryingrelatedPhotoID, so regular comments and photo-scoped comments stay in the same storage model without duplicating comment logic.Scope
chii_subject_photosand related photo comment fieldsValidation
pnpm tscpnpm lint(passes with existing warning inlib/utils/index.ts:203)pnpm exec vitest run routes/index.test.ts -upnpm exec vitest run routes/private/routes/character.test.ts routes/private/routes/person.test.ts -t 'photos|person comments'git diff --checknpm run build