{"version":3,"file":"tanstackrouter.js","sources":["../../src/tanstackrouter.ts"],"sourcesContent":["import {\n browserTracingIntegration as originalBrowserTracingIntegration,\n startBrowserTracingNavigationSpan,\n startBrowserTracingPageLoadSpan,\n WINDOW,\n} from '@sentry/browser';\nimport type { Integration } from '@sentry/core';\nimport {\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n} from '@sentry/core';\nimport type { AnyRouter } from '@tanstack/vue-router';\n\ntype RouteMatch = ReturnType[number];\n\n/**\n * A custom browser tracing integration for TanStack Router.\n *\n * The minimum compatible version of `@tanstack/vue-router` is `1.64.0`.\n *\n * @param router A TanStack Router `Router` instance that should be used for routing instrumentation.\n * @param options Sentry browser tracing configuration.\n */\nexport function tanstackRouterBrowserTracingIntegration(\n router: R,\n options: Parameters[0] = {},\n): Integration {\n const browserTracingIntegrationInstance = originalBrowserTracingIntegration({\n ...options,\n instrumentNavigation: false,\n instrumentPageLoad: false,\n });\n\n const { instrumentPageLoad = true, instrumentNavigation = true } = options;\n\n return {\n ...browserTracingIntegrationInstance,\n afterAllSetup(client) {\n browserTracingIntegrationInstance.afterAllSetup(client);\n\n const initialWindowLocation = WINDOW.location;\n if (instrumentPageLoad && initialWindowLocation) {\n const matchedRoutes = router.matchRoutes(\n initialWindowLocation.pathname,\n router.options.parseSearch(initialWindowLocation.search),\n { preload: false, throwOnError: false },\n );\n\n const lastMatch = matchedRoutes[matchedRoutes.length - 1];\n // If we only match __root__, we ended up not matching any route at all, so\n // we fall back to the pathname.\n const routeMatch = lastMatch?.routeId !== '__root__' ? lastMatch : undefined;\n\n startBrowserTracingPageLoadSpan(client, {\n name: routeMatch ? routeMatch.routeId : initialWindowLocation.pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'pageload',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.vue.tanstack_router',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: routeMatch ? 'route' : 'url',\n ...routeMatchToParamSpanAttributes(routeMatch),\n },\n });\n }\n\n if (instrumentNavigation) {\n // The onBeforeNavigate hook is called at the very beginning of a navigation and is only called once per navigation, even when the user is redirected\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n router.subscribe('onBeforeNavigate', (onBeforeNavigateArgs: any) => {\n // onBeforeNavigate is called during pageloads. We can avoid creating navigation spans by:\n // 1. Checking if there's no fromLocation (initial pageload)\n // 2. Comparing the states of the to and from arguments\n\n if (\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n !onBeforeNavigateArgs.fromLocation ||\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n onBeforeNavigateArgs.toLocation.state === onBeforeNavigateArgs.fromLocation.state\n ) {\n return;\n }\n\n const onResolvedMatchedRoutes = router.matchRoutes(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n onBeforeNavigateArgs.toLocation.pathname,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n onBeforeNavigateArgs.toLocation.search,\n { preload: false, throwOnError: false },\n );\n\n const onBeforeNavigateLastMatch = onResolvedMatchedRoutes[onResolvedMatchedRoutes.length - 1];\n const onBeforeNavigateRouteMatch =\n onBeforeNavigateLastMatch?.routeId !== '__root__' ? onBeforeNavigateLastMatch : undefined;\n\n const navigationLocation = WINDOW.location;\n const navigationSpan = startBrowserTracingNavigationSpan(client, {\n name: onBeforeNavigateRouteMatch\n ? onBeforeNavigateRouteMatch.routeId\n : // In SSR/non-browser contexts, WINDOW.location may be undefined, so fall back to the router's location\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n navigationLocation?.pathname || onBeforeNavigateArgs.toLocation.pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.vue.tanstack_router',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: onBeforeNavigateRouteMatch ? 'route' : 'url',\n },\n });\n\n // In case the user is redirected during navigation we want to update the span with the right value.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsubscribeOnResolved = router.subscribe('onResolved', (onResolvedArgs: any) => {\n unsubscribeOnResolved();\n if (navigationSpan) {\n const onResolvedMatchedRoutes = router.matchRoutes(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n onResolvedArgs.toLocation.pathname,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n onResolvedArgs.toLocation.search,\n { preload: false, throwOnError: false },\n );\n\n const onResolvedLastMatch = onResolvedMatchedRoutes[onResolvedMatchedRoutes.length - 1];\n const onResolvedRouteMatch =\n onResolvedLastMatch?.routeId !== '__root__' ? onResolvedLastMatch : undefined;\n\n if (onResolvedRouteMatch) {\n navigationSpan.updateName(onResolvedRouteMatch.routeId);\n navigationSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'route');\n navigationSpan.setAttributes(routeMatchToParamSpanAttributes(onResolvedRouteMatch));\n }\n }\n });\n });\n }\n },\n };\n}\n\nfunction routeMatchToParamSpanAttributes(match: RouteMatch | undefined): Record {\n if (!match) {\n return {};\n }\n\n const paramAttributes: Record = {};\n Object.entries(match.params as Record).forEach(([key, value]) => {\n paramAttributes[`url.path.parameter.${key}`] = value;\n paramAttributes[`params.${key}`] = value; // params.[key] is an alias\n });\n\n return paramAttributes;\n}\n"],"names":["originalBrowserTracingIntegration","onResolvedMatchedRoutes"],"mappings":";;;AAwBO,SAAS,uCAAA,CACd,MAAA,EACA,OAAA,GAAmE,EAAC,EACvD;AACb,EAAA,MAAM,oCAAoCA,yBAAA,CAAkC;AAAA,IAC1E,GAAG,OAAA;AAAA,IACH,oBAAA,EAAsB,KAAA;AAAA,IACtB,kBAAA,EAAoB;AAAA,GACrB,CAAA;AAED,EAAA,MAAM,EAAE,kBAAA,GAAqB,IAAA,EAAM,oBAAA,GAAuB,MAAK,GAAI,OAAA;AAEnE,EAAA,OAAO;AAAA,IACL,GAAG,iCAAA;AAAA,IACH,cAAc,MAAA,EAAQ;AACpB,MAAA,iCAAA,CAAkC,cAAc,MAAM,CAAA;AAEtD,MAAA,MAAM,wBAAwB,MAAA,CAAO,QAAA;AACrC,MAAA,IAAI,sBAAsB,qBAAA,EAAuB;AAC/C,QAAA,MAAM,gBAAgB,MAAA,CAAO,WAAA;AAAA,UAC3B,qBAAA,CAAsB,QAAA;AAAA,UACtB,MAAA,CAAO,OAAA,CAAQ,WAAA,CAAY,qBAAA,CAAsB,MAAM,CAAA;AAAA,UACvD,EAAE,OAAA,EAAS,KAAA,EAAO,YAAA,EAAc,KAAA;AAAM,SACxC;AAEA,QAAA,MAAM,SAAA,GAAY,aAAA,CAAc,aAAA,CAAc,MAAA,GAAS,CAAC,CAAA;AAGxD,QAAA,MAAM,UAAA,GAAa,SAAA,EAAW,OAAA,KAAY,UAAA,GAAa,SAAA,GAAY,MAAA;AAEnE,QAAA,+BAAA,CAAgC,MAAA,EAAQ;AAAA,UACtC,IAAA,EAAM,UAAA,GAAa,UAAA,CAAW,OAAA,GAAU,qBAAA,CAAsB,QAAA;AAAA,UAC9D,UAAA,EAAY;AAAA,YACV,CAAC,4BAA4B,GAAG,UAAA;AAAA,YAChC,CAAC,gCAAgC,GAAG,mCAAA;AAAA,YACpC,CAAC,gCAAgC,GAAG,UAAA,GAAa,OAAA,GAAU,KAAA;AAAA,YAC3D,GAAG,gCAAgC,UAAU;AAAA;AAC/C,SACD,CAAA;AAAA,MACH;AAEA,MAAA,IAAI,oBAAA,EAAsB;AAGxB,QAAA,MAAA,CAAO,SAAA,CAAU,kBAAA,EAAoB,CAAC,oBAAA,KAA8B;AAKlE,UAAA;AAAA;AAAA,YAEE,CAAC,oBAAA,CAAqB,YAAA;AAAA,YAEtB,oBAAA,CAAqB,UAAA,CAAW,KAAA,KAAU,oBAAA,CAAqB,YAAA,CAAa;AAAA,YAC5E;AACA,YAAA;AAAA,UACF;AAEA,UAAA,MAAM,0BAA0B,MAAA,CAAO,WAAA;AAAA;AAAA,YAErC,qBAAqB,UAAA,CAAW,QAAA;AAAA;AAAA,YAEhC,qBAAqB,UAAA,CAAW,MAAA;AAAA,YAChC,EAAE,OAAA,EAAS,KAAA,EAAO,YAAA,EAAc,KAAA;AAAM,WACxC;AAEA,UAAA,MAAM,yBAAA,GAA4B,uBAAA,CAAwB,uBAAA,CAAwB,MAAA,GAAS,CAAC,CAAA;AAC5F,UAAA,MAAM,0BAAA,GACJ,yBAAA,EAA2B,OAAA,KAAY,UAAA,GAAa,yBAAA,GAA4B,MAAA;AAElF,UAAA,MAAM,qBAAqB,MAAA,CAAO,QAAA;AAClC,UAAA,MAAM,cAAA,GAAiB,kCAAkC,MAAA,EAAQ;AAAA,YAC/D,IAAA,EAAM,6BACF,0BAAA,CAA2B,OAAA;AAAA;AAAA;AAAA,cAG3B,kBAAA,EAAoB,QAAA,IAAY,oBAAA,CAAqB,UAAA,CAAW;AAAA,aAAA;AAAA,YACpE,UAAA,EAAY;AAAA,cACV,CAAC,4BAA4B,GAAG,YAAA;AAAA,cAChC,CAAC,gCAAgC,GAAG,qCAAA;AAAA,cACpC,CAAC,gCAAgC,GAAG,0BAAA,GAA6B,OAAA,GAAU;AAAA;AAC7E,WACD,CAAA;AAID,UAAA,MAAM,qBAAA,GAAwB,MAAA,CAAO,SAAA,CAAU,YAAA,EAAc,CAAC,cAAA,KAAwB;AACpF,YAAA,qBAAA,EAAsB;AACtB,YAAA,IAAI,cAAA,EAAgB;AAClB,cAAA,MAAMC,2BAA0B,MAAA,CAAO,WAAA;AAAA;AAAA,gBAErC,eAAe,UAAA,CAAW,QAAA;AAAA;AAAA,gBAE1B,eAAe,UAAA,CAAW,MAAA;AAAA,gBAC1B,EAAE,OAAA,EAAS,KAAA,EAAO,YAAA,EAAc,KAAA;AAAM,eACxC;AAEA,cAAA,MAAM,mBAAA,GAAsBA,wBAAAA,CAAwBA,wBAAAA,CAAwB,MAAA,GAAS,CAAC,CAAA;AACtF,cAAA,MAAM,oBAAA,GACJ,mBAAA,EAAqB,OAAA,KAAY,UAAA,GAAa,mBAAA,GAAsB,MAAA;AAEtE,cAAA,IAAI,oBAAA,EAAsB;AACxB,gBAAA,cAAA,CAAe,UAAA,CAAW,qBAAqB,OAAO,CAAA;AACtD,gBAAA,cAAA,CAAe,YAAA,CAAa,kCAAkC,OAAO,CAAA;AACrE,gBAAA,cAAA,CAAe,aAAA,CAAc,+BAAA,CAAgC,oBAAoB,CAAC,CAAA;AAAA,cACpF;AAAA,YACF;AAAA,UACF,CAAC,CAAA;AAAA,QACH,CAAC,CAAA;AAAA,MACH;AAAA,IACF;AAAA,GACF;AACF;AAEA,SAAS,gCAAgC,KAAA,EAAuD;AAC9F,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,kBAA0C,EAAC;AACjD,EAAA,MAAA,CAAO,OAAA,CAAQ,MAAM,MAAgC,CAAA,CAAE,QAAQ,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AAC/E,IAAA,eAAA,CAAgB,CAAA,mBAAA,EAAsB,GAAG,CAAA,CAAE,CAAA,GAAI,KAAA;AAC/C,IAAA,eAAA,CAAgB,CAAA,OAAA,EAAU,GAAG,CAAA,CAAE,CAAA,GAAI,KAAA;AAAA,EACrC,CAAC,CAAA;AAED,EAAA,OAAO,eAAA;AACT;;;;"}