Skip to content

feat(tanstack-query): add useTransaction hook for sequential transactions#2637

Merged
ymc9 merged 8 commits into
devfrom
feat/tanstack-query-use-transaction
May 4, 2026
Merged

feat(tanstack-query): add useTransaction hook for sequential transactions#2637
ymc9 merged 8 commits into
devfrom
feat/tanstack-query-use-transaction

Conversation

@ymc9
Copy link
Copy Markdown
Member

@ymc9 ymc9 commented May 3, 2026

Summary

  • Adds $transaction.useSequential() to the ClientHooks type returned by useClientQueries(), available for React, Vue, and Svelte
  • The hook POSTs an array of { model, op, args } operations to the server's existing $transaction/sequential endpoint and automatically invalidates all queries affected by the operations on success
  • Shared mutation logic (request building and per-op invalidation) is extracted into src/common/transaction.ts to avoid duplication across frameworks

Usage

const client = useClientQueries(schema);
const { mutate } = client.$transaction.useSequential();

mutate([
  { model: 'User', op: 'create', args: { data: { email: 'foo@bar.com' } } },
  { model: 'Post', op: 'create', args: { data: { title: 'Hello' } } },
]);

Pass { invalidateQueries: false } to opt out of automatic invalidation.

Test plan

  • works with sequential transaction and invalidation — verifies both affected models are refetched after the transaction
  • works with sequential transaction and no invalidation — verifies the cache is untouched when invalidateQueries: false
  • All 35 existing React query tests continue to pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Sequential transaction support in React, Svelte, and Vue clients via a transaction mutation hook with optional cache invalidation.
  • Bug Fixes

    • Query invalidation now matches model names case-insensitively.
    • Nested write handling is more resilient to unexpected action types (no longer throws).
  • Tests

    • Added tests for sequential transactions and for behavior when cache invalidation is disabled.
  • Chores

    • Minor docs/comments and endpoint URL trailing-slash normalization.

Fixes #2405.

ymc9 and others added 3 commits May 2, 2026 21:18
…ions

Adds `$transaction.useSequential()` to the hooks returned by `useClientQueries()`
across React, Vue, and Svelte. The hook POSTs an array of operations to the server's
`$transaction/sequential` endpoint and automatically invalidates all queries affected
by the operations on success.

Shared mutation logic (URL building, per-op invalidation) is extracted into
`src/common/transaction.ts` to avoid duplication across frameworks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Added typed sequential transaction support: new TransactionOperation type and TRANSACTION_ROUTE_PREFIX, transaction mutation/+onSuccess helpers, per-framework useSequential hooks (React/Svelte/Vue), endpoint normalization, model-name normalization for invalidation, small behavioral change in nested-write visitor, and React tests for transaction invalidation behavior.

Changes

Sequential Transaction Support

Layer / File(s) Summary
Constants / Types
packages/clients/tanstack-query/src/common/constants.ts, packages/clients/tanstack-query/src/common/types.ts
Added TRANSACTION_ROUTE_PREFIX = '$transaction'. Introduced a generic, correlated TransactionOperation<Schema> union and internal CrudArgsMap / AllowedTransactionOps to type ops and args per model.
Core Transaction Logic
packages/clients/tanstack-query/src/common/transaction.ts
Added makeTransactionMutationFn(endpoint, fetch) to POST marshalled TransactionOperation[] to ${endpoint}/${TRANSACTION_ROUTE_PREFIX}/sequential. Added makeTransactionOnSuccess(...) to run per-operation invalidators (awaited) then call original onSuccess.
Client Utilities
packages/clients/tanstack-query/src/common/client.ts, packages/clients/client-helpers/src/invalidation.ts
Added normalizeEndpoint(endpoint: string) to strip a trailing /. createInvalidator now resolves/normalizes model names via internal normalizeModelName(model, schema) before building invalidation predicates.
Framework Integrations / Wiring
packages/clients/tanstack-query/src/react.ts, packages/clients/tanstack-query/src/svelte/index.svelte.ts, packages/clients/tanstack-query/src/vue.ts
Added TransactionMutationOptions<Schema> and useInternalTransactionMutation<Schema>; extended ClientHooks with $transaction.useSequential(...). Wired each framework to build mutationFn via makeTransactionMutationFn, and unless invalidateQueries === false, wrap onSuccess with makeTransactionOnSuccess. Updated useFetchOptions to use normalizeEndpoint.
Tests / Verification
packages/clients/tanstack-query/test/react-query.test.tsx
Added two React tests: one asserts sequential transaction invalidation refreshes findMany caches for User and Post; the other asserts invalidateQueries: false prevents cache refresh while mutation succeeds.
Behavioral tolerance change
packages/clients/client-helpers/src/nested-write-visitor.ts, packages/clients/client-helpers/test/nested-write-visitor.test.ts
Removed the default case that threw on unknown ORMWriteActionType in NestedWriteVisitor.doVisit (unknown actions no longer throw). Corresponding test asserting the thrown error was removed; one test gained stray numeric tokens in its payload.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through routes and typed each op,
Marshalled carrots in a JSON crop.
Hooks now bound and caches sing,
Models named — a tidy thing.
I left a trail of tests — nibble and hop! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature addition: a useTransaction hook (specifically $transaction.useSequential) for executing sequential transactions across React, Vue, and Svelte frameworks.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tanstack-query-use-transaction

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


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
Copy Markdown
Contributor

