@@ -25,7 +25,7 @@ import { match } from 'ts-pattern';
2525import type { GetModels , SchemaDef } from '../../schema' ;
2626import { type ClientImpl } from '../client-impl' ;
2727import { TransactionIsolationLevel , type ClientContract } from '../contract' ;
28- import { InternalError , QueryError } from '../errors' ;
28+ import { InternalError , QueryError , ZenStackError } from '../errors' ;
2929import { stripAlias } from '../kysely-utils' ;
3030import type { AfterEntityMutationCallback , OnKyselyQueryCallback } from '../plugin' ;
3131import { QueryNameMapper } from './name-mapper' ;
@@ -94,7 +94,13 @@ export class ZenStackQueryExecutor<Schema extends SchemaDef> extends DefaultQuer
9494 if ( startedTx ) {
9595 await this . driver . rollbackTransaction ( connection ) ;
9696 }
97- throw err ;
97+ if ( err instanceof ZenStackError ) {
98+ throw err ;
99+ } else {
100+ // wrap error
101+ const message = `Failed to execute query: ${ err } , sql: ${ compiledQuery ?. sql } ` ;
102+ throw new QueryError ( message , err ) ;
103+ }
98104 }
99105 } ) ;
100106 }
@@ -162,84 +168,75 @@ export class ZenStackQueryExecutor<Schema extends SchemaDef> extends DefaultQuer
162168 ) {
163169 let compiled : CompiledQuery | undefined ;
164170
165- try {
166- if ( this . suppressMutationHooks || ! this . isMutationNode ( query ) || ! this . hasEntityMutationPlugins ) {
167- // no need to handle mutation hooks, just proceed
168- const finalQuery = this . nameMapper . transformNode ( query ) ;
169- compiled = this . compileQuery ( finalQuery ) ;
170- if ( parameters ) {
171- compiled = { ...compiled , parameters } ;
172- }
173- return connection . executeQuery < any > ( compiled ) ;
174- }
175-
176- if (
177- ( InsertQueryNode . is ( query ) || UpdateQueryNode . is ( query ) ) &&
178- this . hasEntityMutationPluginsWithAfterMutationHooks
179- ) {
180- // need to make sure the query node has "returnAll" for insert and update queries
181- // so that after-mutation hooks can get the mutated entities with all fields
182- query = {
183- ...query ,
184- returning : ReturningNode . create ( [ SelectionNode . createSelectAll ( ) ] ) ,
185- } ;
186- }
171+ if ( this . suppressMutationHooks || ! this . isMutationNode ( query ) || ! this . hasEntityMutationPlugins ) {
172+ // no need to handle mutation hooks, just proceed
187173 const finalQuery = this . nameMapper . transformNode ( query ) ;
188174 compiled = this . compileQuery ( finalQuery ) ;
189175 if ( parameters ) {
190176 compiled = { ...compiled , parameters } ;
191177 }
178+ return connection . executeQuery < any > ( compiled ) ;
179+ }
192180
193- // the client passed to hooks needs to be in sync with current in-transaction
194- // status so that it doesn't try to create a nested one
195- const currentlyInTx = this . driver . isTransactionConnection ( connection ) ;
181+ if (
182+ ( InsertQueryNode . is ( query ) || UpdateQueryNode . is ( query ) ) &&
183+ this . hasEntityMutationPluginsWithAfterMutationHooks
184+ ) {
185+ // need to make sure the query node has "returnAll" for insert and update queries
186+ // so that after-mutation hooks can get the mutated entities with all fields
187+ query = {
188+ ...query ,
189+ returning : ReturningNode . create ( [ SelectionNode . createSelectAll ( ) ] ) ,
190+ } ;
191+ }
192+ const finalQuery = this . nameMapper . transformNode ( query ) ;
193+ compiled = this . compileQuery ( finalQuery ) ;
194+ if ( parameters ) {
195+ compiled = { ...compiled , parameters } ;
196+ }
196197
197- const connectionClient = this . createClientForConnection ( connection , currentlyInTx ) ;
198+ // the client passed to hooks needs to be in sync with current in-transaction
199+ // status so that it doesn't try to create a nested one
200+ const currentlyInTx = this . driver . isTransactionConnection ( connection ) ;
198201
199- const mutationInfo = this . getMutationInfo ( finalQuery ) ;
202+ const connectionClient = this . createClientForConnection ( connection , currentlyInTx ) ;
200203
201- // cache already loaded before-mutation entities
202- let beforeMutationEntities : Record < string , unknown > [ ] | undefined ;
203- const loadBeforeMutationEntities = async ( ) => {
204- if ( beforeMutationEntities === undefined && ( UpdateQueryNode . is ( query ) || DeleteQueryNode . is ( query ) ) ) {
205- beforeMutationEntities = await this . loadEntities (
206- mutationInfo . model ,
207- mutationInfo . where ,
208- connection ,
209- ) ;
210- }
211- return beforeMutationEntities ;
212- } ;
204+ const mutationInfo = this . getMutationInfo ( finalQuery ) ;
213205
214- // call before mutation hooks
215- await this . callBeforeMutationHooks (
216- finalQuery ,
217- mutationInfo ,
218- loadBeforeMutationEntities ,
219- connectionClient ,
220- queryId ,
221- ) ;
206+ // cache already loaded before- mutation entities
207+ let beforeMutationEntities : Record < string , unknown > [ ] | undefined ;
208+ const loadBeforeMutationEntities = async ( ) => {
209+ if ( beforeMutationEntities === undefined && ( UpdateQueryNode . is ( query ) || DeleteQueryNode . is ( query ) ) ) {
210+ beforeMutationEntities = await this . loadEntities ( mutationInfo . model , mutationInfo . where , connection ) ;
211+ }
212+ return beforeMutationEntities ;
213+ } ;
222214
223- const result = await connection . executeQuery < any > ( compiled ) ;
215+ // call before mutation hooks
216+ await this . callBeforeMutationHooks (
217+ finalQuery ,
218+ mutationInfo ,
219+ loadBeforeMutationEntities ,
220+ connectionClient ,
221+ queryId ,
222+ ) ;
224223
225- if ( ! this . driver . isTransactionConnection ( connection ) ) {
226- // not in a transaction, just call all after-mutation hooks
227- await this . callAfterMutationHooks ( result , finalQuery , mutationInfo , connectionClient , 'all' , queryId ) ;
228- } else {
229- // run after-mutation hooks that are requested to be run inside tx
230- await this . callAfterMutationHooks ( result , finalQuery , mutationInfo , connectionClient , 'inTx' , queryId ) ;
224+ const result = await connection . executeQuery < any > ( compiled ) ;
231225
232- // register other after-mutation hooks to be run after the tx is committed
233- this . driver . registerTransactionCommitCallback ( connection , ( ) =>
234- this . callAfterMutationHooks ( result , finalQuery , mutationInfo , connectionClient , 'outTx' , queryId ) ,
235- ) ;
236- }
226+ if ( ! this . driver . isTransactionConnection ( connection ) ) {
227+ // not in a transaction, just call all after-mutation hooks
228+ await this . callAfterMutationHooks ( result , finalQuery , mutationInfo , connectionClient , 'all' , queryId ) ;
229+ } else {
230+ // run after-mutation hooks that are requested to be run inside tx
231+ await this . callAfterMutationHooks ( result , finalQuery , mutationInfo , connectionClient , 'inTx' , queryId ) ;
237232
238- return result ;
239- } catch ( err ) {
240- const message = `Failed to execute query: ${ err } , sql: ${ compiled ?. sql } ` ;
241- throw new QueryError ( message , err ) ;
233+ // register other after-mutation hooks to be run after the tx is committed
234+ this . driver . registerTransactionCommitCallback ( connection , ( ) =>
235+ this . callAfterMutationHooks ( result , finalQuery , mutationInfo , connectionClient , 'outTx' , queryId ) ,
236+ ) ;
242237 }
238+
239+ return result ;
243240 }
244241
245242 private createClientForConnection ( connection : DatabaseConnection , inTx : boolean ) {
0 commit comments