1
+ /* eslint-disable complexity */
1
2
/* eslint-disable max-lines */
2
3
// Inspired from Donnie McNeal's solution:
3
4
// https://gist.github.com/wontondon/e8c4bdf2888875e4c755712e99279536
@@ -157,24 +158,49 @@ function sendIndexPath(pathBuilder: string, pathname: string, basename: string):
157
158
return [ formattedPath , 'route' ] ;
158
159
}
159
160
160
- function pathEndsWithWildcard ( path : string , branch : RouteMatch < string > ) : boolean {
161
- return ( path . slice ( - 2 ) === '/*' && branch . route . children && branch . route . children . length > 0 ) || false ;
161
+ function pathEndsWithWildcard ( path : string ) : boolean {
162
+ return path . endsWith ( '*' ) ;
162
163
}
163
164
164
165
function pathIsWildcardAndHasChildren ( path : string , branch : RouteMatch < string > ) : boolean {
165
- return ( path === '*' && branch . route . children && branch . route . children . length > 0 ) || false ;
166
+ return ( pathEndsWithWildcard ( path ) && branch . route . children && branch . route . children . length > 0 ) || false ;
167
+ }
168
+
169
+ function pathIsWildcardWithNoChildren ( path : string , branch : RouteMatch < string > ) : boolean {
170
+ return ( pathEndsWithWildcard ( path ) && ( ! branch . route . children || branch . route . children . length === 0 ) ) || false ;
166
171
}
167
172
168
173
function getNormalizedName (
169
174
routes : RouteObject [ ] ,
170
175
location : Location ,
171
176
branches : RouteMatch [ ] ,
172
177
basename : string = '' ,
178
+ allRoutes : RouteObject [ ] = routes ,
173
179
) : [ string , TransactionSource ] {
174
180
if ( ! routes || routes . length === 0 ) {
175
181
return [ _stripBasename ? stripBasenameFromPathname ( location . pathname , basename ) : location . pathname , 'url' ] ;
176
182
}
177
183
184
+ const matchedRoutes = _matchRoutes ( routes , location ) ;
185
+
186
+ if ( matchedRoutes ) {
187
+ const wildCardRoutes : RouteMatch [ ] = matchedRoutes . filter (
188
+ ( match : RouteMatch ) => match . route . path && pathIsWildcardWithNoChildren ( match . route . path , match ) ,
189
+ ) ;
190
+
191
+ for ( const wildCardRoute of wildCardRoutes ) {
192
+ const wildCardRouteMatch = _matchRoutes ( allRoutes , location , wildCardRoute . pathnameBase ) ;
193
+
194
+ if ( wildCardRouteMatch ) {
195
+ const [ name , source ] = getNormalizedName ( wildCardRoutes , location , wildCardRouteMatch , basename , allRoutes ) ;
196
+
197
+ if ( wildCardRoute . pathnameBase && name ) {
198
+ return [ wildCardRoute . pathnameBase + name , source ] ;
199
+ }
200
+ }
201
+ }
202
+ }
203
+
178
204
let pathBuilder = '' ;
179
205
if ( branches ) {
180
206
for ( const branch of branches ) {
@@ -192,7 +218,10 @@ function getNormalizedName(
192
218
pathBuilder += newPath ;
193
219
194
220
// If the path matches the current location, return the path
195
- if ( basename + branch . pathname === location . pathname ) {
221
+ if (
222
+ location . pathname . endsWith ( basename + branch . pathname ) ||
223
+ location . pathname . endsWith ( `${ basename } ${ branch . pathname } /` )
224
+ ) {
196
225
if (
197
226
// If the route defined on the element is something like
198
227
// <Route path="/stores/:storeId/products/:productId" element={<div>Product</div>} />
@@ -201,13 +230,13 @@ function getNormalizedName(
201
230
// eslint-disable-next-line deprecation/deprecation
202
231
getNumberOfUrlSegments ( pathBuilder ) !== getNumberOfUrlSegments ( branch . pathname ) &&
203
232
// We should not count wildcard operators in the url segments calculation
204
- pathBuilder . slice ( - 2 ) !== '/*'
233
+ ! pathEndsWithWildcard ( pathBuilder )
205
234
) {
206
235
return [ ( _stripBasename ? '' : basename ) + newPath , 'route' ] ;
207
236
}
208
237
209
238
// if the last character of the pathbuilder is a wildcard and there are children, remove the wildcard
210
- if ( pathEndsWithWildcard ( pathBuilder , branch ) ) {
239
+ if ( pathIsWildcardAndHasChildren ( pathBuilder , branch ) ) {
211
240
pathBuilder = pathBuilder . slice ( 0 , - 1 ) ;
212
241
}
213
242
@@ -227,13 +256,14 @@ function updatePageloadTransaction(
227
256
routes : RouteObject [ ] ,
228
257
matches ?: AgnosticDataRouteMatch ,
229
258
basename ?: string ,
259
+ allRoutes ?: RouteObject [ ] ,
230
260
) : void {
231
261
const branches = Array . isArray ( matches )
232
262
? matches
233
263
: ( _matchRoutes ( routes , location , basename ) as unknown as RouteMatch [ ] ) ;
234
264
235
265
if ( branches ) {
236
- const [ name , source ] = getNormalizedName ( routes , location , branches , basename ) ;
266
+ const [ name , source ] = getNormalizedName ( routes , location , branches , basename , allRoutes ) ;
237
267
238
268
getCurrentScope ( ) . setTransactionName ( name ) ;
239
269
@@ -250,6 +280,7 @@ function handleNavigation(
250
280
navigationType : Action ,
251
281
matches ?: AgnosticDataRouteMatch ,
252
282
basename ?: string ,
283
+ allRoutes ?: RouteObject [ ] ,
253
284
) : void {
254
285
const branches = Array . isArray ( matches ) ? matches : _matchRoutes ( routes , location , basename ) ;
255
286
@@ -259,7 +290,7 @@ function handleNavigation(
259
290
}
260
291
261
292
if ( ( navigationType === 'PUSH' || navigationType === 'POP' ) && branches ) {
262
- const [ name , source ] = getNormalizedName ( routes , location , branches , basename ) ;
293
+ const [ name , source ] = getNormalizedName ( routes , location , branches , basename , allRoutes ) ;
263
294
264
295
startBrowserTracingNavigationSpan ( client , {
265
296
name,
@@ -272,6 +303,20 @@ function handleNavigation(
272
303
}
273
304
}
274
305
306
+ const getChildRoutesRecursively = ( route : RouteObject ) : RouteObject [ ] => {
307
+ const routes : RouteObject [ ] = [ ] ;
308
+
309
+ if ( route . children ) {
310
+ route . children . forEach ( child => {
311
+ routes . push ( ...getChildRoutesRecursively ( child ) ) ;
312
+ } ) ;
313
+ }
314
+
315
+ routes . push ( route ) ;
316
+
317
+ return routes ;
318
+ } ;
319
+
275
320
// eslint-disable-next-line @typescript-eslint/no-explicit-any
276
321
export function withSentryReactRouterV6Routing < P extends Record < string , any > , R extends React . FC < P > > ( Routes : R ) : R {
277
322
if ( ! _useEffect || ! _useLocation || ! _useNavigationType || ! _createRoutesFromChildren || ! _matchRoutes ) {
@@ -283,6 +328,7 @@ export function withSentryReactRouterV6Routing<P extends Record<string, any>, R
283
328
return Routes ;
284
329
}
285
330
331
+ const allRoutes : RouteObject [ ] = [ ] ;
286
332
let isMountRenderPass : boolean = true ;
287
333
288
334
const SentryRoutes : React . FC < P > = ( props : P ) => {
@@ -293,11 +339,15 @@ export function withSentryReactRouterV6Routing<P extends Record<string, any>, R
293
339
( ) => {
294
340
const routes = _createRoutesFromChildren ( props . children ) as RouteObject [ ] ;
295
341
342
+ routes . forEach ( route => {
343
+ allRoutes . push ( ...getChildRoutesRecursively ( route ) ) ;
344
+ } ) ;
345
+
296
346
if ( isMountRenderPass ) {
297
- updatePageloadTransaction ( getActiveRootSpan ( ) , location , routes ) ;
347
+ updatePageloadTransaction ( getActiveRootSpan ( ) , location , routes , undefined , undefined , allRoutes ) ;
298
348
isMountRenderPass = false ;
299
349
} else {
300
- handleNavigation ( location , routes , navigationType ) ;
350
+ handleNavigation ( location , routes , navigationType , undefined , undefined , allRoutes ) ;
301
351
}
302
352
} ,
303
353
// `props.children` is purposely not included in the dependency array, because we do not want to re-run this effect
@@ -328,6 +378,7 @@ export function wrapUseRoutes(origUseRoutes: UseRoutes): UseRoutes {
328
378
}
329
379
330
380
let isMountRenderPass : boolean = true ;
381
+ const allRoutes : RouteObject [ ] = [ ] ;
331
382
332
383
const SentryRoutes : React . FC < {
333
384
children ?: React . ReactNode ;
@@ -351,11 +402,15 @@ export function wrapUseRoutes(origUseRoutes: UseRoutes): UseRoutes {
351
402
const normalizedLocation =
352
403
typeof stableLocationParam === 'string' ? { pathname : stableLocationParam } : stableLocationParam ;
353
404
405
+ routes . forEach ( route => {
406
+ allRoutes . push ( ...getChildRoutesRecursively ( route ) ) ;
407
+ } ) ;
408
+
354
409
if ( isMountRenderPass ) {
355
- updatePageloadTransaction ( getActiveRootSpan ( ) , normalizedLocation , routes ) ;
410
+ updatePageloadTransaction ( getActiveRootSpan ( ) , normalizedLocation , routes , undefined , undefined , allRoutes ) ;
356
411
isMountRenderPass = false ;
357
412
} else {
358
- handleNavigation ( normalizedLocation , routes , navigationType ) ;
413
+ handleNavigation ( normalizedLocation , routes , navigationType , undefined , undefined , allRoutes ) ;
359
414
}
360
415
} , [ navigationType , stableLocationParam ] ) ;
361
416
0 commit comments