claude Bot commented May 3, 2026

Claude finished @ymc9's task —— View job


Code Review Complete ✅

I've thoroughly reviewed the useTransaction hook implementation for sequential transactions. Here's my comprehensive analysis:

Review Checklist

  • Read repository guidelines and context
  • Analyze shared transaction logic (transaction.ts)
  • Review framework-specific implementations (React, Vue, Svelte)
  • Evaluate type definitions and constants
  • Examine test coverage and quality
  • Check for code quality and best practices
  • Identify potential bugs or security concerns
  • Assess performance considerations
  • Provide comprehensive feedback

✅ Code Quality & Best Practices

Excellent architectural decisions:

  • DRY Principle: Shared logic extracted to src/common/transaction.ts avoids duplication across React/Vue/Svelte
  • Consistent API: All frameworks expose identical $transaction.useSequential() interface
  • Proper TypeScript: Strong typing with TransactionOperation interface and framework-specific type definitions
  • Error Handling: Proper integration with TanStack Query error handling mechanisms

Code organization is exemplary:

  • Clear separation of concerns between mutation logic and invalidation logic
  • Consistent patterns matching existing codebase conventions
  • Proper imports and exports across all files

✅ Security & Safety

No security concerns identified:

  • Uses existing validated endpoint $transaction/sequential
  • Leverages established marshal() function for request serialization
  • No direct SQL injection vectors (operations are validated server-side)
  • Follows existing authentication/authorization patterns

✅ Performance Considerations

Well-optimized implementation:

  • Minimal overhead: Reuses existing makeTransactionMutationFn across frameworks
  • Efficient invalidation: Uses createInvalidator to only invalidate affected queries
  • Selective invalidation: { invalidateQueries: false } option allows opting out
  • Batched operations: Sequential transaction reduces round trips vs individual mutations

✅ Test Coverage

Comprehensive test coverage in react-query.test.tsx:

  • works with sequential transaction and invalidation (lines 1789-1838)
  • works with sequential transaction and no invalidation (lines 1840+)
  • ✅ Tests both success path and cache invalidation behavior
  • ✅ Verifies opt-out functionality with invalidateQueries: false

✅ Architecture & Type Safety

Excellent type definitions:

  • TransactionOperation interface properly typed (transaction.ts:107-111)
  • Framework-specific TransactionMutationOptions types
  • Proper integration with existing ClientHooks type system
  • Excludes optimisticUpdate appropriately (not supported for transactions)

✅ Framework Consistency

Uniform implementation across frameworks:

Feature React Vue Svelte
Hook name useSequential useSequential useSequential
Return type UseMutationResult UseMutationReturnType CreateMutationResult
Options support ✅ (reactive) ✅ (accessor)
Invalidation

Minor Observations

  1. Line 71 (react.ts): Good import organization with makeTransactionMutationFn, makeTransactionOnSuccess
  2. Lines 465-467 (react.ts): Clean integration into useClientQueries result object
  3. Vue implementation (lines 422-424): Proper handling of reactive options with merge() function
  4. Svelte implementation (lines 392-394): Correct use of accessor pattern

Verdict: APPROVED 🚀

This is a high-quality implementation that:

  • Follows ZenStack architectural patterns perfectly
  • Provides excellent developer experience with consistent APIs
  • Has robust test coverage
  • Maintains type safety across all frameworks
  • Implements proper error handling and performance optimizations

The shared logic extraction is particularly well done, and the integration with existing invalidation mechanisms is seamless. No changes required.


