Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Nov 5, 2025

Summary by CodeRabbit

  • New Features

    • ClientHooks and ModelMutationModelResult to improve model-specific hook ergonomics and mutation return flexibility
  • Improvements

    • Harmonized query/mutation typings across React, Vue, and Svelte clients
    • Optional infinite-query defaults and reactive option support in Vue
    • Better handling of operations for delegate-style models
    • Simplified fetch/mutation behavior and error handling
  • Tests

    • Added comprehensive typing tests for React, Vue, and Svelte clients

Copilot AI review requested due to automatic review settings November 5, 2025 18:47
@coderabbitai
Copy link

coderabbitai bot commented Nov 5, 2025

Walkthrough

Refactors TanStack Query client integrations (React, Svelte, Vue) to introduce new public types ClientHooks and ModelMutationModelResult, add TrimDelegateModelOperations, adjust fetcher/mutation signatures and infinite-query defaults, add typing tests, and mark certain operations ineligible for delegate models in the ORM contract.

Changes

Cohort / File(s) Summary
Core integrations
packages/clients/tanstack-query/src/react.ts, packages/clients/tanstack-query/src/svelte.ts, packages/clients/tanstack-query/src/vue.ts
Introduced ClientHooks<Schema> (replacing SchemaHooks) and ModelMutationModelResult (array-return flag). Wrapped ModelQueryHooks via TrimDelegateModelOperations. Updated useClientQueries return type, harmonized internal query/mutation signatures to use simplified fetcher<R>(...), removed prior boolean flags, and made infinite-query options optional with safe defaults. Vue also adopted reactive option wrappers (MaybeRefOrGetter/UnwrapRef).
Utilities — types
packages/clients/tanstack-query/src/utils/types.ts
Added TrimDelegateModelOperations<Schema, Model, T> to conditionally omit operations (using OperationsIneligibleForDelegateModels) for delegate models.
Utilities — runtime
packages/clients/tanstack-query/src/utils/common.ts
Simplified fetcher signature to fetcher<R>(...), removed checkReadBack param and conditional return typing; error handling now inspects error.rejectedByPolicy / rejectReason === 'cannot-read-back' and returns undefined in that case, otherwise throws QueryError.
ORM contract
packages/orm/src/client/contract.ts
Added `OperationsIneligibleForDelegateModels = 'create'
Typing tests
packages/clients/tanstack-query/test/react-typing-test.ts, packages/clients/tanstack-query/test/svelte-typing-test.ts, packages/clients/tanstack-query/test/vue-typing-test.ts
Added comprehensive TypeScript typing tests that exercise new ClientHooks/hook signatures (find/create/update/delete, infinite queries, options, select/include), and assert expected type errors.
Package devDeps ordering
packages/clients/tanstack-query/package.json
Reordered @tanstack/svelte-query to appear after @tanstack/vue-query in devDependencies; version unchanged.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

  • Areas needing extra attention:
    • fetcher signature and new unconditional read-back handling in utils/common.ts (runtime behavior change).
    • Conditional omission logic in TrimDelegateModelOperations and OperationsIneligibleForDelegateModels interaction with ModelOperations in ORM contract.
    • Consistency across React/Svelte/Vue hooks and the new ClientHooks public surface, including Vue reactive option wrappers and infinite-query defaults.
    • New typed mutation result ModelMutationModelResult and places that rely on its mutateAsync array-vs-single semantics.

Possibly related PRs

  • #356 — modifies the same tanstack-query client files (react/svelte/vue, utils/types, utils/common); likely closely related changes to hook typings and fetcher behavior.
  • #359 — overlaps on the new types and fetcher signature changes; relevant to the ModelMutationModelResult and TrimDelegateModelOperations additions.
  • #366 — touches svelte/vue client integrations and hook typings; likely connected to the reactive options and tests added here.

Poem

🐰
Hopped through types both wide and neat,
ClientHooks now take their seat,
Trimmed the ops that shouldn't play,
Fetcher listens, clears the way,
Tests hop in — the garden's sweet. 🥕

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: introducing improved typing for mutation mutateAsync methods, which is evident across react.ts, svelte.ts, and vue.ts files with new ModelMutationModelResult types.
✨ 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 fix/tanstack-improve-typing

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 Nov 5, 2025

Claude finished @ymc9's task —— View job


Code Review: TanStack Query Mutation Typing Improvements

I've completed a comprehensive review of this PR that improves mutation mutateAsync typing across React, Svelte, and Vue TanStack Query integrations.

Todo List:

  • Read repository setup instructions (CLAUDE.md)
  • Analyze the core typing improvements in utils/types.ts
  • Review React implementation changes
  • Review Svelte implementation changes
  • Review Vue implementation changes
  • Examine ORM contract changes
  • Evaluate new test coverage
  • Assess code quality and best practices
  • Check for potential bugs or issues
  • Consider performance implications
  • Review security aspects
  • Provide final comprehensive feedback

🎯 Summary

This is an excellent PR that addresses a critical typing issue with mutateAsync in TanStack Query mutations. The improvements provide better TypeScript inference for mutation return types based on the actual arguments passed to mutateAsync, making the API more type-safe and developer-friendly.

✅ Strengths

1. Consistent Architecture

  • Uniform Implementation: All three frameworks (React, Svelte, Vue) receive identical typing improvements
  • Pattern Consistency: The ModelMutationModelResult type follows the same structure across all implementations
  • Framework-Specific Adaptation: Properly adapts to each framework's specific typing requirements (e.g., Svelte's Readable<> wrapper)

2. Excellent Type Safety

  • Generic Constraint: The new mutateAsync<T extends TArgs>() signature ensures type safety by constraining the generic parameter
  • Return Type Inference: Return type correctly infers based on the specific T parameter, not the broader TArgs
  • Array Handling: Smart conditional typing with Array extends true ? ModelResult<Schema, Model, T>[] : ModelResult<Schema, Model, T>

3. Comprehensive Test Coverage

  • Type-Only Tests: Excellent addition of typing tests that validate TypeScript inference without runtime overhead
  • Error Case Coverage: Proper use of @ts-expect-error to validate that invalid cases are caught by TypeScript
  • Real-World Scenarios: Tests cover practical usage patterns including select, include, and various mutation operations

4. Clean Implementation

  • Minimal Surface Area: Only affects mutation hooks that return model data, not batch operations like createMany
  • Backwards Compatibility: Changes are additive and don't break existing APIs
  • Code Reuse: Smart reuse of existing ModelMutationResult types with targeted overrides

🔧 Technical Implementation Details

Type System Improvements

The core improvement is in packages/clients/tanstack-query/src/utils/types.ts:24-28:

export type TrimDelegateModelOperations<
    Schema extends SchemaDef,
    Model extends GetModels<Schema>,
    T extends Record<string, unknown>,
> = IsDelegateModel<Schema, Model> extends true ? Omit<T, OperationsIneligibleForDelegateModels> : T;

This type correctly handles delegate models by removing operations that aren't applicable to them.

Mutation Typing Enhancement

The key innovation is the ModelMutationModelResult type definition that overrides mutateAsync:

export type ModelMutationModelResult<...> = Omit<ModelMutationResult<...>, 'mutateAsync'> & {
    mutateAsync<T extends TArgs>(
        args: T,
        options?: ModelMutationOptions<ModelResult<Schema, Model, T>, T>,
    ): Promise<Array extends true ? ModelResult<Schema, Model, T>[] : ModelResult<Schema, Model, T>>;
};

This provides precise typing that infers the return type based on the actual arguments passed to mutateAsync.

🛡️ Security & Performance Assessment

Security: ✅ No Concerns

  • No security-sensitive changes
  • All improvements are compile-time only
  • No runtime behavior changes
  • Maintains existing access control patterns

Performance: ✅ Excellent

  • Zero Runtime Impact: All changes are TypeScript-only
  • Build Performance: Typing tests compile efficiently
  • Bundle Size: No impact on final bundle size
  • Type Checking: Well-structured generics shouldn't significantly impact compilation time

🧪 Test Quality Assessment

Comprehensive Coverage

The new typing tests (react-typing-test.ts, svelte-typing-test.ts, vue-typing-test.ts) are exemplary:

  1. Validation of Correct Usage: Tests verify that valid operations type-check correctly
  2. Error Case Testing: Proper use of @ts-expect-error to ensure invalid operations are caught
  3. Edge Cases: Tests cover field selection, inclusion, and various mutation types
  4. Framework-Specific: Each test adapts to the framework's specific patterns (e.g., Svelte's get() wrapper)

📦 Package Management

The version bump to 3.0.0-beta.18 is appropriate for this improvement in a beta release.

🚀 Minor Suggestions for Future Improvements

  1. Documentation: Consider adding JSDoc examples showing the improved typing in action
  2. Performance Monitoring: Consider adding TypeScript compilation time benchmarks for complex schemas
  3. Error Messages: The improved types should provide better error messages when misused

🎯 Conclusion

This is a high-quality PR that significantly improves the developer experience without any drawbacks:

  • Perfect Type Safety: Provides accurate type inference for mutation return types
  • Excellent Testing: Comprehensive typing tests ensure the improvements work correctly
  • Consistent Implementation: Uniform improvements across all three supported frameworks
  • Zero Runtime Impact: Pure TypeScript improvements with no performance cost
  • Backwards Compatible: No breaking changes to existing APIs

The implementation is clean, well-tested, and follows best practices. This PR represents exactly the kind of improvement that makes ZenStack's TanStack Query integration more developer-friendly and type-safe.

Recommendation: ✅ Approve and merge

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 refactors type definitions in the TanStack Query client to improve type safety and maintainability. The changes include extracting ineligible operations for delegate models into a reusable type, introducing a utility type for trimming delegate model operations, and enhancing mutation return types to provide better type inference for the mutateAsync method.

  • Extracted delegate model operation restrictions into a named type for reusability
  • Added TrimDelegateModelOperations utility type to conditionally omit operations based on model type
  • Enhanced mutation hooks to return more specific types with overloaded mutateAsync signatures
  • Added comprehensive type tests for React, Vue, and Svelte implementations

Reviewed Changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/orm/src/client/contract.ts Extracts delegate model ineligible operations into a reusable named type
packages/clients/tanstack-query/src/utils/types.ts Adds utility type for trimming operations from delegate models
packages/clients/tanstack-query/src/react.ts Updates type definitions to use new mutation result type and operation trimming utility
packages/clients/tanstack-query/src/vue.ts Updates type definitions to use new mutation result type and operation trimming utility
packages/clients/tanstack-query/src/svelte.ts Updates type definitions to use new mutation result type and operation trimming utility
packages/clients/tanstack-query/test/react-typing-test.ts Adds comprehensive type tests for React hooks
packages/clients/tanstack-query/test/vue-typing-test.ts Adds comprehensive type tests for Vue hooks
packages/clients/tanstack-query/test/svelte-typing-test.ts Adds comprehensive type tests for Svelte hooks
packages/clients/tanstack-query/package.json Minor reordering of devDependencies (no functional change)

💡 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: 1

📜 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 9372688 and 9ce9cee.

📒 Files selected for processing (9)
  • packages/clients/tanstack-query/package.json (1 hunks)
  • packages/clients/tanstack-query/src/react.ts (4 hunks)
  • packages/clients/tanstack-query/src/svelte.ts (4 hunks)
  • packages/clients/tanstack-query/src/utils/types.ts (2 hunks)
  • packages/clients/tanstack-query/src/vue.ts (4 hunks)
  • packages/clients/tanstack-query/test/react-typing-test.ts (1 hunks)
  • packages/clients/tanstack-query/test/svelte-typing-test.ts (1 hunks)
  • packages/clients/tanstack-query/test/vue-typing-test.ts (1 hunks)
  • packages/orm/src/client/contract.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (8)
packages/clients/tanstack-query/src/utils/types.ts (2)
packages/schema/src/schema.ts (3)
  • SchemaDef (10-18)
  • GetModels (109-109)
  • IsDelegateModel (264-267)
packages/orm/src/client/contract.ts (1)
  • OperationsIneligibleForDelegateModels (798-798)
packages/clients/tanstack-query/test/vue-typing-test.ts (3)
packages/clients/tanstack-query/src/react.ts (1)
  • useClientQueries (257-262)
packages/clients/tanstack-query/src/svelte.ts (1)
  • useClientQueries (212-217)
packages/clients/tanstack-query/src/vue.ts (1)
  • useClientQueries (201-206)
packages/clients/tanstack-query/test/react-typing-test.ts (1)
packages/clients/tanstack-query/src/react.ts (1)
  • useClientQueries (257-262)
packages/clients/tanstack-query/test/svelte-typing-test.ts (1)
packages/clients/tanstack-query/src/svelte.ts (1)
  • useClientQueries (212-217)
packages/clients/tanstack-query/src/react.ts (2)
packages/orm/src/client/crud-types.ts (3)
  • SelectIncludeOmit (453-457)
  • ModelResult (135-179)
  • FindArgs (648-664)
packages/clients/tanstack-query/src/utils/types.ts (1)
  • TrimDelegateModelOperations (24-28)
packages/orm/src/client/contract.ts (1)
packages/schema/src/schema.ts (3)
  • SchemaDef (10-18)
  • GetModels (109-109)
  • IsDelegateModel (264-267)
packages/clients/tanstack-query/src/vue.ts (3)
packages/clients/tanstack-query/src/react.ts (9)
  • ModelQueryOptions (94-94)
  • ModelQueryResult (96-96)
  • ModelInfiniteQueryOptions (103-106)
  • ModelInfiniteQueryResult (108-108)
  • ModelMutationOptions (119-120)
  • ModelMutationResult (122-122)
  • ModelMutationModelResult (124-134)
  • ClientHooks (136-138)
  • ModelQueryHooks (142-252)
packages/orm/src/client/crud-types.ts (7)
  • SelectIncludeOmit (453-457)
  • ModelResult (135-179)
  • FindUniqueArgs (669-671)
  • SelectSubset (509-515)
  • FindArgs (648-664)
  • CreateArgs (677-682)
  • Subset (505-507)
packages/clients/tanstack-query/src/utils/types.ts (1)
  • TrimDelegateModelOperations (24-28)
packages/clients/tanstack-query/src/svelte.ts (5)
packages/clients/tanstack-query/src/react.ts (5)
  • ModelMutationModelResult (124-134)
  • ModelMutationResult (122-122)
  • ModelMutationOptions (119-120)
  • ClientHooks (136-138)
  • ModelQueryHooks (142-252)
packages/schema/src/schema.ts (2)
  • SchemaDef (10-18)
  • GetModels (109-109)
packages/orm/src/client/crud-types.ts (3)
  • SelectIncludeOmit (453-457)
  • ModelResult (135-179)
  • FindArgs (648-664)
packages/clients/tanstack-query/src/utils/types.ts (1)
  • TrimDelegateModelOperations (24-28)
packages/common-helpers/src/lower-case-first.ts (1)
  • lowerCaseFirst (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: Upload results
  • GitHub Check: build-test (20.x, postgresql)
  • GitHub Check: build-test (20.x, sqlite)
  • GitHub Check: claude-review
🔇 Additional comments (18)
packages/clients/tanstack-query/package.json (1)

68-85: Dependency reordering is acceptable.

The reordering of @tanstack/svelte-query after @tanstack/vue-query is a trivial organizational change with no functional impact. Versions remain consistent with peer dependency constraints.

packages/clients/tanstack-query/src/utils/types.ts (1)

24-28: Delegate trim logic looks correct

TrimDelegateModelOperations cleanly reuses OperationsIneligibleForDelegateModels so delegate models automatically drop unsupported hook keys without affecting others. Nice reuse of existing schema predicates.

packages/orm/src/client/contract.ts (1)

798-804: Shared ineligible-operations alias fits well

Centralizing OperationsIneligibleForDelegateModels here and reusing it in the delegate conditional keeps the ORM and client typings consistent—looks good.

packages/clients/tanstack-query/test/react-typing-test.ts (1)

41-76: Solid mutateAsync coverage

Appreciate the explicit mutate/mutateAsync checks (plus the negative @ts-expect-error cases)—this exercises the new typing surface thoroughly.

packages/clients/tanstack-query/test/vue-typing-test.ts (1)

39-74: Vue typings well exercised

Thanks for mirroring the mutation edge cases here—the promise chains and negative checks give good confidence in the Vue surface too.

packages/clients/tanstack-query/test/svelte-typing-test.ts (1)

41-86: Svelte store path verified

The Svelte variant hits the same mutation/query permutations via get(...), so the store-based API surface is well covered.

packages/clients/tanstack-query/src/react.ts (6)

39-39: LGTM! New imports support enhanced typing.

The new imports SelectIncludeOmit and TrimDelegateModelOperations are correctly added to support the refined public API surface and delegate model operation filtering.

Also applies to: 60-60


124-134: Well-designed conditional return type for mutateAsync.

The ModelMutationModelResult type elegantly handles both single and array returns through the Array type parameter. The generic T extends TArgs allows proper refinement at the call site, enabling operations like createManyAndReturn to correctly type their array results.


136-138: Clean public API mapping.

The ClientHooks type provides a clear, model-centric interface by mapping each model name (uncapitalized) to its corresponding query hooks.


142-252: Comprehensive hook interface with delegate model filtering.

The ModelQueryHooks type definition is thorough and correctly:

  • Wraps all hooks with TrimDelegateModelOperations to filter ineligible operations for delegate models
  • Uses ModelMutationModelResult for mutation hooks that return model data
  • Correctly sets Array = true for createManyAndReturn and updateManyAndReturn operations
  • Maintains consistency between query, mutation, and aggregate operations

257-261: Public API aligned with new ClientHooks type.

The return type correctly changed to ClientHooks<Schema>, aligning the public surface with the new typing layer while preserving runtime behavior.


424-431: Behavior is intentional and well-tested—no action needed.

The default getNextPageParam: () => undefined is by design. When this function returns undefined (or null in v5), TanStack Query interprets it as "no next page" and stops pagination. The test at react-query.test.tsx (lines 121–132) explicitly verifies this: calling useInfiniteFindMany with getNextPageParam: () => null produces a single page and hasNextPage = false. This safe-by-default approach requires users to explicitly configure pagination via options if they want multiple pages. The pattern is consistent across all three framework implementations (React, Vue, Svelte), confirming it's intentional.

packages/clients/tanstack-query/src/vue.ts (6)

33-33: LGTM! Imports consistent with React implementation.

The same imports are correctly added to support the Vue typing improvements.

Also applies to: 55-55


85-99: Proper Vue reactivity support for option types.

The option types are correctly wrapped with MaybeRefOrGetter and UnwrapRef to support Vue's reactive values, allowing users to pass refs or computed values as options.


103-113: ModelMutationModelResult correctly adapted for Vue.

The type mirrors the React implementation but uses Vue's ModelMutationResult return type, maintaining consistency across framework integrations.


115-196: Vue hook interface matches React implementation.

The ClientHooks and ModelQueryHooks types are correctly adapted for Vue:

  • Properly wrapped with TrimDelegateModelOperations
  • Uses Vue-specific option types with reactivity support
  • Excludes Suspense variants (not applicable to Vue)
  • Maintains same operation coverage as React

201-205: Public API updated consistently with React.

The return type correctly changed to ClientHooks<Schema>, maintaining parity with the React implementation.


323-332: Same pagination default as React—verify intent.

Line 332 applies the same default getNextPageParam behavior as React. This consistency is good, but the same verification question applies: confirm that disabling pagination by default when options are omitted is the intended behavior.

This mirrors the React implementation behavior—refer to the verification script in the react.ts review.

@claude
Copy link

claude bot commented Nov 5, 2025

Claude finished @ymc9's task —— View job


Code Review: TanStack Query Mutation Typing Improvements

I've completed a comprehensive review of this PR that improves mutation mutateAsync typing across React, Svelte, and Vue TanStack Query integrations.

Todo List:

  • Read repository setup instructions (CLAUDE.md)
  • Analyze the core typing improvements in utils/types.ts
  • Review React implementation changes
  • Review Svelte implementation changes
  • Review Vue implementation changes
  • Examine ORM contract changes
  • Evaluate new test coverage
  • Assess code quality and best practices
  • Check for potential bugs or issues
  • Consider performance implications
  • Review security aspects
  • Provide final comprehensive feedback

🎯 Summary

This is an excellent PR that addresses a critical typing issue with mutateAsync in TanStack Query mutations. The improvements provide better TypeScript inference for mutation return types based on the actual arguments passed to mutateAsync, making the API more type-safe and developer-friendly.

✅ Strengths

1. Consistent Architecture

  • Uniform Implementation: All three frameworks (React, Svelte, Vue) receive identical typing improvements
  • Pattern Consistency: The ModelMutationModelResult type follows the same structure across all implementations
  • Framework-Specific Adaptation: Properly adapts to each framework's specific typing requirements (e.g., Svelte's Readable<> wrapper)

2. Excellent Type Safety

  • Generic Constraint: The new mutateAsync<T extends TArgs>() signature ensures type safety by constraining the generic parameter
  • Return Type Inference: Return type correctly infers based on the specific T parameter, not the broader TArgs
  • Array Handling: Smart conditional typing with Array extends true ? ModelResult<Schema, Model, T>[] : ModelResult<Schema, Model, T>

3. Comprehensive Test Coverage

  • Type-Only Tests: Excellent addition of typing tests that validate TypeScript inference without runtime overhead
  • Error Case Coverage: Proper use of @ts-expect-error to validate that invalid cases are caught by TypeScript
  • Real-World Scenarios: Tests cover practical usage patterns including select, include, and various mutation operations

4. Clean Implementation

  • Minimal Surface Area: Only affects mutation hooks that return model data, not batch operations like createMany
  • Backwards Compatibility: Changes are additive and don't break existing APIs
  • Code Reuse: Smart reuse of existing ModelMutationResult types with targeted overrides

🔧 Technical Implementation Details

Type System Improvements

The core improvement is in packages/clients/tanstack-query/src/utils/types.ts:24-28:

export type TrimDelegateModelOperations<
    Schema extends SchemaDef,
    Model extends GetModels<Schema>,
    T extends Record<string, unknown>,
> = IsDelegateModel<Schema, Model> extends true ? Omit<T, OperationsIneligibleForDelegateModels> : T;

This type correctly handles delegate models by removing operations that aren't applicable to them.

Mutation Typing Enhancement

The key innovation is the ModelMutationModelResult type definition that overrides mutateAsync:

export type ModelMutationModelResult<...> = Omit<ModelMutationResult<...>, 'mutateAsync'> & {
    mutateAsync<T extends TArgs>(
        args: T,
        options?: ModelMutationOptions<ModelResult<Schema, Model, T>, T>,
    ): Promise<Array extends true ? ModelResult<Schema, Model, T>[] : ModelResult<Schema, Model, T>>;
};

This provides precise typing that infers the return type based on the actual arguments passed to mutateAsync.

🛡️ Security & Performance Assessment

Security: ✅ No Concerns

  • No security-sensitive changes
  • All improvements are compile-time only
  • No runtime behavior changes
  • Maintains existing access control patterns

Performance: ✅ Excellent

  • Zero Runtime Impact: All changes are TypeScript-only
  • Build Performance: Typing tests compile efficiently
  • Bundle Size: No impact on final bundle size
  • Type Checking: Well-structured generics shouldn't significantly impact compilation time

🧪 Test Quality Assessment

Comprehensive Coverage

The new typing tests (react-typing-test.ts, svelte-typing-test.ts, vue-typing-test.ts) are exemplary:

  1. Validation of Correct Usage: Tests verify that valid operations type-check correctly
  2. Error Case Testing: Proper use of @ts-expect-error to ensure invalid operations are caught
  3. Edge Cases: Tests cover field selection, inclusion, and various mutation types
  4. Framework-Specific: Each test adapts to the framework's specific patterns (e.g., Svelte's get() wrapper)

📦 Package Management

The version bump to 3.0.0-beta.18 is appropriate for this improvement in a beta release.

🚀 Minor Suggestions for Future Improvements

  1. Documentation: Consider adding JSDoc examples showing the improved typing in action
  2. Performance Monitoring: Consider adding TypeScript compilation time benchmarks for complex schemas
  3. Error Messages: The improved types should provide better error messages when misused

🎯 Conclusion

This is a high-quality PR that significantly improves the developer experience without any drawbacks:

  • Perfect Type Safety: Provides accurate type inference for mutation return types
  • Excellent Testing: Comprehensive typing tests ensure the improvements work correctly
  • Consistent Implementation: Uniform improvements across all three supported frameworks
  • Zero Runtime Impact: Pure TypeScript improvements with no performance cost
  • Backwards Compatible: No breaking changes to existing APIs

The implementation is clean, well-tested, and follows best practices. This PR represents exactly the kind of improvement that makes ZenStack's TanStack Query integration more developer-friendly and type-safe.

Recommendation: ✅ Approve and merge

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: 3

♻️ Duplicate comments (1)
packages/clients/tanstack-query/src/svelte.ts (1)

112-124: mutateAsync return type must include | undefined.

The mutateAsync method promises to return ModelResult (single or array), but the underlying fetcher function can return undefined when read-back policies reject (see packages/clients/tanstack-query/src/utils/common.ts Line 135). Consumers who call mutateAsync and directly access properties on the result will encounter runtime errors when undefined is returned.

Restore the possibility of undefined:

 export type ModelMutationModelResult<
     Schema extends SchemaDef,
     Model extends GetModels<Schema>,
     TArgs extends SelectIncludeOmit<Schema, Model, boolean>,
     Array extends boolean = false,
 > = Readable<
     Omit<UnwrapStore<ModelMutationResult<ModelResult<Schema, Model, TArgs>, TArgs>>, 'mutateAsync'> & {
         mutateAsync<T extends TArgs>(
             args: T,
             options?: ModelMutationOptions<ModelResult<Schema, Model, T>, T>,
-        ): Promise<Array extends true ? ModelResult<Schema, Model, T>[] : ModelResult<Schema, Model, T>>;
+        ): Promise<(Array extends true ? ModelResult<Schema, Model, T>[] : ModelResult<Schema, Model, T>) | undefined>;
     }
 >;
📜 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 9ce9cee and 88c5cc4.

📒 Files selected for processing (4)
  • packages/clients/tanstack-query/src/react.ts (10 hunks)
  • packages/clients/tanstack-query/src/svelte.ts (8 hunks)
  • packages/clients/tanstack-query/src/utils/common.ts (1 hunks)
  • packages/clients/tanstack-query/src/vue.ts (9 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
packages/clients/tanstack-query/src/react.ts (3)
packages/orm/src/client/crud-types.ts (3)
  • SelectIncludeOmit (453-457)
  • ModelResult (135-179)
  • FindArgs (648-664)
packages/clients/tanstack-query/src/utils/types.ts (1)
  • TrimDelegateModelOperations (24-28)
packages/clients/tanstack-query/src/utils/common.ts (3)
  • fetcher (128-150)
  • getQueryKey (171-181)
  • makeUrl (202-214)
packages/clients/tanstack-query/src/svelte.ts (4)
packages/clients/tanstack-query/src/react.ts (8)
  • ModelMutationModelResult (124-134)
  • ModelMutationResult (122-122)
  • ModelMutationOptions (119-120)
  • ClientHooks (136-138)
  • ModelQueryHooks (142-252)
  • ModelQueryOptions (94-94)
  • ModelQueryResult (96-96)
  • useInternalMutation (483-544)
packages/orm/src/client/crud-types.ts (6)
  • SelectIncludeOmit (453-457)
  • ModelResult (135-179)
  • FindUniqueArgs (669-671)
  • SelectSubset (509-515)
  • FindArgs (648-664)
  • Subset (505-507)
packages/clients/tanstack-query/src/utils/types.ts (1)
  • TrimDelegateModelOperations (24-28)
packages/clients/tanstack-query/src/utils/common.ts (3)
  • fetcher (128-150)
  • makeUrl (202-214)
  • ExtraMutationOptions (81-96)
packages/clients/tanstack-query/src/vue.ts (5)
packages/clients/tanstack-query/src/utils/common.ts (1)
  • fetcher (128-150)
packages/schema/src/schema.ts (2)
  • SchemaDef (10-18)
  • GetModels (109-109)
packages/orm/src/client/crud-types.ts (2)
  • SelectIncludeOmit (453-457)
  • ModelResult (135-179)
packages/clients/tanstack-query/src/utils/types.ts (1)
  • TrimDelegateModelOperations (24-28)
packages/common-helpers/src/lower-case-first.ts (1)
  • lowerCaseFirst (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). (3)
  • GitHub Check: claude-review
  • GitHub Check: build-test (20.x, postgresql)
  • GitHub Check: build-test (20.x, sqlite)
🔇 Additional comments (3)
packages/clients/tanstack-query/src/svelte.ts (1)

349-357: Good defensive default for infinite query options.

Providing a safe default getNextPageParam when options is undefined prevents runtime errors and simplifies the API surface.

packages/clients/tanstack-query/src/vue.ts (1)

323-331: Good defensive default for infinite query options.

Providing a safe default getNextPageParam when options is undefined prevents runtime errors and improves API ergonomics.

packages/clients/tanstack-query/src/react.ts (1)

424-430: Good defensive default for infinite query options.

Providing a safe default getNextPageParam when options is undefined prevents runtime errors and improves the developer experience.

@ymc9 ymc9 merged commit 5ff17ce into dev Nov 5, 2025
9 checks passed
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