@@ -65,14 +65,16 @@ import type {
6565} from '@zenstackhq/orm' ;
6666import type { GetModels , SchemaDef } from '@zenstackhq/schema' ;
6767import { createContext , useContext } from 'react' ;
68- import { getAllQueries , invalidateQueriesMatchingPredicate } from './common/client.js' ;
68+ import { getAllQueries , invalidateQueriesMatchingPredicate , normalizeEndpoint } from './common/client.js' ;
6969import { CUSTOM_PROC_ROUTE_NAME } from './common/constants.js' ;
7070import { getQueryKey } from './common/query-key.js' ;
71+ import { makeTransactionMutationFn , makeTransactionOnSuccess } from './common/transaction.js' ;
7172import type {
7273 ExtraMutationOptions ,
7374 ExtraQueryOptions ,
7475 ProcedureReturn ,
7576 QueryContext ,
77+ TransactionOperation ,
7678 TrimSlicedOperations ,
7779 WithOptimistic ,
7880} from './common/types.js' ;
@@ -165,6 +167,12 @@ export type ModelMutationModelResult<
165167 ) : Promise < SimplifiedResult < Schema , Model , T , Options , false , Array , ExtResult > > ;
166168} ;
167169
170+ export type TransactionMutationOptions < Schema extends SchemaDef > = Omit <
171+ UseMutationOptions < unknown [ ] , DefaultError , TransactionOperation < Schema > [ ] > ,
172+ 'mutationFn'
173+ > &
174+ Omit < ExtraMutationOptions , 'optimisticUpdate' | 'optimisticDataProvider' > ;
175+
168176export type ClientHooks <
169177 Schema extends SchemaDef ,
170178 Options extends QueryOptions < Schema > = QueryOptions < Schema > ,
@@ -176,7 +184,13 @@ export type ClientHooks<
176184 Options ,
177185 ExtResult
178186 > ;
179- } & ProcedureHooks < Schema , Options > ;
187+ } & ProcedureHooks < Schema , Options > & {
188+ $transaction : {
189+ useSequential (
190+ options ?: TransactionMutationOptions < Schema > ,
191+ ) : UseMutationResult < unknown [ ] , DefaultError , TransactionOperation < Schema > [ ] > ;
192+ } ;
193+ } ;
180194
181195type ProcedureHookGroup < Schema extends SchemaDef , Options extends QueryOptions < Schema > > = {
182196 [ Name in GetSlicedProcedures < Schema , Options > ] : GetProcedure < Schema , Name > extends { mutation : true }
@@ -448,6 +462,10 @@ export function useClientQueries<SchemaOrClient extends SchemaDef | ClientContra
448462 ( result as any ) . $procs = buildProcedureHooks ( ) ;
449463 }
450464
465+ ( result as any ) . $transaction = {
466+ useSequential : ( hookOptions ?: any ) => useInternalTransactionMutation ( schema , { ...options , ...hookOptions } ) ,
467+ } ;
468+
451469 return result ;
452470}
453471
@@ -789,11 +807,35 @@ export function useInternalMutation<TArgs, R = any>(
789807 return useMutation ( finalOptions ) ;
790808}
791809
810+ export function useInternalTransactionMutation < Schema extends SchemaDef > (
811+ schema : Schema ,
812+ options ?: TransactionMutationOptions < Schema > ,
813+ ) {
814+ const { endpoint, fetch, logging } = useFetchOptions ( options ) ;
815+ const queryClient = useQueryClient ( ) ;
816+
817+ const mutationFn = makeTransactionMutationFn < Schema > ( endpoint , fetch ) ;
818+
819+ const finalOptions = { ...options , mutationFn } ;
820+
821+ if ( options ?. invalidateQueries !== false ) {
822+ const origOnSuccess = finalOptions . onSuccess ;
823+ finalOptions . onSuccess = makeTransactionOnSuccess (
824+ schema ,
825+ ( predicate ) => invalidateQueriesMatchingPredicate ( queryClient , predicate ) ,
826+ logging ,
827+ origOnSuccess as any ,
828+ ) ;
829+ }
830+
831+ return useMutation ( finalOptions ) ;
832+ }
833+
792834function useFetchOptions ( options : QueryContext | undefined ) {
793835 const { endpoint, fetch, logging } = useHooksContext ( ) ;
794836 // options take precedence over context
795837 return {
796- endpoint : options ?. endpoint ?? endpoint ,
838+ endpoint : normalizeEndpoint ( options ?. endpoint ?? endpoint ) ,
797839 fetch : options ?. fetch ?? fetch ,
798840 logging : options ?. logging ?? logging ,
799841 } ;
0 commit comments