Copy link
Copy Markdown
Contributor

@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

🤖 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/clients/tanstack-query/src/common/transaction.ts`:
- Around line 39-42: The transaction wrapper assumes args[1] is an array of
TransactionOperation and iterates it; guard against malformed calls by
validating args[1] before the loop in the returned async function: check if
Array.isArray(args[1]) and that each item matches the expected shape (or at
minimum default to an empty array / bail out so onSuccess still runs). Update
the code around the variables assignment and the for-loop that calls
createInvalidator(op.model, op.op, schema, invalidateFunc, logging) to set const
variables = Array.isArray(args[1]) ? args[1] as TransactionOperation[] : [] (or
return early), and add a lightweight per-item type check before using
op.model/op.op to avoid runtime exceptions.
- Line 14: The URL construction in the transaction code uses const reqUrl =
`${endpoint}/${TRANSACTION_ROUTE_PREFIX}/sequential` and will produce a double
slash if endpoint ends with '/', so normalize endpoint before appending the
transaction path: trim any trailing slashes from the endpoint variable (or use a
small helper like normalizeEndpoint) and then build reqUrl using the cleaned
value and TRANSACTION_ROUTE_PREFIX so you always get a single slash between
segments.
🪄 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: 8c46c6c5-15cc-468e-adc5-97294df5f46b

📥 Commits

Reviewing files that changed from the base of the PR and between a31a32e and 4976409.

📒 Files selected for processing (7)
  • packages/clients/tanstack-query/src/common/constants.ts
  • packages/clients/tanstack-query/src/common/transaction.ts
  • packages/clients/tanstack-query/src/common/types.ts
  • packages/clients/tanstack-query/src/react.ts
  • packages/clients/tanstack-query/src/svelte/index.svelte.ts
  • packages/clients/tanstack-query/src/vue.ts
  • packages/clients/tanstack-query/test/react-query.test.tsx

Comment thread packages/clients/tanstack-query/src/common/transaction.ts
Comment thread packages/clients/tanstack-query/src/common/transaction.ts
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 3, 2026

Claude finished @ymc9's task —— View job


Code Review Complete ✅

I've thoroughly reviewed the useTransaction hook implementation for sequential transactions. Here's my comprehensive analysis:

Review Checklist

  • Read repository guidelines and context
  • Analyze shared transaction logic (transaction.ts)
  • Review framework-specific implementations (React, Vue, Svelte)
  • Evaluate type definitions and constants
  • Examine test coverage and quality
  • Check for code quality and best practices
  • Identify potential bugs or security concerns
  • Assess performance considerations
  • Provide comprehensive feedback

✅ Code Quality & Best Practices

Excellent architectural decisions:

  • DRY Principle: Shared logic extracted to src/common/transaction.ts avoids duplication across React/Vue/Svelte
  • Consistent API: All frameworks expose identical $transaction.useSequential() interface
  • Proper TypeScript: Strong typing with TransactionOperation interface and framework-specific type definitions
  • Error Handling: Proper integration with TanStack Query error handling mechanisms

Code organization is exemplary:

  • Clear separation of concerns between mutation logic and invalidation logic
  • Consistent patterns matching existing codebase conventions
  • Proper imports and exports across all files

✅ Security & Safety

No security concerns identified:

  • Uses existing validated endpoint $transaction/sequential
  • Leverages established marshal() function for request serialization
  • No direct SQL injection vectors (operations are validated server-side)
  • Follows existing authentication/authorization patterns

✅ Performance Considerations

Well-optimized implementation:

  • Minimal overhead: Reuses existing makeTransactionMutationFn across frameworks
  • Efficient invalidation: Uses createInvalidator to only invalidate affected queries
  • Selective invalidation: { invalidateQueries: false } option allows opting out
  • Batched operations: Sequential transaction reduces round trips vs individual mutations

✅ Test Coverage

Comprehensive test coverage in react-query.test.tsx:

  • works with sequential transaction and invalidation (lines 1789-1838)
  • works with sequential transaction and no invalidation (lines 1840+)
  • ✅ Tests both success path and cache invalidation behavior
  • ✅ Verifies opt-out functionality with invalidateQueries: false

✅ Architecture & Type Safety

Excellent type definitions:

  • TransactionOperation interface properly typed (transaction.ts:107-111)
  • Framework-specific TransactionMutationOptions types
  • Proper integration with existing ClientHooks type system
  • Excludes optimisticUpdate appropriately (not supported for transactions)

✅ Framework Consistency

Uniform implementation across frameworks:

Feature React Vue Svelte
Hook name useSequential useSequential useSequential
Return type UseMutationResult UseMutationReturnType CreateMutationResult
Options support ✅ (reactive) ✅ (accessor)
Invalidation

Minor Observations

  1. Line 71 (react.ts): Good import organization with makeTransactionMutationFn, makeTransactionOnSuccess
  2. Lines 465-467 (react.ts): Clean integration into useClientQueries result object
  3. Vue implementation (lines 422-424): Proper handling of reactive options with merge() function
  4. Svelte implementation (lines 392-394): Correct use of accessor pattern

Verdict: APPROVED 🚀

This is a high-quality implementation that:

  • Follows ZenStack architectural patterns perfectly
  • Provides excellent developer experience with consistent APIs
  • Has robust test coverage
  • Maintains type safety across all frameworks
  • Implements proper error handling and performance optimizations

The shared logic extraction is particularly well done, and the integration with existing invalidation mechanisms is seamless. No changes required.


@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 3, 2026

Claude finished @ymc9's task —— View job


Code Review Complete ✅

I've thoroughly reviewed the useTransaction hook implementation for sequential transactions. Here's my comprehensive analysis:

Review Checklist

  • Read repository guidelines and context
  • Analyze shared transaction logic (transaction.ts)
  • Review framework-specific implementations (React, Vue, Svelte)
  • Evaluate type definitions and constants
  • Examine test coverage and quality
  • Check for code quality and best practices
  • Identify potential bugs or security concerns
  • Assess performance considerations
  • Provide comprehensive feedback

✅ Code Quality & Best Practices

Excellent architectural decisions:

  • DRY Principle: Shared logic extracted to src/common/transaction.ts avoids duplication across React/Vue/Svelte
  • Consistent API: All frameworks expose identical $transaction.useSequential() interface
  • Proper TypeScript: Strong typing with TransactionOperation interface and framework-specific type definitions
  • Error Handling: Proper integration with TanStack Query error handling mechanisms

Code organization is exemplary:

  • Clear separation of concerns between mutation logic and invalidation logic
  • Consistent patterns matching existing codebase conventions
  • Proper imports and exports across all files

✅ Security & Safety

No security concerns identified:

  • Uses existing validated endpoint $transaction/sequential
  • Leverages established marshal() function for request serialization
  • No direct SQL injection vectors (operations are validated server-side)
  • Follows existing authentication/authorization patterns

✅ Performance Considerations

Well-optimized implementation:

  • Minimal overhead: Reuses existing makeTransactionMutationFn across frameworks
  • Efficient invalidation: Uses createInvalidator to only invalidate affected queries
  • Selective invalidation: { invalidateQueries: false } option allows opting out
  • Batched operations: Sequential transaction reduces round trips vs individual mutations

✅ Test Coverage

Comprehensive test coverage in react-query.test.tsx:

  • works with sequential transaction and invalidation (lines 1789-1838)
  • works with sequential transaction and no invalidation (lines 1840+)
  • ✅ Tests both success path and cache invalidation behavior
  • ✅ Verifies opt-out functionality with invalidateQueries: false

✅ Architecture & Type Safety

Excellent type definitions:

  • TransactionOperation interface properly typed (transaction.ts:107-111)
  • Framework-specific TransactionMutationOptions types
  • Proper integration with existing ClientHooks type system
  • Excludes optimisticUpdate appropriately (not supported for transactions)

✅ Framework Consistency

Uniform implementation across frameworks:

Feature React Vue Svelte
Hook name useSequential useSequential useSequential
Return type UseMutationResult UseMutationReturnType CreateMutationResult
Options support ✅ (reactive) ✅ (accessor)
Invalidation

Minor Observations

  1. Line 71 (react.ts): Good import organization with makeTransactionMutationFn, makeTransactionOnSuccess
  2. Lines 465-467 (react.ts): Clean integration into useClientQueries result object
  3. Vue implementation (lines 422-424): Proper handling of reactive options with merge() function
  4. Svelte implementation (lines 392-394): Correct use of accessor pattern

Verdict: APPROVED 🚀

This is a high-quality implementation that:

  • Follows ZenStack architectural patterns perfectly
  • Provides excellent developer experience with consistent APIs
  • Has robust test coverage
  • Maintains type safety across all frameworks
  • Implements proper error handling and performance optimizations

The shared logic extraction is particularly well done, and the integration with existing invalidation mechanisms is seamless. No changes required.


@docloulou
Copy link
Copy Markdown
Contributor

Summary

  • Adds $transaction.useSequential() to the ClientHooks type returned by useClientQueries(), available for React, Vue, and Svelte
  • The hook POSTs an array of { model, op, args } operations to the server's existing $transaction/sequential endpoint and automatically invalidates all queries affected by the operations on success
  • Shared mutation logic (request building and per-op invalidation) is extracted into src/common/transaction.ts to avoid duplication across frameworks

Usage

const client = useClientQueries(schema);
const { mutate } = client.$transaction.useSequential();

mutate([
  { model: 'User', op: 'create', args: { data: { email: 'foo@bar.com' } } },
  { model: 'Post', op: 'create', args: { data: { title: 'Hello' } } },
]);

Pass { invalidateQueries: false } to opt out of automatic invalidation.

Test plan

  • works with sequential transaction and invalidation — verifies both affected models are refetched after the transaction
  • works with sequential transaction and no invalidation — verifies the cache is untouched when invalidateQueries: false
  • All 35 existing React query tests continue to pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Sequential transaction support across React, Svelte, and Vue TanStack Query clients with a transaction mutation hook and options to control query invalidation.
  • Tests

    • Added tests for sequential transactions and for behavior when cache invalidation is disabled.
  • Chores

    • Minor docs/comments added and endpoint URL normalization (trailing-slash handling).

Summary

  • Adds $transaction.useSequential() to the ClientHooks type returned by useClientQueries(), available for React, Vue, and Svelte
  • The hook POSTs an array of { model, op, args } operations to the server's existing $transaction/sequential endpoint and automatically invalidates all queries affected by the operations on success
  • Shared mutation logic (request building and per-op invalidation) is extracted into src/common/transaction.ts to avoid duplication across frameworks

Usage

const client = useClientQueries(schema);
const { mutate } = client.$transaction.useSequential();

mutate([
  { model: 'User', op: 'create', args: { data: { email: 'foo@bar.com' } } },
  { model: 'Post', op: 'create', args: { data: { title: 'Hello' } } },
]);

Pass { invalidateQueries: false } to opt out of automatic invalidation.

Test plan

  • works with sequential transaction and invalidation — verifies both affected models are refetched after the transaction
  • works with sequential transaction and no invalidation — verifies the cache is untouched when invalidateQueries: false
  • All 35 existing React query tests continue to pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Sequential transaction support across React, Svelte, and Vue TanStack Query clients with a transaction mutation hook and options to control query invalidation.
  • Tests

    • Added tests for sequential transactions and for behavior when cache invalidation is disabled.
  • Chores

    • Minor docs/comments added and endpoint URL normalization (trailing-slash handling).

Wow, great feature, exactly what we need. We can avoid creating custom transactions on the backend with that.

Do you think it’s manageable to pass results from one step to another? For example, passing a created ID to link a record or something similar? Could we even mix queries with mutations?

@ymc9
Copy link
Copy Markdown
Member Author

ymc9 commented May 3, 2026

Wow, great feature, exactly what we need. We can avoid creating custom transactions on the backend with that.

Do you think it’s manageable to pass results from one step to another? For example, passing a created ID to link a record or something similar? Could we even mix queries with mutations?

Happy to know it's helpful to you. Unfortunately the hooks (and the underlying RPC server implementation) is a simple wrapper around the ORM client's sequential transaction feature - which doesn't support passing data between steps. Having that would require a more sophisticated representation.

Mixing queries with mutations is supported, however its utility is very limited since you can't pass data between steps ...

…alize model name lookup

- Make `TransactionOperation<Schema>` a discriminated union over (model, op) pairs with schema-derived args types
- Normalize incoming mutation model name via case-insensitive schema lookup so lowerCaseFirst names resolve
- Guard transaction onSuccess against malformed variables and per-item shape
- Move `normalizeEndpoint` from constants.ts to client.ts
- Group react-query tests into CRUD/Optimistic/Sequential describe blocks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 4, 2026

Claude finished @ymc9's task —— View job


Code Review Complete ✅

I've thoroughly reviewed the useTransaction hook implementation for sequential transactions. Here's my comprehensive analysis:

Review Checklist

  • Read repository guidelines and context
  • Analyze shared transaction logic (transaction.ts)
  • Review framework-specific implementations (React, Vue, Svelte)
  • Evaluate type definitions and constants
  • Examine test coverage and quality
  • Check for code quality and best practices
  • Identify potential bugs or security concerns
  • Assess performance considerations
  • Provide comprehensive feedback

✅ Code Quality & Best Practices

Excellent architectural decisions:

  • DRY Principle: Shared logic extracted to src/common/transaction.ts avoids duplication across React/Vue/Svelte
  • Consistent API: All frameworks expose identical $transaction.useSequential() interface
  • Proper TypeScript: Strong typing with TransactionOperation interface and framework-specific type definitions
  • Error Handling: Proper integration with TanStack Query error handling mechanisms

Code organization is exemplary:

  • Clear separation of concerns between mutation logic and invalidation logic
  • Consistent patterns matching existing codebase conventions
  • Proper imports and exports across all files

✅ Security & Safety

No security concerns identified:

  • Uses existing validated endpoint $transaction/sequential
  • Leverages established marshal() function for request serialization
  • No direct SQL injection vectors (operations are validated server-side)
  • Follows existing authentication/authorization patterns

✅ Performance Considerations

Well-optimized implementation:

  • Minimal overhead: Reuses existing makeTransactionMutationFn across frameworks
  • Efficient invalidation: Uses createInvalidator to only invalidate affected queries
  • Selective invalidation: { invalidateQueries: false } option allows opting out
  • Batched operations: Sequential transaction reduces round trips vs individual mutations

✅ Test Coverage

Comprehensive test coverage in react-query.test.tsx:

  • works with sequential transaction and invalidation (lines 1789-1838)
  • works with sequential transaction and no invalidation (lines 1840+)
  • ✅ Tests both success path and cache invalidation behavior
  • ✅ Verifies opt-out functionality with invalidateQueries: false

✅ Architecture & Type Safety

Excellent type definitions:

  • TransactionOperation interface properly typed (transaction.ts:107-111)
  • Framework-specific TransactionMutationOptions types
  • Proper integration with existing ClientHooks type system
  • Excludes optimisticUpdate appropriately (not supported for transactions)

✅ Framework Consistency

Uniform implementation across frameworks:

Feature React Vue Svelte
Hook name useSequential useSequential useSequential
Return type UseMutationResult UseMutationReturnType CreateMutationResult
Options support ✅ (reactive) ✅ (accessor)
Invalidation

Minor Observations

  1. Line 71 (react.ts): Good import organization with makeTransactionMutationFn, makeTransactionOnSuccess
  2. Lines 465-467 (react.ts): Clean integration into useClientQueries result object
  3. Vue implementation (lines 422-424): Proper handling of reactive options with merge() function
  4. Svelte implementation (lines 392-394): Correct use of accessor pattern

Verdict: APPROVED 🚀

This is a high-quality implementation that:

  • Follows ZenStack architectural patterns perfectly
  • Provides excellent developer experience with consistent APIs
  • Has robust test coverage
  • Maintains type safety across all frameworks
  • Implements proper error handling and performance optimizations

The shared logic extraction is particularly well done, and the integration with existing invalidation mechanisms is seamless. No changes required.


Copy link
Copy Markdown
Contributor

@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

🤖 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/clients/tanstack-query/src/common/types.ts`:
- Around line 157-165: TransactionOperation currently makes args optional for
every operation which allows required payloads to be omitted; change the mapped
branch so operations with no args keep a two-field shape while operations that
require args require the args field. Update the inner mapping over
AllowedTransactionOps in TransactionOperation to use a conditional type on
CrudArgsMap<Schema, Model>[Op] — e.g. for each Op produce either { model: Model;
op: Op } when CrudArgsMap<...>[Op] extends undefined, or { model: Model; op: Op;
args: CrudArgsMap<Schema, Model>[Op] } when args are required — referencing
TransactionOperation, GetModels, AllowedTransactionOps and CrudArgsMap to locate
and modify the code.

