Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

fix(api): query pagination accepts non-integer limit/page → fractional OFFSET/LIMIT

未关闭
#785 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

@Devesh36 已经在做这个了。

开始于 2026年9月21日。

  • #858 来自 @Devesh36 —— 已合并

评估

难度
3/5
预计耗时
1-2 天
新手友好度
76/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
typescript

调研方向

先从 apps/api/src/schemas/query-schemas.ts 和 apps/api/src/routes/query.ts 中的 DynamicQueryRequestSchema 和 validatePaginationFields 开始,然后检查 packages/ai/src/query/index.ts 中的 QuerySchema 以及 limit/offset 构建器。复现 issue 中描述的分数输入,并添加回归测试覆盖。完成的标准是:非有限或非整数的 limit/page 值收到预期的 400 验证响应,同时有效的分页仍能构建与整数兼容的子句。

由索引模型根据 Issue 内容生成。

描述

Describe the bug
POST /v1/query DynamicQueryRequest accepts non-integer limit/page without validation and produces fractional LIMIT/OFFSET that fail ClickHouse Int32 binding.

Affected code:

  • apps/api/src/schemas/query-schemas.ts:49-50 DynamicQueryRequestSchema: t.Optional(t.Number()) — no minimum/integer constraint.
  • apps/api/src/routes/query.ts:294-308 validatePaginationFields only checks <1 and >10000/<1 for page, not Number.isInteger/isFinite.
  • apps/api/src/routes/query.ts:1040-1041 limit: request.limit || 100, offset: request.page ? (request.page-1)*(request.limit||100) :0 → with limit=1.5, page=1.5 yields offset=0.75 (fractional).
  • packages/ai/src/query/simple-builder.ts:1148-1154 buildLimitClause/buildOffsetClause emit LIMIT 1.5 OFFSET 0.75 vs. builders LIMIT {limit:Int32} OFFSET {offset:Int32} (packages/ai/src/query/builders/pages.ts:182, sessions.ts:318, etc.).
  • Internal packages/ai/src/query/index.ts:61-62 QuerySchema: z.number().min(1).max(1000) also allows floats (missing .int()).

To Reproduce

  1. Authenticated request:
POST /v1/query?website_id=<id>&timezone=UTC
Content-Type: application/json
{
  "parameters": ["top_pages"],
  "startDate": "2026-01-01",
  "endDate": "2026-01-02",
  "limit": 1.5,
  "page": 1.5
}
  1. Also try {"limit": 0.5}, {"page": 1.5}, {"limit": 1.5, "page": 2.3}.

Expected behavior
400 VALIDATION_ERROR with details like:

{ "field":"limit", "message":"Limit must be an integer" }
{ "field":"page", "message":"Page must be an integer" }

limit/page should require finite integer, limit 1..10000, page 1...

Actual behavior
No validation error; request reaches ClickHouse with fractional values. Reproduced locally with copy of validatePaginationFields (D:\tmp\repro_pagination.js):

float limit {limit:1.5} => errors=[] limit=1.5 offset=0  BUG non-integer passed
float page {page:1.5} => errors=[] limit=100 offset=50  BUG
both float => offset 0.75 BUG not integer
Infinity/NaN similarly slip through (JSON NaN not encodable but Elysia coercion from query string can produce floats).

buildLimitClause(NaN) → '' (unbounded), buildLimitClause(0) → ''.

Screenshots
N/A

Environment

  • OS: Windows, Bun 1.4.2 (package.json:30 [email protected] pinned)
  • Commit: 92c15273d (origin/staging)

Additional context

  • limit default fallback || 100 masks 0/NaN in apps/api/src/routes/query.ts:1040, simple-builder.ts:1149 fallback similarly.
  • limit max mismatch: API allows 10000 (validatePaginationFields:301), internal QuerySchema allows 1000 — not part of this bug but worth aligning.
  • No existing open issue covers this (checked gh issue list).
  • Minimal fix proposal: tighten DynamicQueryRequestSchema (TypeBox minimum), add Number.isInteger/isFinite in validatePaginationFields, add .int() to QuerySchema (packages/ai/src/query/index.ts:61-62), add regression test.

AI disclosure
Issue drafted with assistance from Muse Spark (opencode/muse-spark-1.2-contributor-free) and human-verified via local reproduction (node D:\tmp\repro_pagination.js).

主要语言
TypeScript
星标
1.2k
派生
220
平均合并
12 小时 12 分钟
30 天内合并 PR
295

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

databuddy-analytics/Databuddy 的其他 Issue

查看 databuddy-analytics/Databuddy 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。