1- import type { RequestEventData } from '@sentry/core' ;
1+ import type { RequestEventData , WrappedFunction } from '@sentry/core' ;
22import {
33 continueTrace ,
44 fill ,
@@ -12,14 +12,16 @@ import {
1212 withIsolationScope ,
1313} from '@sentry/core' ;
1414import { DEBUG_BUILD } from './debug-build' ;
15- import { captureRemixServerException } from './errors' ;
15+ import { captureRemixServerException , errorHandleDataFunction , errorHandleDocumentRequestFunction } from './errors' ;
1616import { extractData , isDeferredData , isResponse , isRouteErrorResponse , json } from './vendor/response' ;
1717import type {
1818 AppData ,
1919 AppLoadContext ,
2020 CreateRequestHandlerFunction ,
2121 DataFunction ,
2222 DataFunctionArgs ,
23+ EntryContext ,
24+ HandleDocumentRequestFunction ,
2325 RemixRequest ,
2426 RequestHandler ,
2527 ServerBuild ,
@@ -91,6 +93,45 @@ function getTraceAndBaggage(): {
9193 return { } ;
9294}
9395
96+ function makeWrappedDocumentRequestFunction ( ) {
97+ return function ( origDocumentRequestFunction : HandleDocumentRequestFunction ) : HandleDocumentRequestFunction {
98+ return async function (
99+ this : unknown ,
100+ request : Request ,
101+ responseStatusCode : number ,
102+ responseHeaders : Headers ,
103+ context : EntryContext ,
104+ loadContext ?: Record < string , unknown > ,
105+ ) : Promise < Response > {
106+ return errorHandleDocumentRequestFunction . call ( this , origDocumentRequestFunction , {
107+ request,
108+ responseStatusCode,
109+ responseHeaders,
110+ context,
111+ loadContext,
112+ } ) ;
113+ } ;
114+ } ;
115+ }
116+
117+ function makeWrappedDataFunction ( origFn : DataFunction , id : string , name : 'action' | 'loader' ) : DataFunction {
118+ return async function ( this : unknown , args : DataFunctionArgs ) : Promise < Response | AppData > {
119+ return errorHandleDataFunction . call ( this , origFn , name , args ) ;
120+ } ;
121+ }
122+
123+ const makeWrappedAction =
124+ ( id : string ) =>
125+ ( origAction : DataFunction ) : DataFunction => {
126+ return makeWrappedDataFunction ( origAction , id , 'action' ) ;
127+ } ;
128+
129+ const makeWrappedLoader =
130+ ( id : string ) =>
131+ ( origLoader : DataFunction ) : DataFunction => {
132+ return makeWrappedDataFunction ( origLoader , id , 'loader' ) ;
133+ } ;
134+
94135function makeWrappedRootLoader ( ) {
95136 return function ( origLoader : DataFunction ) : DataFunction {
96137 return async function ( this : unknown , args : DataFunctionArgs ) : Promise < Response | AppData > {
@@ -177,9 +218,28 @@ function instrumentBuildCallback(build: ServerBuild): ServerBuild {
177218 const routes : ServerRouteManifest = { } ;
178219 const wrappedEntry = { ...build . entry , module : { ...build . entry . module } } ;
179220
221+ // Not keeping boolean flags like it's done for `requestHandler` functions,
222+ // Because the build can change between build and runtime.
223+ // So if there is a new `loader` or`action` or `documentRequest` after build.
224+ // We should be able to wrap them, as they may not be wrapped before.
225+ const defaultExport = wrappedEntry . module . default as undefined | WrappedFunction ;
226+ if ( defaultExport && ! defaultExport . __sentry_original__ ) {
227+ fill ( wrappedEntry . module , 'default' , makeWrappedDocumentRequestFunction ( ) ) ;
228+ }
229+
180230 for ( const [ id , route ] of Object . entries ( build . routes ) ) {
181231 const wrappedRoute = { ...route , module : { ...route . module } } ;
182232
233+ const routeAction = wrappedRoute . module . action as undefined | WrappedFunction ;
234+ if ( routeAction && ! routeAction . __sentry_original__ ) {
235+ fill ( wrappedRoute . module , 'action' , makeWrappedAction ( id ) ) ;
236+ }
237+
238+ const routeLoader = wrappedRoute . module . loader as undefined | WrappedFunction ;
239+ if ( routeLoader && ! routeLoader . __sentry_original__ ) {
240+ fill ( wrappedRoute . module , 'loader' , makeWrappedLoader ( id ) ) ;
241+ }
242+
183243 // Entry module should have a loader function to provide `sentry-trace` and `baggage`
184244 // They will be available for the root `meta` function as `data.sentryTrace` and `data.sentryBaggage`
185245 if ( ! wrappedRoute . parentId ) {
0 commit comments