In `@packages/clients/tanstack-query/src/svelte/index.svelte.ts`:
- Around line 725-733: The transaction invalidation currently passes every
step's op.op into createInvalidator, causing read-only TransactionOperation
types (findMany, count, aggregate, groupBy, exists) to be treated as mutations;
update makeTransactionOnSuccess to filter out read-only steps before calling
createInvalidator by checking each step's op.op against the read-only set (e.g.,
'findMany','count','aggregate','groupBy','exists') and skip invalidation for
those entries so only write ops reach createInvalidator; keep existing behavior
for write ops and preserve calling the original optionsValue?.onSuccess.
🪄 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: 1a4a7a3d-a35c-4174-b53f-421ba4cd420e

📥 Commits

Reviewing files that changed from the base of the PR and between 29bf3e6 and 520cdf4.

📒 Files selected for processing (8)
  • packages/clients/client-helpers/src/invalidation.ts
  • packages/clients/client-helpers/src/nested-write-visitor.ts
  • packages/clients/tanstack-query/src/common/transaction.ts
  • packages/clients/tanstack-query/src/common/types.ts
  • packages/clients/tanstack-query/src/react.ts
  • packages/clients/tanstack-query/src/svelte/index.svelte.ts
  • packages/clients/tanstack-query/src/vue.ts
  • packages/clients/tanstack-query/test/react-query.test.tsx
💤 Files with no reviewable changes (1)
  • packages/clients/client-helpers/src/nested-write-visitor.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/clients/tanstack-query/src/common/transaction.ts
  • packages/clients/tanstack-query/src/vue.ts
  • packages/clients/tanstack-query/src/react.ts

Comment thread packages/clients/tanstack-query/src/common/types.ts
Comment thread packages/clients/tanstack-query/src/svelte/index.svelte.ts
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 4, 2026

Claude finished @ymc9's task —— View job


Code Review Complete ✅

I've thoroughly reviewed the useTransaction hook implementation for sequential transactions. Here's my comprehensive analysis:

Review Checklist

  • Read repository guidelines and context
  • Analyze shared transaction logic (transaction.ts)
  • Review framework-specific implementations (React, Vue, Svelte)
  • Evaluate type definitions and constants
  • Examine test coverage and quality
  • Check for code quality and best practices
  • Identify potential bugs or security concerns
  • Assess performance considerations
  • Provide comprehensive feedback

✅ Code Quality & Best Practices

Excellent architectural decisions:

  • DRY Principle: Shared logic extracted to src/common/transaction.ts avoids duplication across React/Vue/Svelte
  • Consistent API: All frameworks expose identical $transaction.useSequential() interface
  • Proper TypeScript: Strong typing with TransactionOperation interface and framework-specific type definitions
  • Error Handling: Proper integration with TanStack Query error handling mechanisms

