Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Dec 9, 2025

Summary by CodeRabbit

  • New Features

    • Enhanced typed JSON filtering with typedef-aware recursive field filters, richer per-field predicates, and new string/array JSON operations.
    • JSON path filtering now uses string path expressions.
  • Tests

    • Expanded e2e JSON filter tests for typed JSON, array/index paths, and null semantics.
  • Schema

    • Added optional Profile.tags (String[]) and Address.zip (String).
  • Chores

    • Updated better-sqlite3 to ^12.5.0.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings December 9, 2025 14:45
@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Implements typedef-aware typed-JSON filtering across the ORM: introduces generic TypedJson filter types and helpers, replaces JSON path arrays with string paths, updates validator schemas for typed JSON, adds requireTypeDef helper, and extends BaseCrudDialect plus Postgres/SQLite implementations for new string/array JSON predicates.

Changes

Cohort / File(s) Summary
Core Types & Filters
packages/orm/src/client/crud-types.ts
Replaced untyped TypedJsonFilter with TypedJsonFilter<Schema, TypeDefName, Array, Optional> and added typedef-aware helpers (TypedJsonTypedFilter, ArrayTypedJsonFilter, NonArrayTypedJsonFilter, TypedJsonFieldsFilter); renamed generics (ArrayFilterType) and changed JsonFilter.path from string[] to string; exported new typedef helpers (GetTypeDefFieldType, TypeDefFieldIsArray, TypeDefFieldIsOptional).
Dialect Base & JSON Builders
packages/orm/src/client/crud/dialects/base-dialect.ts
buildJsonFilter now accepts fieldDef and dispatches to plain vs typed JSON handlers; added helpers (buildPlainJsonFilter, buildTypedJsonFilter, buildTypedJsonArrayFilter, buildTypeJsonNonArrayFilter); expanded abstract API (buildJsonPathSelection, buildJsonStringFilter, buildJsonArrayFilter, buildJsonArrayExistsPredicate); integrated requireTypeDef.
Dialect Implementations
packages/orm/src/client/crud/dialects/postgresql.ts, packages/orm/src/client/crud/dialects/sqlite.ts
Updated buildJsonPathSelection signature to `(receiver, path: string
Validator & Schema Validation
packages/orm/src/client/crud/validator/index.ts
Renamed makePrimitiveSchemamakeScalarSchema; switched optional handling to nullish(); extended makeTypedJsonFilterSchema to accept an array flag and compose recursive typed-json/array/plain filters; adjusted array element schemas and JSON nullability rules.
Query Utilities
packages/orm/src/client/query-utils.ts
Added export function requireTypeDef(schema: SchemaDef, type: string) to fetch/validate type definitions and throw descriptive errors when missing.
Schema Types
packages/schema/src/schema.ts
Added GetTypeDefFieldType<Schema, TypeDef, Field> to resolve a typedef field's type.
Tests & Test Schemas
tests/e2e/orm/client-api/json-filter.test.ts, tests/e2e/orm/schemas/typed-json/schema.ts, tests/e2e/orm/schemas/typed-json/schema.zmodel
Tests switched JSON path notation from arrays to string paths (e.g., '$.field'), expanded null/typed-json cases, and added Profile.tags: String[]? and Address.zip: String?.
Workspace / Misc
pnpm-workspace.yaml, TODO.md
Bumped better-sqlite3 version range to ^12.5.0; marked JSON filtering as implemented in TODO.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Areas needing extra attention:
    • Type propagation across new TypedJsonFilter helpers and Array/Optional flag logic in crud-types.ts.
    • Consistency between BaseCrudDialect abstract methods and Postgres/SQLite implementations (SQL generation, json path semantics).
    • Validator recursion and union composition in makeTypedJsonFilterSchema.
    • Tests: ensure string path notation and new typed-json cases exercise runtime code paths.

Possibly related PRs

Poem

🐰
I hop through JSON paths with whiskers bright,
From $.name burrow to arrays tucked tight.
Typedefs guide my nibbling, field by field,
Dialects answer predicates that I yield.
Hooray — small hops make typed filters light! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(orm): typed-json filters' accurately summarizes the primary change: implementing typed JSON filtering capabilities across the ORM package.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/typed-json-filter

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link

claude bot commented Dec 9, 2025

Claude finished @ymc9's task —— View job


Pull Request Review

I've completed a comprehensive review of this typed JSON filters implementation. Here's my analysis:

Review Summary

  • Analyze core type definitions and changes
  • Review dialect implementations (PostgreSQL, SQLite)
  • Examine validator logic and safety
  • Check test coverage and quality
  • Assess performance implications
  • Look for security concerns
  • Provide final feedback and recommendations

Overall Assessment: ⚠️ Requires Attention

This is a solid implementation of typed JSON filtering with excellent type safety, comprehensive dialect support, and thorough test coverage. However, there's one critical issue that needs to be addressed.

🚨 Critical Issue

Validator Implementation Missing (validator/index.ts:702-705)

private makeTypeDefFilterSchema(_type: string, _optional: boolean) {
    // TODO: strong typed JSON filtering
    return z.never();
}

Impact: This makes typed JSON filters completely unusable in production as they'll be rejected by input validation.

Required Fix: The makeTypeDefFilterSchema method needs to be implemented to generate proper Zod schemas for typed JSON filters, similar to how makeTypedJsonFilterSchema is implemented but wasn't connected to the validator pipeline.

Strengths

Type Safety & API Design (crud-types.ts)

  • Excellent use of conditional types with proper array/object distinction
  • XOR types prevent mixing typed and untyped JSON filters
  • Recursive type handling for nested TypeDef structures
  • Clean separation between some/every/none (arrays) and is/isNot (objects)

Database Dialect Implementation

  • PostgreSQL: Robust JSON path queries using jsonb_path_query_first, proper array element iteration with jsonb_array_elements
  • SQLite: Good fallback handling using json_each, proper type detection in transformOutput
  • Both dialects handle edge cases like empty arrays and nested structures correctly

Test Coverage (json-filter.test.ts)

  • Comprehensive tests covering direct field filtering, nested objects, array operations
  • Tests both simple and complex scenarios including is/isNot and some/every/none
  • Edge case testing for nullable fields and mixed shallow/deep filtering

📊 Performance Considerations

Positive:

  • Efficient JSON path selection using database-native functions
  • Proper use of EXISTS predicates for array filtering
  • Good query optimization with appropriate indexing strategies

Watch Points:

  • Complex nested queries may impact performance on large datasets
  • Consider adding query plan analysis for complex typed JSON filters

🔒 Security Assessment

Good practices observed:

  • Proper SQL injection prevention through parameterized queries
  • Safe JSON path construction using database functions
  • Input validation framework is in place (though incomplete)

📋 Recommendations

  1. Immediate (Required):

    • Implement makeTypeDefFilterSchema in validator to enable typed JSON filters
    • Connect the existing makeTypedJsonFilterSchema logic to the validation pipeline
  2. Short-term:

    • Add performance tests for complex nested queries
    • Consider documenting query optimization strategies
    • Add validation tests specifically for typed JSON filters
  3. Long-term:

    • Monitor query performance on production workloads
    • Consider caching strategies for frequently used filter patterns

🎯 Verdict

This is high-quality code with excellent architecture and comprehensive testing. The only blocker is the unimplemented validator, which is straightforward to fix. Once the validator is implemented, this feature will provide significant value with strong type safety and good performance characteristics.

Recommendation: Approve after addressing the validator implementation.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive typed JSON filter support, enabling direct field-based filtering on JSON fields with type definitions. The implementation shifts from array-based path syntax to standard JSON path strings (e.g., '$.a.b' instead of ['a', 'b']) and introduces typed filters that support direct field access, nested filtering via is/isNot operators, and array operations (some/every/none).

Key Changes

  • JSON Path Syntax: Migrated from array-based paths ['a', 'b'] to JSON path strings '$.a.b', '$.x[1]'
  • Typed JSON Filters: Added direct field filtering for typed JSON fields with support for nested structures and array operations
  • Dialect-Specific Implementations: Enhanced SQLite and PostgreSQL dialects with typed JSON support including path selection, string filtering, and array predicate handling

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/e2e/orm/schemas/typed-json/schema.zmodel Added tags array and zip optional field to test schema for comprehensive typed JSON testing
tests/e2e/orm/schemas/typed-json/schema.ts Generated schema updates reflecting new test fields
tests/e2e/orm/client-api/json-filter.test.ts Converted path syntax from arrays to strings; added 216 lines of comprehensive typed JSON filter tests including null handling, nested filters, and array operations
pnpm-workspace.yaml Bumped better-sqlite3 to ^12.5.0 for Node 25.x compatibility
pnpm-lock.yaml Lockfile updates for better-sqlite3 dependency version bump
packages/schema/src/schema.ts Added GetTypeDefFieldType utility type for extracting field types from type definitions
packages/orm/src/client/query-utils.ts Added requireTypeDef utility function for safe type definition retrieval
packages/orm/src/client/crud/validator/index.ts Implemented makeTypedJsonFilterSchema for validating typed JSON filters; renamed makePrimitiveSchema to makeScalarSchema; changed optional typedef fields from .optional() to .nullish()
packages/orm/src/client/crud/dialects/base-dialect.ts Added buildTypedJsonFilter, buildTypedJsonArrayFilter, and buildTypeJsonNonArrayFilter methods; refactored buildJsonFilter to distinguish plain vs typed JSON; made buildJsonPathSelection, buildJsonStringFilter, and buildJsonArrayExistsPredicate abstract
packages/orm/src/client/crud/dialects/sqlite.ts Implemented SQLite-specific JSON path selection using -> operator; added buildJsonStringFilter with quote-aware patterns; implemented buildJsonArrayExistsPredicate using json_each
packages/orm/src/client/crud/dialects/postgresql.ts Implemented PostgreSQL JSON path selection using jsonb_path_query_first; added case-sensitive/insensitive string filtering; implemented array predicate using jsonb_array_elements
packages/orm/src/client/crud-types.ts Added comprehensive TypedJsonFilter type system with ArrayTypedJsonFilter, NonArrayTypedJsonFilter, and TypedJsonFieldsFilter recursive types; changed path type from string[] to string
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/orm/src/client/crud/dialects/sqlite.ts (1)

391-413: Inconsistent and overly-restrictive use of jsonb_each — requires SQLite 3.51.0 (November 2025).

Line 393 uses jsonb_each for array_contains, while line 409 uses json_each for buildJsonArrayExistsPredicate. The jsonb_each function was only added in SQLite 3.51.0 (released November 2025), making it unavailable on virtually all production SQLite installations. The json_each variant has been available since SQLite 3.9.0 (2015).

Replace with json_each for broad compatibility:

-            .with('array_contains', () => sql<any>`EXISTS (SELECT 1 FROM jsonb_each(${lhs}) WHERE value = ${value})`)
+            .with('array_contains', () => sql<any>`EXISTS (SELECT 1 FROM json_each(${lhs}) WHERE value = ${value})`)

This aligns with line 409's usage and supports SQLite versions from 2015 onward.

🧹 Nitpick comments (1)
packages/orm/src/client/crud/dialects/base-dialect.ts (1)

524-546: Consider throwing on unrecognized filter patterns instead of returning true().

When the filter doesn't match known plain JSON filter keys and isn't a typedef, the code returns this.true() (line 544), which silently accepts any input. This could mask invalid filter payloads.

Consider being more explicit about unrecognized patterns:

         } else if (isTypeDef(this.schema, fieldDef.type)) {
             return this.buildTypedJsonFilter(receiver, filter, fieldDef.type, !!fieldDef.array);
         } else {
-            return this.true();
+            // Plain Json field without recognized filter keys - treat as no filter
+            // This handles cases like empty objects or unknown keys
+            return this.true();
         }

Alternatively, if unknown keys should be rejected:

         } else {
-            return this.true();
+            const unknownKeys = Object.keys(filter).filter(k => !['path', 'equals', 'not', 'string_contains', 'string_starts_with', 'string_ends_with', 'array_contains', 'array_starts_with', 'array_ends_with', 'mode'].includes(k));
+            if (unknownKeys.length > 0) {
+                invariant(false, `Invalid JSON filter keys: ${unknownKeys.join(', ')}`);
+            }
+            return this.true();
         }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ebf98a5 and 67ff010.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • packages/orm/src/client/crud-types.ts (6 hunks)
  • packages/orm/src/client/crud/dialects/base-dialect.ts (6 hunks)
  • packages/orm/src/client/crud/dialects/postgresql.ts (2 hunks)
  • packages/orm/src/client/crud/dialects/sqlite.ts (4 hunks)
  • packages/orm/src/client/crud/validator/index.ts (11 hunks)
  • packages/orm/src/client/query-utils.ts (1 hunks)
  • packages/schema/src/schema.ts (1 hunks)
  • pnpm-workspace.yaml (1 hunks)
  • tests/e2e/orm/client-api/json-filter.test.ts (28 hunks)
  • tests/e2e/orm/schemas/typed-json/schema.ts (2 hunks)
  • tests/e2e/orm/schemas/typed-json/schema.zmodel (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.zmodel

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.zmodel: Always run zenstack generate after modifying ZModel schemas
ZModel schema files should define database structure and policies that compile to TypeScript via zenstack generate

Files:

  • tests/e2e/orm/schemas/typed-json/schema.zmodel
tests/e2e/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

E2E tests should validate real-world schema compatibility with established projects

Files:

  • tests/e2e/orm/client-api/json-filter.test.ts
  • tests/e2e/orm/schemas/typed-json/schema.ts
🧠 Learnings (8)
📚 Learning: 2025-10-21T16:09:31.218Z
Learnt from: ymc9
Repo: zenstackhq/zenstack-v3 PR: 319
File: packages/runtime/src/client/executor/zenstack-query-executor.ts:63-72
Timestamp: 2025-10-21T16:09:31.218Z
Learning: In ZenStack, TypeDefs can be inherited by models. When a TypeDef contains fields with `map` attributes, those mapped field names need to be processed by the QueryNameMapper since they become part of the inheriting model's schema. Therefore, when checking if a schema has mapped names (e.g., in `schemaHasMappedNames`), both `schema.models` and `schema.typeDefs` must be inspected for `@map` and `map` attributes.

Applied to files:

  • packages/orm/src/client/query-utils.ts
  • tests/e2e/orm/schemas/typed-json/schema.zmodel
  • packages/schema/src/schema.ts
  • packages/orm/src/client/crud-types.ts
  • packages/orm/src/client/crud/validator/index.ts
  • packages/orm/src/client/crud/dialects/base-dialect.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.{ts,tsx} : Use Kysely as the query builder interface for low-level database queries, avoiding raw SQL when possible

Applied to files:

  • packages/orm/src/client/query-utils.ts
  • packages/orm/src/client/crud/dialects/sqlite.ts
  • packages/orm/src/client/crud/validator/index.ts
  • packages/orm/src/client/crud/dialects/base-dialect.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to **/*.zmodel : ZModel schema files should define database structure and policies that compile to TypeScript via `zenstack generate`

Applied to files:

  • packages/orm/src/client/query-utils.ts
  • tests/e2e/orm/schemas/typed-json/schema.zmodel
  • packages/orm/src/client/crud/validator/index.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to tests/e2e/**/*.{ts,tsx} : E2E tests should validate real-world schema compatibility with established projects

Applied to files:

  • tests/e2e/orm/schemas/typed-json/schema.zmodel
  • tests/e2e/orm/client-api/json-filter.test.ts
  • packages/orm/src/client/crud/validator/index.ts
  • tests/e2e/orm/schemas/typed-json/schema.ts
📚 Learning: 2025-10-21T16:04:56.292Z
Learnt from: ymc9
Repo: zenstackhq/zenstack-v3 PR: 319
File: packages/runtime/src/client/crud/dialects/base-dialect.ts:745-747
Timestamp: 2025-10-21T16:04:56.292Z
Learning: In packages/runtime/src/client/crud/dialects/base-dialect.ts, it's intentional that buildCursorFilter applies default ordering (via makeDefaultOrderBy fallback) while buildOrderBy does not. This ensures cursor-based pagination always has stable ordering for correctness, while regular queries remain unordered unless explicitly specified. This design is to be consistent with Prisma's pagination requirements.

Applied to files:

  • packages/orm/src/client/crud/dialects/sqlite.ts
  • packages/orm/src/client/crud/validator/index.ts
  • packages/orm/src/client/crud/dialects/base-dialect.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.test.{ts,tsx} : ORM package tests should include comprehensive client API tests and policy tests

Applied to files:

  • tests/e2e/orm/client-api/json-filter.test.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.{ts,tsx} : Implement plugin hooks at ORM, Kysely, and entity mutation levels for query interception and customization

Applied to files:

  • packages/orm/src/client/crud-types.ts
  • packages/orm/src/client/crud/validator/index.ts
  • packages/orm/src/client/crud/dialects/base-dialect.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Use `pnpm` with workspaces for package management, pinned to version `pnpm10.12.1`

Applied to files:

  • pnpm-workspace.yaml
🧬 Code graph analysis (6)
packages/orm/src/client/query-utils.ts (2)
packages/schema/src/schema.ts (1)
  • SchemaDef (11-19)
packages/orm/src/client/errors.ts (1)
  • createInternalError (147-151)
packages/orm/src/client/crud/dialects/sqlite.ts (1)
packages/orm/src/client/crud/dialects/base-dialect.ts (1)
  • buildFilter (111-158)
tests/e2e/orm/client-api/json-filter.test.ts (2)
packages/orm/src/client/null-values.ts (6)
  • JsonNull (10-10)
  • JsonNull (11-11)
  • DbNull (4-4)
  • DbNull (5-5)
  • AnyNull (16-16)
  • AnyNull (17-17)
packages/testtools/src/client.ts (1)
  • createTestClient (101-248)
packages/orm/src/client/crud-types.ts (1)
packages/schema/src/schema.ts (11)
  • GetModelFieldType (166-170)
  • FieldIsArray (262-266)
  • ModelFieldIsOptional (238-242)
  • SchemaDef (11-19)
  • GetEnums (136-136)
  • GetEnum (138-140)
  • GetTypeDefs (142-142)
  • GetTypeDefFields (172-175)
  • GetTypeDefFieldType (183-187)
  • TypeDefFieldIsArray (250-254)
  • TypeDefFieldIsOptional (244-248)
packages/orm/src/client/crud/dialects/postgresql.ts (1)
packages/orm/src/client/crud/dialects/base-dialect.ts (1)
  • buildFilter (111-158)
packages/orm/src/client/crud/validator/index.ts (4)
packages/schema/src/schema.ts (2)
  • AttributeApplication (40-43)
  • BuiltinType (88-98)
packages/orm/src/client/query-utils.ts (2)
  • getTypeDef (28-30)
  • getEnum (197-199)
packages/common-helpers/src/tiny-invariant.ts (1)
  • invariant (4-14)
packages/orm/src/client/null-values.ts (1)
  • DbNullClass (1-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Agent
  • GitHub Check: build-test (20.x, sqlite)
  • GitHub Check: build-test (20.x, postgresql)
  • GitHub Check: claude-review
🔇 Additional comments (23)
packages/schema/src/schema.ts (1)

183-188: LGTM - well-designed type utility.

The new GetTypeDefFieldType type follows the established pattern of GetModelFieldType (line 166-170) and properly extracts the type property from a TypeDef field. This enables typed JSON filtering to resolve nested field types at compile time.

tests/e2e/orm/schemas/typed-json/schema.ts (2)

62-68: LGTM - auto-generated schema correctly reflects zmodel changes.

The tags field is correctly defined as an optional array of String (optional: true, array: true), matching the tags: String[]? definition in the corresponding zmodel file.


77-82: LGTM - Address.zip field correctly defined.

The zip field is properly defined as an optional String, consistent with zip: String? in the zmodel.

tests/e2e/orm/schemas/typed-json/schema.zmodel (2)

22-22: LGTM - new test field for optional array filtering.

The tags: String[]? field adds test coverage for optional arrays of primitives within typed JSON structures. As per coding guidelines, ensure zenstack generate is run after modifying ZModel schemas.


27-27: LGTM - new test field for nullable nested primitives.

The zip: String? field enables testing null filtering on optional nested fields within typed JSON.

packages/orm/src/client/query-utils.ts (1)

40-46: LGTM - consistent helper function following established patterns.

The requireTypeDef function mirrors the requireModel pattern (lines 32-38), providing a throwing variant of getTypeDef for cases where the type definition must exist. This is used by the typed JSON filtering logic in the CRUD dialects.

tests/e2e/orm/client-api/json-filter.test.ts (3)

252-323: LGTM - path syntax migrated to JSONPath strings.

The path filter tests are correctly updated from array syntax to JSONPath string notation (e.g., '$.a', '$.x[1]'). The test coverage includes root path ('$'), nested objects ('$.a.b'), and array indices ('$.x[0]').


324-480: Excellent null filter test coverage.

Comprehensive testing of JsonNull, DbNull, and AnyNull across multiple scenarios:

  • Non-null values (lines 327-358)
  • Null values in objects (lines 360-401)
  • Top-level null handling (lines 403-413)
  • Nulls within arrays (lines 415-480)

This ensures the semantic differences between JSON null, database NULL, and path-not-found are properly distinguished.


823-1038: Comprehensive typed JSON filtering tests.

The new typed json direct filtering test block provides excellent coverage of the new feature:

  • Direct field filtering (name: 'Alice')
  • Numeric comparisons (age: { lt: 20 })
  • Deep field access (address: { country: 'US' })
  • is/isNot operators
  • Mixed shallow and deep filtering
  • Nullable field handling with null literal
  • Array quantifiers (some, every, none)
  • String operators in nested arrays (startsWith)
  • Rejection of mixed plain/typed JSON filters
  • Null filter for optional typedef fields

This validates the typed JSON filtering feature works correctly at runtime.

packages/orm/src/client/crud/validator/index.ts (6)

300-337: LGTM - well-structured scalar schema builder.

Renaming from makePrimitiveSchema to makeScalarSchema better reflects its purpose, as it now handles:

  • TypeDefs (recursive typed JSON)
  • Enums
  • Built-in primitives (String, Int, Float, etc.)

The implementation correctly delegates to specialized handlers for each type category.


369-390: Improved typedef schema with nullish handling.

The changes correctly:

  1. Use makeScalarSchema for nested field types (line 370)
  2. Apply nullish() for optional fields (line 375), allowing both null and undefined
  3. Use a custom schema wrapper (lines 385-387) to preserve original data order since Zod doesn't maintain object field order

540-613: Well-designed typed JSON filter schema builder.

The makeTypedJsonFilterSchema comprehensively handles:

  • Non-array fields: Field-level filters with proper type handling (lines 546-581)
  • Array quantifiers: some/every/none for array typedef fields (lines 584-592)
  • Object predicates: is/isNot for non-array fields (lines 593-601)
  • Plain JSON fallback: Allows raw JSON filter syntax (line 604)
  • Null handling: Allows null literal for optional fields (lines 606-609)

The union at line 612 correctly combines all valid filter variants.


631-638: Consistent use of makeScalarSchema in array filters.

The array filter schema now uses makeScalarSchema for element types (equals, has, hasEvery, hasSome), ensuring proper handling of typed elements including enums and typedefs.


659-669: Correct DbNull handling based on context.

The logic now properly restricts DbNull:

  • In filters (forFilter: true): Always allowed (line 663)
  • In mutations: Only allowed for nullable fields (lines 665-668)

This prevents invalid DbNull usage in non-nullable JSON field mutations.


686-700: Path property now optional string.

The path property is now an optional string (line 689) instead of a required array, aligning with the JSONPath string syntax ('$.a.b') used throughout the codebase. This simplifies the API while maintaining full path expression capability.

pnpm-workspace.yaml (1)

13-13: LGTM - minor version bump for better-sqlite3.

The catalog update from ^12.2.0 to ^12.5.0 is a minor version increment. The releases between v12.3.0 and v12.5.0 include CI/build infrastructure updates, GitHub Action bumps, and updates to the bundled SQLite version (from 3.50.4 to 3.51.1). No breaking changes or API modifications are introduced.

packages/orm/src/client/crud/dialects/postgresql.ts (1)

505-515: LGTM!

The buildJsonArrayExistsPredicate implementation correctly uses PostgreSQL's jsonb_array_elements function with an EXISTS subquery to check for element matches within JSON arrays.

packages/orm/src/client/crud/dialects/sqlite.ts (1)

371-385: LGTM!

The buildJsonStringFilter implementation correctly handles the JSON string pattern matching. The unused _mode parameter is intentional since SQLite's LIKE is case-insensitive by default (as documented at line 470-471).

packages/orm/src/client/crud-types.ts (2)

467-478: Breaking change: path type changed from string[] to string.

The path property type was changed from string[] to string. This aligns with the new string-based JSON path notation (e.g., '$.a', '$.tags[0]') used in the dialect implementations, but may break existing code that passes array paths.

Ensure this breaking change is documented in migration notes if applicable.


480-539: LGTM!

The new TypedJsonFilter type system is well-designed:

  • XOR ensures mutual exclusivity between plain JSON filter and typed filter
  • Array filters (some/every/none) correctly mirror relation filter semantics
  • Non-array filters support both is/isNot and direct field access
  • Recursive TypedJsonFieldsFilter properly handles nested typedefs with array/optional propagation
packages/orm/src/client/crud/dialects/base-dialect.ts (3)

653-699: LGTM!

The buildTypeJsonNonArrayFilter implementation correctly handles:

  • Null comparison using JSON null literal ('null')
  • is/isNot filter delegation with proper negation
  • Direct field filters with recursive typedef handling
  • String field quote trimming via trim() function

The use of requireTypeDef ensures type safety when accessing typedef fields.


614-651: LGTM!

The buildTypedJsonArrayFilter correctly implements array quantifier semantics:

  • some: EXISTS predicate
  • none: NOT EXISTS predicate
  • every: NOT EXISTS with negated inner filter (equivalent to "no element fails the filter")

The helper lambdas makeExistsPred and makeExistsNegatedPred cleanly encapsulate the EXISTS subquery construction.


1410-1437: LGTM!

The abstract method signatures are well-defined:

  • buildJsonPathSelection now takes string | undefined path
  • buildJsonStringFilter provides pattern-based string matching
  • buildJsonArrayExistsPredicate enables typed JSON array filtering

These abstractions allow PostgreSQL and SQLite dialects to provide appropriate implementations.

@claude
Copy link

claude bot commented Dec 9, 2025

Claude finished @ymc9's task —— View job


Pull Request Review

I've completed a comprehensive review of this typed JSON filters implementation. Here's my analysis:

  • Analyze core type definitions and changes
  • Review dialect implementations (PostgreSQL, SQLite)
  • Examine validator logic and safety
  • Check test coverage and quality
  • Assess performance implications
  • Look for security concerns
  • Provide final feedback and recommendations

Overall Assessment: ⚠️ Requires Attention

This is a solid implementation of typed JSON filtering with excellent type safety, comprehensive dialect support, and thorough test coverage. However, there's one critical issue that needs to be addressed.

🚨 Critical Issue

Validator Implementation Missing (validator/index.ts:702-705)

private makeTypeDefFilterSchema(_type: string, _optional: boolean) {
    // TODO: strong typed JSON filtering
    return z.never();
}

Impact: This makes typed JSON filters completely unusable in production as they'll be rejected by input validation.

Required Fix: The makeTypeDefFilterSchema method needs to be implemented to generate proper Zod schemas for typed JSON filters, similar to how makeTypedJsonFilterSchema is implemented but wasn't connected to the validator pipeline.

Strengths

Type Safety & API Design (crud-types.ts)

  • Excellent use of conditional types with proper array/object distinction
  • XOR types prevent mixing typed and untyped JSON filters
  • Recursive type handling for nested TypeDef structures
  • Clean separation between some/every/none (arrays) and is/isNot (objects)

Database Dialect Implementation

  • PostgreSQL: Robust JSON path queries using jsonb_path_query_first, proper array element iteration with jsonb_array_elements
  • SQLite: Good fallback handling using json_each, proper type detection in transformOutput
  • Both dialects handle edge cases like empty arrays and nested structures correctly

Test Coverage (json-filter.test.ts)

  • Comprehensive tests covering direct field filtering, nested objects, array operations
  • Tests both simple and complex scenarios including is/isNot and some/every/none
  • Edge case testing for nullable fields and mixed shallow/deep filtering

📊 Performance Considerations

Positive:

  • Efficient JSON path selection using database-native functions
  • Proper use of EXISTS predicates for array filtering
  • Good query optimization with appropriate indexing strategies

Watch Points:

  • Complex nested queries may impact performance on large datasets
  • Consider adding query plan analysis for complex typed JSON filters

🔒 Security Assessment

Good practices observed:

  • Proper SQL injection prevention through parameterized queries
  • Safe JSON path construction using database functions
  • Input validation framework is in place (though incomplete)

📋 Recommendations

  1. Immediate (Required):

    • Implement makeTypeDefFilterSchema in validator to enable typed JSON filters
    • Connect the existing makeTypedJsonFilterSchema logic to the validation pipeline
  2. Short-term:

    • Add performance tests for complex nested queries
    • Consider documenting query optimization strategies
    • Add validation tests specifically for typed JSON filters
  3. Long-term:

    • Monitor query performance on production workloads
    • Consider caching strategies for frequently used filter patterns

🎯 Verdict

This is high-quality code with excellent architecture and comprehensive testing. The only blocker is the unimplemented validator, which is straightforward to fix. Once the validator is implemented, this feature will provide significant value with strong type safety and good performance characteristics.

Recommendation: Approve after addressing the validator implementation.

@claude
Copy link

claude bot commented Dec 9, 2025

Claude finished @ymc9's task —— View job


I've completed a comprehensive review of this typed JSON filters implementation. Here's my analysis:

  • Analyze core type definitions and changes
  • Review dialect implementations (PostgreSQL, SQLite)
  • Examine validator logic and safety
  • Check test coverage and quality
  • Assess performance implications
  • Look for security concerns
  • Provide final feedback and recommendations

Overall Assessment: ✅ Excellent Implementation

This is a high-quality implementation of typed JSON filtering with excellent type safety, comprehensive dialect support, and thorough test coverage. The code demonstrates solid architectural decisions and attention to detail.

Major Strengths

Type Safety & API Design (crud-types.ts)

  • Excellent use of conditional types with proper array/object distinction
  • XOR types prevent mixing typed and untyped JSON filters
  • Recursive type handling for nested TypeDef structures
  • Clean separation between some/every/none (arrays) and is/isNot (objects)

Database Dialect Implementation

  • PostgreSQL: Robust JSON path queries using jsonb_path_query_first, proper array element iteration with jsonb_array_elements
  • SQLite: Good fallback handling using json_each, proper type detection in transformOutput
  • Both dialects handle edge cases like empty arrays and nested structures correctly

Validator Logic (validator/index.ts)

  • Complete makeTypedJsonFilterSchema implementation with proper recursive handling
  • Correct nullish handling for optional fields (.nullish() vs .optional())
  • Good validation of mixed plain/typed JSON filters (prevents invalid combinations)
  • Proper enum and primitive type delegation

Test Coverage (json-filter.test.ts)

  • Comprehensive tests covering direct field filtering, nested objects, array operations
  • Tests both simple and complex scenarios including is/isNot and some/every/none
  • Edge case testing for nullable fields and mixed shallow/deep filtering
  • Good validation error testing for invalid filter combinations

📊 Performance Considerations

Positive:

  • Efficient JSON path selection using database-native functions
  • Proper use of EXISTS predicates for array filtering
  • Good query optimization with appropriate indexing strategies

Watch Points:

  • Complex nested queries may impact performance on large datasets
  • Consider adding query plan analysis for complex typed JSON filters

🔒 Security Assessment

Good practices observed:

  • Proper SQL injection prevention through parameterized queries
  • Safe JSON path construction using database functions
  • Input validation framework properly implemented
  • No exposure of internal type definitions to external input

⚠️ Minor Issues Found

  1. PostgreSQL String Filter Bug (postgresql.ts:475)

    • Missing opening quote in string_ends_with pattern: should be "%${value}" instead of %${value}"
    • This would cause string filtering to fail for end-of-string matches
  2. SQLite Compatibility Issue (sqlite.ts:393)

    • Uses jsonb_each instead of json_each for array_contains
    • jsonb_each requires SQLite 3.51.0+ (very recent), should use json_each for broader compatibility

📋 Recommendations

  1. Immediate:

    • Fix the PostgreSQL string pattern bug
    • Change SQLite jsonb_each to json_each for compatibility
  2. Short-term:

    • Add performance tests for complex nested queries
    • Consider documenting query optimization strategies
    • Add validation tests specifically for typed JSON edge cases
  3. Long-term:

    • Monitor query performance on production workloads
    • Consider caching strategies for frequently used filter patterns

🎯 Verdict

This is an excellent implementation that significantly enhances the ORM's capabilities. The type safety is impressive, the database integration is well-thought-out, and the test coverage is comprehensive. The minor bugs are easy fixes that don't affect the overall architecture.

Recommendation: Approve after addressing the two minor compatibility issues.


Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/orm/src/client/crud/validator/index.ts (1)

385-389: Consider improving error messages for the custom validator.

The z.custom() wrapper preserves object field order (per the comment), but sacrifices detailed Zod validation errors. When validation fails, users only see a generic failure message rather than field-specific errors. If field order preservation is critical, consider whether Zod 4's object handling has improved, or explore using .transform(v => v) as an alternative that might preserve both order and error detail.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c1eef07 and c05d91b.

📒 Files selected for processing (1)
  • packages/orm/src/client/crud/validator/index.ts (10 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.{ts,tsx} : Implement plugin hooks at ORM, Kysely, and entity mutation levels for query interception and customization

Applied to files:

  • packages/orm/src/client/crud/validator/index.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to tests/e2e/**/*.{ts,tsx} : E2E tests should validate real-world schema compatibility with established projects

Applied to files:

  • packages/orm/src/client/crud/validator/index.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.{ts,tsx} : Use Kysely as the query builder interface for low-level database queries, avoiding raw SQL when possible

Applied to files:

  • packages/orm/src/client/crud/validator/index.ts
📚 Learning: 2025-10-21T16:09:31.218Z
Learnt from: ymc9
Repo: zenstackhq/zenstack-v3 PR: 319
File: packages/runtime/src/client/executor/zenstack-query-executor.ts:63-72
Timestamp: 2025-10-21T16:09:31.218Z
Learning: In ZenStack, TypeDefs can be inherited by models. When a TypeDef contains fields with `map` attributes, those mapped field names need to be processed by the QueryNameMapper since they become part of the inheriting model's schema. Therefore, when checking if a schema has mapped names (e.g., in `schemaHasMappedNames`), both `schema.models` and `schema.typeDefs` must be inspected for `@map` and `map` attributes.

Applied to files:

  • packages/orm/src/client/crud/validator/index.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to **/*.zmodel : ZModel schema files should define database structure and policies that compile to TypeScript via `zenstack generate`

Applied to files:

  • packages/orm/src/client/crud/validator/index.ts
🧬 Code graph analysis (1)
packages/orm/src/client/crud/validator/index.ts (4)
packages/schema/src/schema.ts (2)
  • AttributeApplication (40-43)
  • BuiltinType (88-98)
packages/orm/src/client/query-utils.ts (2)
  • getTypeDef (28-30)
  • getEnum (197-199)
packages/common-helpers/src/tiny-invariant.ts (1)
  • invariant (4-14)
packages/orm/src/client/null-values.ts (1)
  • DbNullClass (1-3)
🔇 Additional comments (7)
packages/orm/src/client/crud/validator/index.ts (7)

300-337: LGTM! Good refactoring to rename the method.

The rename from makePrimitiveSchema to makeScalarSchema better reflects the method's scope—it handles primitives, enums, and TypeDefs. The logic remains consistent.


370-376: Good use of makeScalarSchema and nullish() for Zod 4.

The changes correctly use makeScalarSchema for consistency and nullish() to allow both null and undefined for optional TypeDef fields, which aligns with Zod 4 semantics.


540-613: Excellent TypeDef-aware filter implementation—verify edge cases through testing.

The rewritten makeTypedJsonFilterSchema adds sophisticated filtering capabilities:

  • Field-based filters for TypeDef properties
  • Recursive handling for nested TypeDefs, arrays, enums, and primitives
  • is/isNot filters for non-array TypeDefs
  • some/every/none filters for array TypeDefs
  • Plain JSON filter fallback for flexibility
  • Proper null handling for optional fields

The recursive structure with z.lazy() correctly avoids infinite loops, and the element schema derivation (line 583, array: false) is appropriate.

Given the complexity and multiple edge cases (nested TypeDefs, arrays within TypeDefs, optional typed fields), please ensure comprehensive test coverage for:

  • Nested TypeDef filtering (e.g., Address containing Location)
  • Array of TypeDef filtering (e.g., addresses: Address[])
  • Mixed primitive and TypeDef fields
  • Optional TypeDef fields with null checks

Can you confirm that E2E or integration tests cover these typed JSON filtering scenarios?


631-639: LGTM! Consistent use of makeScalarSchema for array elements.

The array filter schema correctly derives element validators using makeScalarSchema, aligning with the refactoring throughout this file.


655-680: Excellent correctness improvement for DbNull handling.

The refined logic properly distinguishes between filter and mutation contexts:

  • Filters: Always allow DbNullClass and AnyNullClass (lines 659, 668) so queries can match DbNull values regardless of field nullability
  • Mutations: Only allow DbNullClass if the field is nullable (lines 661-664), preventing invalid DbNull assignments

This prevents invalid mutations while maintaining flexible querying capabilities.


682-696: LGTM! Correct to make path optional in JSON filters.

Making the path optional allows filtering the entire JSON value directly (e.g., { equals: {...} }) without requiring a path specification. Users can still provide a path (now a string per the PR objectives) for nested field filtering.


1100-1127: LGTM! Consistent scalar schema usage in create and update paths.

Both create (line 1101) and update (line 1371) data schemas correctly use makeScalarSchema with field attributes, maintaining consistency across mutation operations.

Also applies to: 1370-1421

@claude
Copy link

claude bot commented Dec 10, 2025

Claude finished @ymc9's task —— View job


Pull Request Review

I've completed a comprehensive review of this typed JSON filters implementation. Here's my analysis:

  • Analyze core type definitions and changes
  • Review dialect implementations (PostgreSQL, SQLite)
  • Examine validator logic and safety
  • Check test coverage and quality
  • Assess performance implications
  • Look for security concerns
  • Provide final feedback and recommendations

Overall Assessment: ✅ Excellent Implementation

This is a high-quality implementation of typed JSON filtering with excellent type safety, comprehensive dialect support, and thorough test coverage. The code demonstrates solid architectural decisions and attention to detail.

Major Strengths

Type Safety & API Design (crud-types.ts)

  • Excellent use of conditional types with proper array/object distinction
  • XOR types prevent mixing typed and untyped JSON filters
  • Recursive type handling for nested TypeDef structures
  • Clean separation between some/every/none (arrays) and is/isNot (objects)

Database Dialect Implementation

  • PostgreSQL: Robust JSON path queries using jsonb_path_query_first, proper array element iteration with jsonb_array_elements
  • SQLite: Good fallback handling using json_each, proper type detection in transformOutput
  • Both dialects handle edge cases like empty arrays and nested structures correctly

Validator Logic (validator/index.ts)

  • Complete makeTypedJsonFilterSchema implementation with proper recursive handling
  • Correct nullish handling for optional fields (.nullish() vs .optional())
  • Good validation of mixed plain/typed JSON filters (prevents invalid combinations)
  • Proper enum and primitive type delegation

Test Coverage (json-filter.test.ts)

  • Comprehensive tests covering direct field filtering, nested objects, array operations
  • Tests both simple and complex scenarios including is/isNot and some/every/none
  • Edge case testing for nullable fields and mixed shallow/deep filtering
  • Good validation error testing for invalid filter combinations

📊 Performance Considerations

Positive:

  • Efficient JSON path selection using database-native functions
  • Proper use of EXISTS predicates for array filtering
  • Good query optimization with appropriate indexing strategies

Watch Points:

  • Complex nested queries may impact performance on large datasets
  • Consider adding query plan analysis for complex typed JSON filters

🔒 Security Assessment

Good practices observed:

  • Proper SQL injection prevention through parameterized queries
  • Safe JSON path construction using database functions
  • Input validation framework properly implemented
  • No exposure of internal type definitions to external input

⚠️ Minor Issues Found

  1. SQLite Compatibility Issue (sqlite.ts:393)
    • Uses jsonb_each instead of json_each for array_contains
    • jsonb_each requires SQLite 3.51.0+ (very recent), should use json_each for broader compatibility

📋 Recommendations

  1. Immediate:

    • Change SQLite jsonb_each to json_each for compatibility
  2. Short-term:

    • Add performance tests for complex nested queries
    • Consider documenting query optimization strategies
    • Add validation tests specifically for typed JSON edge cases
  3. Long-term:

    • Monitor query performance on production workloads
    • Consider caching strategies for frequently used filter patterns

🎯 Verdict

This is an excellent implementation that significantly enhances the ORM's capabilities. The type safety is impressive, the database integration is well-thought-out, and the test coverage is comprehensive. The minor compatibility issue is easy to fix and doesn't affect the overall architecture.

Recommendation: Approve after addressing the SQLite compatibility issue.


Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/orm/src/client/crud-types.ts (1)

714-719: Minor: Potential field name collision with is/isNot.

The union type allows either { is: ..., isNot: ... } wrapper or direct TypedJsonFieldsFilter. If a typedef has fields literally named is or isNot, there could be ambiguous interpretation. This is an edge case and follows Prisma's established pattern for relation filters.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c05d91b and 5e39ffd.

📒 Files selected for processing (1)
  • packages/orm/src/client/crud-types.ts (30 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-21T16:09:31.218Z
Learnt from: ymc9
Repo: zenstackhq/zenstack-v3 PR: 319
File: packages/runtime/src/client/executor/zenstack-query-executor.ts:63-72
Timestamp: 2025-10-21T16:09:31.218Z
Learning: In ZenStack, TypeDefs can be inherited by models. When a TypeDef contains fields with `map` attributes, those mapped field names need to be processed by the QueryNameMapper since they become part of the inheriting model's schema. Therefore, when checking if a schema has mapped names (e.g., in `schemaHasMappedNames`), both `schema.models` and `schema.typeDefs` must be inspected for `@map` and `map` attributes.

Applied to files:

  • packages/orm/src/client/crud-types.ts
📚 Learning: 2025-11-26T01:55:04.540Z
Learnt from: CR
Repo: zenstackhq/zenstack-v3 PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-26T01:55:04.540Z
Learning: Applies to packages/zenstackhq/orm/**/*.{ts,tsx} : Implement plugin hooks at ORM, Kysely, and entity mutation levels for query interception and customization

Applied to files:

  • packages/orm/src/client/crud-types.ts
🧬 Code graph analysis (1)
packages/orm/src/client/crud-types.ts (2)
packages/schema/src/schema.ts (14)
  • GetModelFieldType (166-170)
  • FieldIsArray (262-266)
  • GetEnum (138-140)
  • SchemaDef (11-19)
  • GetEnums (136-136)
  • GetTypeDefs (142-142)
  • GetTypeDefFields (172-175)
  • GetTypeDefFieldType (183-187)
  • TypeDefFieldIsArray (250-254)
  • TypeDefFieldIsOptional (244-248)
  • RelationFields (217-221)
  • RelationFieldType (229-236)
  • GetModels (121-121)
  • NonRelationFields (211-215)
packages/orm/src/utils/type-utils.ts (8)
  • NullableIf (8-8)
  • MapBaseType (46-46)
  • JsonValue (48-48)
  • JsonNullValues (53-53)
  • Optional (4-4)
  • XOR (77-77)
  • OrArray (59-59)
  • NonEmptyArray (61-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: build-test (20.x, postgresql)
  • GitHub Check: build-test (20.x, sqlite)
  • GitHub Check: claude-review
🔇 Additional comments (4)
packages/orm/src/client/crud-types.ts (4)

311-316: LGTM! TypedJsonFilter integration in WhereInput is well-structured.

The typedef field detection and parameter passing to TypedJsonFilter correctly propagates the schema, typedef name, array status, and optionality from the model field level.


692-751: Well-designed recursive TypedJsonFilter implementation.

The type structure correctly handles:

  • XOR between raw JsonFilter and typed filter for flexibility
  • Array fields with some/every/none quantifiers
  • Non-array fields with is/isNot predicates or direct field matching
  • Recursive nesting for typedef fields containing other typedefs
  • Proper nullable handling when Optional is true

One observation: WithAggregations is hardcoded to false for nested EnumFilter and PrimitiveFilter (lines 743, 749), which is appropriate since aggregation filters only apply at the top query level.


377-406: LGTM! ArrayFilter and MapScalarType improvements.

The generic parameter rename from T to Type improves readability. The added JSDoc comments and isEmpty predicate enhance the filter's usability and discoverability.


339-374: Excellent documentation additions throughout.

The comprehensive JSDoc comments added to filter types, CRUD operations, and aggregation fields significantly improve developer experience and discoverability. The documentation accurately describes each field's purpose and includes helpful notes about dialect-specific behaviors (e.g., mode not effective for SQLite).

@ymc9 ymc9 merged commit 583e77e into dev Dec 10, 2025
7 checks passed
@ymc9 ymc9 deleted the feat/typed-json-filter branch December 10, 2025 01:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants