fix(view,components): the spec→FilterBuilder operator table covers the whole view vocabulary (#2945) - #2989
Merged
Conversation
…e whole view vocabulary (#2945) `SPEC_TO_BUILDER_OP` resolved 10 of the spec's 19 canonical `VIEW_FILTER_OPERATORS`. The nine it missed — not_equals, starts_with, ends_with, greater_than, less_than, greater_than_or_equal, less_than_or_equal, is_null, is_not_null — are all canonical members a stored view legitimately carries, and each reached the FilterBuilder as a raw spelling its dropdown cannot select. Same defect and cause as #2974, one table over: spellings enumerated by hand. Now derived from the spec's own canonical list and VIEW_FILTER_OPERATOR_ALIASES, matched case- and separator-insensitively. Four canonical operators have no FilterBuilder equivalent and are recorded as asserted `null`s rather than folded onto a near-equivalent, which would rewrite the author's operator on the next save. Also retires BUILDER_TO_SPEC_OP + toSpecFilter — the write direction, dead since the studio's spec-driven inspector replaced buildViewConfigSchema, and objectui's last emitter of `'not in'`, `before` and `after` as filter-AST operators (objectstack-ai/objectstack#3948). @object-ui/components now exports FILTER_BUILDER_OPERATORS so tables that map onto that vocabulary assert against it instead of restating it. Refs #2945, #2901 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This was referenced Jul 30, 2026
Closed
os-zhuang
added a commit
that referenced
this pull request
Jul 30, 2026
…added (#3022) CANONICAL_TO_BUILDER mapped starts_with, ends_with, is_null and is_not_null to null, with a comment asserting the FilterBuilder had no such operator. #2942 gave it startsWith/endsWith/isNull/isNotNull and this table did not follow — so a stored view carrying any of the four still reached the builder as a raw spelling it could by then have rendered, and the comment was false. is_null/is_not_null map to isNull/isNotNull, NOT isEmpty/isNotEmpty: the builder draws both pairs now, and folding the NULL predicate onto the empty-string one would rewrite the author's operator on the next save. The old guard could not catch this — it compared the unmapped set against a hand-kept gap list, and neither side moves when the BUILDER gains an operator. The new assertion is derived: starts_with and startsWith fold to the same key, so an unmapped canonical operator whose folded name matches a folded builder id is an omission by definition. Confirmed by reverting the four mappings, which reproduces the drift as four named failures. The unmapped set is now empty — all 19 canonical members translate. Refs #2945, #2942, #2989 Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Third of objectui's spec-operator translation tables. The other two were pinned to the spec in #2974; this one was still enumerating spellings by hand, and had missed nine.
The gap
view-config-utils'SPEC_TO_BUILDER_OPresolved 10 of the spec's 19 canonicalVIEW_FILTER_OPERATORS. Executed against the real spec:All nine are canonical —
ViewFilterRuleSchemavalidates a stored view against exactly this list — so each reached the FilterBuilder as a raw spelling its operator dropdown cannot select.Five have an exact FilterBuilder equivalent and were simply absent. The table is now derived from the spec's own canonical list plus
VIEW_FILTER_OPERATOR_ALIASES, matched case- and separator-insensitively, sonot_in/notIn/'not in'/NOT_INare one entry instead of four chances to miss one. That is what #2974 concluded formapOperator, for the same reason.The four that stay unmapped
starts_with/ends_withhave no FilterBuilder operator at all.is_null/is_not_nullare distinct from theis_empty/is_not_emptythe builder does have.They are recorded as explicit
nulls and asserted, not folded onto a near-equivalent — folding would silently rewrite the author's operator the next time the view was saved. Unmapped instead reaches the builder unchanged and shows as a condition row the author must complete: visible, and lossless until they touch it. Shrink that list by adding the operator to the FilterBuilder, never by aliasing it.Scope, stated plainly
toFilterGroup— the only caller of this table — is exported from@object-ui/plugin-viewbut has no caller inside this repo. So this is a public-API defect, not a live in-repo bug; the surfaces that translate operators today (ListView,data-objectstack,FilterConditionField,datasetFilterCondition) are unaffected. It is worth fixing because it is the last of the three tables #2901 identified, and because the guard is what keeps it fixed.Dead write direction, retired
BUILDER_TO_SPEC_OPandtoSpecFilterare deleted. Zero callers anywhere in the repo — not even a test — and neither is in@object-ui/plugin-view's public exports; they were left behind when the studio's spec-driven inspector replaced the legacybuildViewConfigSchemaengine.They matter because of what they emitted:
'not in'with a space, plusbeforeandafter, as filter-AST operators. Those are the three spellings objectstack-ai/objectstack#3948 names as its trigger, citing this file. With this deleted and #2974 merged, objectui no longer has a live path that emits them — so #3948's remaining exposure is the server-side silent-drop itself, not an objectui caller. (Frameworkmainhas since addedbefore/aftertoAST_OPERATOR_MAP, which removes the trigger but not the drop.)One source of truth for the builder vocabulary
@object-ui/componentsnow exportsFILTER_BUILDER_OPERATORSand theFilterBuilderOperatortype, derived from the operators the FilterBuilder actually renders. Tables mapping onto that vocabulary assert against it rather than restating it — the guard below fails if a mapping targets an operator the dropdown does not have.Guards
packages/plugin-view/src/config/__tests__/view-operator-builder-parity.test.ts, asserting in both directions:CANONICAL_TO_BUILDER's keys are exactlyVIEW_FILTER_OPERATORS(also enforced at compile time — theRecordis keyed byViewFilterOperator);FILTER_BUILDER_OPERATORS;=,!=,>=,nin,like) resolve;equals.Verification
plugin-view+components/custom: 69 pass across 4 files.@objectstack/spec-side facts re-derived by executing the published spec, not read from the audit.eslint: 0 errors in both packages.@object-ui/componentstype-check: clean.Refs #2945, #2901, objectstack-ai/objectstack#3948
🤖 Generated with Claude Code