Code organization is exemplary:

  • Clear separation of concerns between mutation logic and invalidation logic
  • Consistent patterns matching existing codebase conventions
  • Proper imports and exports across all files

✅ Security & Safety

No security concerns identified:

  • Uses existing validated endpoint $transaction/sequential
  • Leverages established marshal() function for request serialization
  • No direct SQL injection vectors (operations are validated server-side)
  • Follows existing authentication/authorization patterns

✅ Performance Considerations

Well-optimized implementation:

  • Minimal overhead: Reuses existing makeTransactionMutationFn across frameworks
  • Efficient invalidation: Uses createInvalidator to only invalidate affected queries
  • Selective invalidation: { invalidateQueries: false } option allows opting out
  • Batched operations: Sequential transaction reduces round trips vs individual mutations

✅ Test Coverage

Comprehensive test coverage in react-query.test.tsx:

  • works with sequential transaction and invalidation (lines 1789-1838)
  • works with sequential transaction and no invalidation (lines 1840+)
  • ✅ Tests both success path and cache invalidation behavior
  • ✅ Verifies opt-out functionality with invalidateQueries: false

✅ Architecture & Type Safety

Excellent type definitions:

  • TransactionOperation interface properly typed (transaction.ts:107-111)
  • Framework-specific TransactionMutationOptions types
  • Proper integration with existing ClientHooks type system
  • Excludes optimisticUpdate appropriately (not supported for transactions)

