@@ -155,6 +155,9 @@ export class DefaultPrismaProxyHandler implements PrismaProxyHandler {
155
155
}
156
156
}
157
157
158
+ // a marker for filtering error stack trace
159
+ const ERROR_MARKER = '__error_marker__' ;
160
+
158
161
/**
159
162
* Makes a Prisma client proxy.
160
163
*/
@@ -216,9 +219,71 @@ export function makeProxy<T extends PrismaProxyHandler>(
216
219
return undefined ;
217
220
}
218
221
219
- return makeHandler ( target , prop ) ;
222
+ return createHandlerProxy ( makeHandler ( target , prop ) ) ;
220
223
} ,
221
224
} ) ;
222
225
223
226
return proxy ;
224
227
}
228
+
229
+ // A proxy for capturing errors and processing stack trace
230
+ function createHandlerProxy < T extends PrismaProxyHandler > ( handler : T ) : T {
231
+ return new Proxy ( handler , {
232
+ get ( target , propKey ) {
233
+ const prop = target [ propKey as keyof T ] ;
234
+ if ( typeof prop !== 'function' ) {
235
+ return prop ;
236
+ }
237
+
238
+ // eslint-disable-next-line @typescript-eslint/ban-types
239
+ const origMethod = prop as Function ;
240
+ return async function ( ...args : any [ ] ) {
241
+ const _err = new Error ( ERROR_MARKER ) ;
242
+ try {
243
+ return await origMethod . apply ( handler , args ) ;
244
+ } catch ( err ) {
245
+ if ( _err . stack && err instanceof Error ) {
246
+ ( err as any ) . internalStack = err . stack ;
247
+ err . stack = cleanCallStack ( _err . stack , propKey . toString ( ) , err . message ) ;
248
+ }
249
+ throw err ;
250
+ }
251
+ } ;
252
+ } ,
253
+ } ) ;
254
+ }
255
+
256
+ // Filter out @zenstackhq /runtime stack (generated by proxy) from stack trace
257
+ function cleanCallStack ( stack : string , method : string , message : string ) {
258
+ // message line
259
+ let resultStack = `Error calling enhanced Prisma method \`${ method } \`: ${ message } ` ;
260
+
261
+ const lines = stack . split ( '\n' ) ;
262
+ let foundMarker = false ;
263
+
264
+ for ( let i = 0 ; i < lines . length ; i ++ ) {
265
+ const line = lines [ i ] ;
266
+
267
+ if ( ! foundMarker ) {
268
+ // find marker, then stack trace lines follow
269
+ if ( line . includes ( ERROR_MARKER ) ) {
270
+ foundMarker = true ;
271
+ }
272
+ continue ;
273
+ }
274
+
275
+ // skip leading zenstack and anonymous lines
276
+ if ( line . includes ( '@zenstackhq/runtime' ) || line . includes ( '<anonymous>' ) ) {
277
+ continue ;
278
+ }
279
+
280
+ // capture remaining lines
281
+ resultStack += lines
282
+ . slice ( i )
283
+ . map ( ( l ) => '\n' + l )
284
+ . join ( ) ;
285
+ break ;
286
+ }
287
+
288
+ return resultStack ;
289
+ }
0 commit comments