feat(search): extend document search to content + add time range and sort filters (#68) - #69
Conversation
…sort filters (bytefolk#68) - Internal GET /api/doc and API v1 GET /api/v1/documents now search both title and content (OR) instead of title-only - Add after/before query params for updatedAt range filtering - Add sort query param (updated_desc|updated_asc|created_desc|created_asc) - No schema migration needed — uses Prisma OR + contains
PeterGuy326
left a comment
There was a problem hiding this comment.
REQUEST CHANGES\n\n当前 head 需要先修复以下阻断和契约不一致:\n\n1. 构建不通过。src/lib/api-v1-documents.ts:143-154 的 getOrderBy 返回 readonly tuple,src/lib/api-v1-documents.ts:241 传给 Prisma orderBy 时触发 TS2322。已在本地 npx tsc --noEmit 复现;GitHub CI 的 docker-build 也因同一错误失败。请返回可赋给 Prisma orderBy 的可变数组类型,并补充构建验证。\n\n2. 搜索大小写行为不一致。src/app/api/doc/route.ts:240-242 的 title 条件没有 mode: insensitive,但 content 条件有;v1 入口两者都有。内部 GET /api/doc 的标题搜索因此大小写敏感,请统一。\n\n3. 参数校验行为不一致。src/app/api/doc/route.ts:216-247 对非法 after/before 生成 Invalid Date 后静默省略条件,:250-256 对非法 sort 静默回退 updated_desc;v1 入口对两者都返回 400 invalid_query。两个入口应共享解析/校验逻辑,并补充内部 route 的 400 回归测试。\n\n4. created_* 排序和游标分页不匹配。src/lib/api-v1-documents.ts:63-66、225-255 的 cursor 只保存/比较 updatedAt + id,但 getOrderBy 已允许按 createdAt 排序。使用 created_asc 或 created_desc 翻第二页时仍按 updatedAt 过滤,可能重复或漏项。请让 cursor 带 sort 相关字段并使用对应比较条件,或暂时禁止这些 sort 的 cursor 分页,并补充第二页测试。\n\n5. 两套路由仍各自维护 where/orderBy 构建:src/app/api/doc/route.ts:210-271 与 src/lib/api-v1-documents.ts:192-243。当前差异已经造成上述搜索和校验不一致,建议抽取共享的 query parser、where builder 和 orderBy builder。\n\n验证:PR head db8ecb8 已在本地核对;v1 service 15 tests 与 v1 route 6 tests 通过,npx tsc --noEmit 失败并复现上述 TS2322。GitHub CI 的 test 312 tests 通过,但 docker-build 失败。PR 描述中的内部搜索、时间范围、sort 手工验证仍未完成,本次 diff 也没有 CHANGELOG.md 的 [Unreleased] 条目。修复并补齐验证后请通知复审。
…or pagination - Extract shared doc-query.ts module for query parsing and where/orderBy builders - Fix getOrderBy to return mutable array (TS2322 build failure) - Add mode: insensitive to /api/doc title search for consistency with v1 - Return 400 for invalid date/sort params instead of silently ignoring - Disable cursor pagination for created_* sort orders (cursor is updatedAt-based) - Unify search/date/sort logic between /api/doc and /api/v1/documents
PeterGuy326
left a comment
There was a problem hiding this comment.
复核当前 head c013bfd:此前列出的查询逻辑、校验、大小写搜索和 created_* 游标问题已按当前 diff 处理;当前真正阻断的是 CI 的 test job:npm run format 只报 src/lib/doc-query.ts 需要 Prettier 格式化。我在隔离工作树复现了同一格式告警,格式化后仅有该文件的排版变化;但无法直接推送到作者 fork,请运行 npx prettier --write src/lib/doc-query.ts 后提交并 request re-review。另请补齐 CHANGELOG.md [Unreleased] 条目和内部搜索/时间范围/sort 的手工验证记录。
waterbro-8
left a comment
There was a problem hiding this comment.
Review
CI: test failed on npm run format — Prettier wants src/lib/doc-query.ts rewritten. docker-build passed.
Must fix
- Run
npx prettier --write src/lib/doc-query.ts(ornpm run format:fix) and push. CI dies before tests.
Scope (ok if documented)
- This is Phase 2 of #68 (title OR content
contains,after/before/sort), not tsvector /matchField. That follow-up is #71. Please do not close #68 as fully done, or split the issue. - Searching TipTap JSON with
containswill miss some body hits and can match markup. Fine as the no-migration path; say so in the API docs (docs/API.mdis unchanged).
Nice
- Rejecting
created_*sort with cursor pagination is the right fail-closed choice. - Invalid date/sort tests are present.
Verdict: request changes until format CI is green. After that this is a reasonable Phase-2 merge.
|
Changes pushed: Prettier format fixed, CHANGELOG entry added, CI green. Ready for re-review. |
waterbro-8
left a comment
There was a problem hiding this comment.
Re-review
Previous blockers are addressed on the current head:
getOrderByreturns a mutable Prisma array- title and content search both use
mode: insensitive - invalid
after/before/sortreturn 400 via shareddoc-query.ts created_*+ cursor is fail-closed (400)- Prettier on
doc-query.tsis clean - CHANGELOG
[Unreleased]is present - CI (test + docker-build) is green
Residual (non-blocking)
/api/doc400 paths are not covered by tests (only v1listApiDocumentsis). Worth one invalid-sort/date case on the internal route.after > beforeis not rejected.- TipTap JSON
containswill miss some body hits and can match markup. Acceptable as the no-migration Phase 2 path; keep full-text /matchFieldon #71. Do not close #68 as fully done unless Phase 3 is explicitly dropped. - Host-app API docs are a separate follow-up (#77).
Verdict: approve as Phase 2 of #68.
PeterGuy326
left a comment
There was a problem hiding this comment.
Reviewed current head f3ed1c3.
- Required CI is green; Prettier format and TypeScript checks pass.
- Focused API/document-route tests pass (21 tests).
- Shared query parsing covers title/content search, date bounds, sort validation, and invalid-input 400 responses; current diff has no remaining blocking finding.
- Existing CODEOWNER approval is present; the remaining merge blocker is the repository's expected CodeQL (javascript-typescript) context on fork PRs.
Summary
Closes #68 (Phase 1 + Phase 2).
GET /api/doc?keyword=XandGET /api/v1/documents?query=Xnow search bothtitleANDcontent(OR), not just title. Uses PrismaOR+containswithmode: 'insensitive'— no schema migration needed.afterandbeforequery params filter byupdatedAt(ISO 8601 dates). Invalid dates return 400.sortquery param acceptsupdated_desc(default),updated_asc,created_desc,created_asc. Invalid values return 400.doc-query.tswith sharedparseOptionalDate,parseSort,buildSearchWhere,buildDateWhere,getOrderByhelpers used by both routes.Changes
src/lib/doc-query.tssrc/lib/api-v1-documents.tscreated_*sortssrc/app/api/doc/route.tssrc/__tests__/lib/api-v1-documents.test.tsAPI contract
GET /api/v1/documents(new query params)queryafterupdatedAt > after(400 if invalid)beforeupdatedAt < before(400 if invalid)sortupdated_descupdated_desc,updated_asc,created_desc,created_asc(400 if invalid)GET /api/doc(new query params)keywordafterupdatedAt > after(400 if invalid)beforeupdatedAt < before(400 if invalid)sortupdated_descTest plan
npx vitest run— 333 tests pass (5 new)npx tsc --noEmit— no TypeScript errorsafter/before/sortparams via API v1 with a PATOut of scope (Phase 3+)
created_*sorts — currently returns 400 if cursor is provided with these sorts