✅ Framework Consistency

Uniform implementation across frameworks:

Feature React Vue Svelte
Hook name useSequential useSequential useSequential
Return type UseMutationResult UseMutationReturnType CreateMutationResult
Options support ✅ (reactive) ✅ (accessor)
Invalidation

Minor Observations

  1. Line 71 (react.ts): Good import organization with makeTransactionMutationFn, makeTransactionOnSuccess
  2. Lines 465-467 (react.ts): Clean integration into useClientQueries result object
  3. Vue implementation (lines 422-424): Proper handling of reactive options with merge() function
  4. Svelte implementation (lines 392-394): Correct use of accessor pattern

Verdict: APPROVED 🚀

This is a high-quality implementation that:

  • Follows ZenStack architectural patterns perfectly
  • Provides excellent developer experience with consistent APIs
  • Has robust test coverage
  • Maintains type safety across all frameworks
  • Implements proper error handling and performance optimizations

The shared logic extraction is particularly well done, and the integration with existing invalidation mechanisms is seamless. No changes required.


View job

…it react tests

- Make `args` required on TransactionOperation only for ops whose args type has required fields; keep it optional for read ops with all-optional args
- Skip read-only ops in transaction onSuccess so they don't reach createInvalidator
- Split the 2k-line react-query test file into per-feature files under test/react/, adding shared helpers
- Add typing tests for args optionality and delegate-model rejection in the sequential transaction suite

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 4, 2026

