Fix filter AST array format incompatibility with query engine#800
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
- Add parseFilterAST() to packages/spec/src/data/filter.zod.ts that
converts array AST format (e.g. ["and", ["field", "=", "val"]]) to
FilterCondition object format (e.g. { $and: [{ field: "val" }] })
- Fix protocol.ts findData to convert AST arrays after JSON.parse
- Fix http-dispatcher.ts to pass query params as { query } not { filters }
- Update broker shims to handle new param format
- Add 27 tests for parseFilterAST covering all operators and edge cases
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
|
@copilot 仔细检查确认已经完成任务要求的所有开发内容 |
已全部完成并验证,以下为变更清单:
全部 6412 条测试通过,无回归。完整链路已验证:浏览器 AST 数组 → Dispatcher → |
There was a problem hiding this comment.
Pull request overview
Fixes server-side filter handling so JSON array AST filters from clients are converted into FilterCondition objects that the query engine understands, and corrects dispatcher param shape so query params reach findData.
Changes:
- Added
parseFilterAST()to convert array-based filter AST intoFilterConditionobject format (with tests). - Updated protocol
findDatapath to convert parsed array filters viaparseFilterAST(). - Fixed HTTP dispatcher and broker shims/tests to pass
{ query }instead of{ filters: query }.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/spec/src/data/filter.zod.ts | Adds AST→FilterCondition conversion utility used by server-side query handling. |
| packages/spec/src/data/filter.test.ts | Adds unit tests validating AST conversion and schema compatibility. |
| packages/objectql/src/protocol.ts | Applies AST conversion after JSON.parse when filter is an array. |
| packages/runtime/src/http-dispatcher.ts | Fixes broker call param shape to forward query params correctly. |
| packages/client/src/client.msw.test.ts | Updates MSW broker shim tests to read filters from params.query. |
| apps/studio/src/mocks/createKernel.ts | Updates studio broker shim to accept new { query } shape (fallback to legacy). |
| */ | ||
| export function parseFilterAST(filter: unknown): FilterCondition | undefined { | ||
| if (filter == null) return undefined; | ||
| if (!Array.isArray(filter)) return filter as FilterCondition; |
There was a problem hiding this comment.
parseFilterAST currently “passes through” any non-array input by casting to FilterCondition. That includes primitives (e.g., a string/number/boolean) which would silently become an invalid FilterCondition at runtime. Consider only passing through when typeof filter === 'object' (and not null), otherwise return undefined (or throw) to avoid propagating invalid filters.
| if (!Array.isArray(filter)) return filter as FilterCondition; | |
| if (!Array.isArray(filter)) { | |
| if (typeof filter === 'object') { | |
| return filter as FilterCondition; | |
| } | |
| return undefined; | |
| } |
| } | ||
|
|
||
| // Comparison node: [field, operator, value] | ||
| if (filter.length >= 2 && typeof first === 'string') { |
There was a problem hiding this comment.
This branch will treat any array with at least 2 elements as a comparison node, which can produce { field: { $op: undefined } } when the value is missing (e.g. ["age", ">"]) and also doesn’t ensure the operator is a string. Tighten the shape check (e.g., require filter.length === 3 and typeof filter[1] === 'string'), while still allowing unary operators like is_null / is_not_null if you intend to support [field, op] forms.
| if (filter.length >= 2 && typeof first === 'string') { | |
| if (filter.length === 3 && typeof first === 'string' && typeof filter[1] === 'string') { |
| 'is_null': '$null', | ||
| 'is_not_null': '$null', |
There was a problem hiding this comment.
is_null / is_not_null are mapped in AST_OPERATOR_MAP, but convertComparison handles both via special-cases and never uses these mappings. Removing these entries would reduce confusion about whether $null should receive a boolean vs. the raw AST value.
| 'is_null': '$null', | |
| 'is_not_null': '$null', |
| const children = filter.slice(1).map((child: unknown) => parseFilterAST(child)).filter(Boolean) as FilterCondition[]; | ||
| if (children.length === 0) return undefined; |
There was a problem hiding this comment.
Using .filter(Boolean) for narrowing works here but is a bit opaque and relies on truthiness. A typed predicate (e.g., filtering only undefined results from parseFilterAST) is clearer and keeps TypeScript inference safer if the return type later changes.
| if (!all) all = []; | ||
|
|
||
| const filters = params.filters; | ||
| const filters = params.query || params.filters; |
There was a problem hiding this comment.
filters now holds either the entire query object or the legacy filters value, so the name is misleading (it’s no longer necessarily just filters). Renaming to something like queryParams (and then extracting filters/filter from it explicitly) would make the subsequent logic easier to follow.
Client sends filters as JSON array AST (
["and", ["priority", "=", "high"], ["status", "=", "active"]]), but the query engine expects FilterCondition objects ({ $and: [{ priority: "high" }, { status: "active" }] }). Two bugs: (1) no AST→object conversion afterJSON.parse, (2) dispatcher passes{ filters: query }instead of{ query }, sofindDatanever sees the params.Changes
packages/spec/src/data/filter.zod.ts— AddparseFilterAST()utility that converts array AST to FilterCondition objects. Supports all comparison operators (=,!=,>,>=,<,<=,in,not_in,contains,like,between,is_null,is_not_null) and logical combinators (and,or). Passthrough for inputs already in object format.packages/objectql/src/protocol.ts— CallparseFilterAST()after JSON.parse infindDatawhen the parsed filter is an array.packages/runtime/src/http-dispatcher.ts— Fix param shape from{ object, filters: query }→{ object, query }so protocol receives query params atrequest.queryas expected.Broker shims (
apps/studio,packages/client) — Updated to handle corrected param format.Example
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.