feat(orm): implement $is sub-model filter for delegate base models#2559
feat(orm): implement $is sub-model filter for delegate base models#2559motopods wants to merge 12 commits intozenstackhq:devfrom
Conversation
…hic) models Agent-Logs-Url: https://github.com/motopods/zenstack/sessions/678a87a1-1e67-44f9-95ee-e77f3d5e81cc Co-authored-by: motopods <58200641+motopods@users.noreply.github.com>
Agent-Logs-Url: https://github.com/motopods/zenstack/sessions/678a87a1-1e67-44f9-95ee-e77f3d5e81cc Co-authored-by: motopods <58200641+motopods@users.noreply.github.com>
…-content feat(orm): implement discriminated union return types for delegate (polymorphic) models
…egate (polymorphic) models"
…rence-for-content Revert "feat(orm): implement discriminated union return types for delegate (polymorphic) models"
📝 WalkthroughWalkthroughAdds a Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@ymc9 Hi, what about you think of this? |
|
This is very interesting. It may be better to use the lowercase-first name of the model ( Also, await client.asset.findMany({
where: { $is: { video: true } },
}); |
|
@sanny-io You make a lot of sense. |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/orm/src/client/crud/dialects/base-dialect.ts`:
- Around line 367-382: The EXISTS subquery is built manually (using tmpAlias,
selectFrom and this.eb.exists) which bypasses delegate-aware helpers and causes
inherited-delegate filters from this.buildFilter to reference outer tables
incorrectly; replace the manual existsSubquery construction with the
dialect-aware helper (use the existing buildExistsExpression /
buildDelegateQueryHelpers pathway) so the subquery is created via the same
delegate-aware query builder, passing subModelName, subAlias, joinConditions and
subWhere (or subWhereFilter) into that helper instead of calling
this.eb.selectFrom directly; ensure the final condition still uses
discriminatorCheck and the helper-produced exists expression (instead of
this.eb.exists(existsSubquery)) so dialect-specific EXISTS workarounds and
proper alias joins are preserved.
In `@packages/orm/src/client/zod/factory.ts`:
- Around line 490-503: The $is filter currently uses z.object(...) which strips
unknown sub-model keys and hides typos; update the construction of
subModelSchema to use z.strictObject(...) instead (i.e. replace z.object(...)
with z.strictObject(...)) so unknown sub-model names will be rejected at
validation time; keep the same Object.fromEntries mapping of subModel names and
the existing union that references this.makeWhereSchema, and preserve the
.optional() on subModelSchema before assigning it to fields['$is'].
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a7ffa087-26a0-464d-9e91-d1bac09d8a0b
📒 Files selected for processing (4)
packages/orm/src/client/crud-types.tspackages/orm/src/client/crud/dialects/base-dialect.tspackages/orm/src/client/zod/factory.tstests/e2e/orm/client-api/delegate.test.ts
inherited from a delegate base model (e.g. `viewCount` on `Asset`
accessed via `$is: { video: { viewCount: ... } }`), including:
- single inherited-field filter
- mixed inherited + own-field filter
- inherited-field filter returning no rows
- nested delegate level (Video → RatedVideo) with inherited field
Adds support for the
$isfilter operator on delegate (polymorphic) base modelwhereclauses, enabling queries that filter by sub-model-specific fields.What's new
When querying from a delegate base model, use
$isto filter by sub-model type and/or sub-model-specific fields. Multiple sub-model entries are combined with OR semantics.EXISTS (SELECT 1 FROM <submodel> WHERE id = <base>.id AND <discriminator> AND <sub-fields>)SQL, ensuring correct row-level scoping.WhereInput—$SubModelWhereInputtypes are generated incrud-types.tsso TypeScript enforces valid sub-model fields at compile time.zod/factory.tsvalidates$ispayloads at runtime, giving clear error messages for unknown sub-models or invalid field shapes.Files changed
packages/orm/src/client/crud-types.ts$SubModelWhereInputand wired$isintoWhereInputpackages/orm/src/client/crud/dialects/base-dialect.tsbuildIsFilterto emit correlated EXISTS subqueriespackages/orm/src/client/zod/factory.ts$ispayloadstests/e2e/orm/client-api/delegate.test.ts$isfilteringClose #1740
Summary by CodeRabbit
New Features
$isfilter for delegate (polymorphic) base models to filter by sub-model type, including nested$isconditions, OR-combined multi-sub-model queries, and correlated-subquery semantics for inherited/base fields. Input validation now recognizes$isin where/filter schemas.Tests
$isbehavior across base models, nested$ispaths, nested predicates, and multi-sub-model queries.