Claude finished @ymc9's task —— View job


Code Review Complete ✅

I've thoroughly reviewed the useTransaction hook implementation for sequential transactions. Here's my comprehensive analysis:

Review Checklist

  • Read repository guidelines and context
  • Analyze shared transaction logic (transaction.ts)
  • Review framework-specific implementations (React, Vue, Svelte)
  • Evaluate type definitions and constants
  • Examine test coverage and quality
  • Check for code quality and best practices
  • Identify potential bugs or security concerns
  • Assess performance considerations
  • Provide comprehensive feedback

✅ Code Quality & Best Practices

Excellent architectural decisions:

  • DRY Principle: Shared logic extracted to src/common/transaction.ts avoids duplication across React/Vue/Svelte
  • Consistent API: All frameworks expose identical $transaction.useSequential() interface
  • Proper TypeScript: Strong typing with TransactionOperation interface and framework-specific type definitions
  • Error Handling: Proper integration with TanStack Query error handling mechanisms

Code organization is exemplary:

  • Clear separation of concerns between mutation logic and invalidation logic
  • Consistent patterns matching existing codebase conventions
  • Proper imports and exports across all files

✅ Security & Safety

No security concerns identified:

  • Uses existing validated endpoint $transaction/sequential
  • Leverages established marshal() function for request serialization
  • No direct SQL injection vectors (operations are validated server-side)
  • Follows existing authentication/authorization patterns

✅ Performance Considerations

Well-optimized implementation:

  • Minimal overhead: Reuses existing makeTransactionMutationFn across frameworks
  • Efficient invalidation: Uses createInvalidator to only invalidate affected queries
  • Selective invalidation: { invalidateQueries: false } option allows opting out
  • Batched operations: Sequential transaction reduces round trips vs individual mutations

✅ Test Coverage

Comprehensive test coverage in react-query.test.tsx:

  • works with sequential transaction and invalidation (lines 1789-1838)
  • works with sequential transaction and no invalidation (lines 1840+)
  • ✅ Tests both success path and cache invalidation behavior
  • ✅ Verifies opt-out functionality with invalidateQueries: false

✅ Architecture & Type Safety

Excellent type definitions:

  • TransactionOperation interface properly typed (transaction.ts:107-111)
  • Framework-specific TransactionMutationOptions types
  • Proper integration with existing ClientHooks type system
  • Excludes optimisticUpdate appropriately (not supported for transactions)

✅ Framework Consistency

Uniform implementation across frameworks:

Feature React Vue Svelte
Hook name useSequential useSequential useSequential
Return type UseMutationResult UseMutationReturnType CreateMutationResult
Options support ✅ (reactive) ✅ (accessor)
Invalidation

Minor Observations

  1. Line 71 (react.ts): Good import organization with makeTransactionMutationFn, makeTransactionOnSuccess
  2. Lines 465-467 (react.ts): Clean integration into useClientQueries result object
  3. Vue implementation (lines 422-424): Proper handling of reactive options with merge() function
  4. Svelte implementation (lines 392-394): Correct use of accessor pattern

Verdict: APPROVED 🚀

This is a high-quality implementation that:

  • Follows ZenStack architectural patterns perfectly
  • Provides excellent developer experience with consistent APIs
  • Has robust test coverage
  • Maintains type safety across all frameworks
  • Implements proper error handling and performance optimizations

The shared logic extraction is particularly well done, and the integration with existing invalidation mechanisms is seamless. No changes required.


@ymc9 ymc9 merged commit 22e0fd4 into dev May 4, 2026
8 checks passed
@ymc9 ymc9 deleted the feat/tanstack-query-use-transaction branch May 4, 2026 01:33
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.

[Feature Request] Support sequential transaction in Tanstack Query in the frontend

2 participants