@sentry/react-router 10.69.0 → 11.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/client/createClientInstrumentation.js +18 -12
- package/build/cjs/client/createClientInstrumentation.js.map +1 -1
- package/build/cjs/client/hydratedRouter.js +4 -1
- package/build/cjs/client/hydratedRouter.js.map +1 -1
- package/build/cjs/client/tracingIntegration.js +1 -0
- package/build/cjs/client/tracingIntegration.js.map +1 -1
- package/build/cjs/client/utils.js +6 -2
- package/build/cjs/client/utils.js.map +1 -1
- package/build/cjs/index.server.js +0 -4
- package/build/cjs/index.server.js.map +1 -1
- package/build/cjs/server/createSentryHandleRequest.js.map +1 -1
- package/build/cjs/server/createServerInstrumentation.js +71 -65
- package/build/cjs/server/createServerInstrumentation.js.map +1 -1
- package/build/cjs/server/integration/reactRouterServer.js +1 -40
- package/build/cjs/server/integration/reactRouterServer.js.map +1 -1
- package/build/cjs/server/serverBuild.js +0 -4
- package/build/cjs/server/serverBuild.js.map +1 -1
- package/build/cjs/server/serverGlobals.js +0 -9
- package/build/cjs/server/serverGlobals.js.map +1 -1
- package/build/cjs/vite/buildEnd/handleOnBuildEnd.js +26 -14
- package/build/cjs/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
- package/build/cjs/vite/makeCustomSentryVitePlugins.js +29 -10
- package/build/cjs/vite/makeCustomSentryVitePlugins.js.map +1 -1
- package/build/cjs/vite/makeServerBuildCapturePlugin.js +2 -6
- package/build/cjs/vite/makeServerBuildCapturePlugin.js.map +1 -1
- package/build/cjs/vite/plugin.js +2 -0
- package/build/cjs/vite/plugin.js.map +1 -1
- package/build/esm/client/createClientInstrumentation.js +20 -14
- package/build/esm/client/createClientInstrumentation.js.map +1 -1
- package/build/esm/client/hydratedRouter.js +4 -1
- package/build/esm/client/hydratedRouter.js.map +1 -1
- package/build/esm/client/tracingIntegration.js +1 -0
- package/build/esm/client/tracingIntegration.js.map +1 -1
- package/build/esm/client/utils.js +7 -3
- package/build/esm/client/utils.js.map +1 -1
- package/build/esm/index.server.js +0 -2
- package/build/esm/index.server.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/server/createSentryHandleRequest.js.map +1 -1
- package/build/esm/server/createServerInstrumentation.js +73 -67
- package/build/esm/server/createServerInstrumentation.js.map +1 -1
- package/build/esm/server/integration/reactRouterServer.js +3 -41
- package/build/esm/server/integration/reactRouterServer.js.map +1 -1
- package/build/esm/server/serverBuild.js +1 -4
- package/build/esm/server/serverBuild.js.map +1 -1
- package/build/esm/server/serverGlobals.js +1 -8
- package/build/esm/server/serverGlobals.js.map +1 -1
- package/build/esm/vite/buildEnd/handleOnBuildEnd.js +26 -14
- package/build/esm/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
- package/build/esm/vite/makeCustomSentryVitePlugins.js +28 -9
- package/build/esm/vite/makeCustomSentryVitePlugins.js.map +1 -1
- package/build/esm/vite/makeServerBuildCapturePlugin.js +2 -6
- package/build/esm/vite/makeServerBuildCapturePlugin.js.map +1 -1
- package/build/esm/vite/plugin.js +2 -0
- package/build/esm/vite/plugin.js.map +1 -1
- package/build/types/client/createClientInstrumentation.d.ts.map +1 -1
- package/build/types/client/hydratedRouter.d.ts.map +1 -1
- package/build/types/client/tracingIntegration.d.ts.map +1 -1
- package/build/types/client/utils.d.ts.map +1 -1
- package/build/types/index.types.d.ts +1 -0
- package/build/types/index.types.d.ts.map +1 -1
- package/build/types/server/createSentryHandleRequest.d.ts.map +1 -1
- package/build/types/server/createServerInstrumentation.d.ts.map +1 -1
- package/build/types/server/index.d.ts +0 -2
- package/build/types/server/index.d.ts.map +1 -1
- package/build/types/server/integration/reactRouterServer.d.ts +0 -3
- package/build/types/server/integration/reactRouterServer.d.ts.map +1 -1
- package/build/types/server/serverGlobals.d.ts +0 -10
- package/build/types/server/serverGlobals.d.ts.map +1 -1
- package/build/types/vite/buildEnd/handleOnBuildEnd.d.ts.map +1 -1
- package/build/types/vite/makeCustomSentryVitePlugins.d.ts.map +1 -1
- package/build/types/vite/makeServerBuildCapturePlugin.d.ts.map +1 -1
- package/build/types/vite/plugin.d.ts.map +1 -1
- package/build/types/vite/types.d.ts +1 -1
- package/build/types/vite/types.d.ts.map +1 -1
- package/package.json +14 -14
- package/build/cjs/server/instrumentation/reactRouter.js +0 -106
- package/build/cjs/server/instrumentation/reactRouter.js.map +0 -1
- package/build/cjs/server/instrumentation/util.js +0 -24
- package/build/cjs/server/instrumentation/util.js.map +0 -1
- package/build/cjs/server/wrapServerAction.js +0 -56
- package/build/cjs/server/wrapServerAction.js.map +0 -1
- package/build/cjs/server/wrapServerLoader.js +0 -56
- package/build/cjs/server/wrapServerLoader.js.map +0 -1
- package/build/esm/server/instrumentation/reactRouter.js +0 -104
- package/build/esm/server/instrumentation/reactRouter.js.map +0 -1
- package/build/esm/server/instrumentation/util.js +0 -18
- package/build/esm/server/instrumentation/util.js.map +0 -1
- package/build/esm/server/wrapServerAction.js +0 -54
- package/build/esm/server/wrapServerAction.js.map +0 -1
- package/build/esm/server/wrapServerLoader.js +0 -54
- package/build/esm/server/wrapServerLoader.js.map +0 -1
- package/build/types/server/instrumentation/reactRouter.d.ts +0 -19
- package/build/types/server/instrumentation/reactRouter.d.ts.map +0 -1
- package/build/types/server/instrumentation/util.d.ts +0 -31
- package/build/types/server/instrumentation/util.d.ts.map +0 -1
- package/build/types/server/wrapServerAction.d.ts +0 -33
- package/build/types/server/wrapServerAction.d.ts.map +0 -1
- package/build/types/server/wrapServerLoader.d.ts +0 -33
- package/build/types/server/wrapServerLoader.d.ts.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const vite = require('@sentry/bundler-plugins/vite');
|
|
4
4
|
|
|
5
5
|
async function makeCustomSentryVitePlugins(options) {
|
|
6
6
|
const {
|
|
@@ -15,7 +15,15 @@ async function makeCustomSentryVitePlugins(options) {
|
|
|
15
15
|
reactComponentAnnotation,
|
|
16
16
|
release
|
|
17
17
|
} = options;
|
|
18
|
-
const
|
|
18
|
+
const unstableSourcemapsDisable = unstable_sentryVitePluginOptions?.sourcemaps?.disable;
|
|
19
|
+
if (unstableSourcemapsDisable !== void 0 && unstableSourcemapsDisable !== true) {
|
|
20
|
+
console.warn(
|
|
21
|
+
`[Sentry] \`unstable_sentryVitePluginOptions.sourcemaps.disable: ${JSON.stringify(
|
|
22
|
+
unstableSourcemapsDisable
|
|
23
|
+
)}\` does not apply to the Vite plugin. Debug ID injection and source map upload are handled by the \`sentryOnBuildEnd\` hook for React Router, so letting the Vite plugin do it as well would inject a second debug ID per chunk. The option still applies to \`sentryOnBuildEnd\`.`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
const sentryVitePlugins = vite.sentryVitePlugin({
|
|
19
27
|
applicationKey,
|
|
20
28
|
authToken: authToken ?? process.env.SENTRY_AUTH_TOKEN,
|
|
21
29
|
bundleSizeOptimizations,
|
|
@@ -23,27 +31,38 @@ async function makeCustomSentryVitePlugins(options) {
|
|
|
23
31
|
org: org ?? process.env.SENTRY_ORG,
|
|
24
32
|
project: project ?? process.env.SENTRY_PROJECT,
|
|
25
33
|
telemetry: telemetry ?? true,
|
|
34
|
+
// Spread here so it can override the plain options above, but not the objects
|
|
35
|
+
// merged below - object spread replaces whole keys rather than deep-merging.
|
|
36
|
+
...unstable_sentryVitePluginOptions,
|
|
26
37
|
_metaOptions: {
|
|
38
|
+
...unstable_sentryVitePluginOptions?._metaOptions,
|
|
27
39
|
telemetry: {
|
|
40
|
+
...unstable_sentryVitePluginOptions?._metaOptions?.telemetry,
|
|
28
41
|
metaFramework: "react-router"
|
|
29
|
-
}
|
|
30
|
-
...unstable_sentryVitePluginOptions?._metaOptions
|
|
42
|
+
}
|
|
31
43
|
},
|
|
32
44
|
reactComponentAnnotation: {
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
// Only assign when set, as an explicit `undefined` would erase the unstable value
|
|
46
|
+
...reactComponentAnnotation?.enabled !== void 0 && { enabled: reactComponentAnnotation.enabled },
|
|
47
|
+
...reactComponentAnnotation?.ignoredComponents !== void 0 && {
|
|
48
|
+
ignoredComponents: reactComponentAnnotation.ignoredComponents
|
|
49
|
+
},
|
|
35
50
|
...unstable_sentryVitePluginOptions?.reactComponentAnnotation
|
|
36
51
|
},
|
|
37
52
|
release: {
|
|
38
53
|
...unstable_sentryVitePluginOptions?.release,
|
|
39
54
|
...release
|
|
40
55
|
},
|
|
41
|
-
// will be handled in buildEnd hook
|
|
42
56
|
sourcemaps: {
|
|
57
|
+
...unstable_sentryVitePluginOptions?.sourcemaps,
|
|
58
|
+
// Injection and upload are handled in the buildEnd hook, so the Vite plugin must
|
|
59
|
+
// never do it too. This is deliberately not overridable - see the warning above.
|
|
43
60
|
disable: true,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
61
|
+
// The plugin deletes these in a `finally` block that runs regardless of `disable`,
|
|
62
|
+
// which would remove the maps before `sentryOnBuildEnd` gets to upload them.
|
|
63
|
+
// Deletion is handled there instead, from the same option.
|
|
64
|
+
filesToDeleteAfterUpload: void 0
|
|
65
|
+
}
|
|
47
66
|
});
|
|
48
67
|
return sentryVitePlugins;
|
|
49
68
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"makeCustomSentryVitePlugins.js","sources":["../../../src/vite/makeCustomSentryVitePlugins.ts"],"sourcesContent":["import { sentryVitePlugin } from '@sentry/vite
|
|
1
|
+
{"version":3,"file":"makeCustomSentryVitePlugins.js","sources":["../../../src/vite/makeCustomSentryVitePlugins.ts"],"sourcesContent":["import { sentryVitePlugin } from '@sentry/bundler-plugins/vite';\nimport { type Plugin } from 'vite';\nimport type { SentryReactRouterBuildOptions } from './types';\n\n/**\n * Create a custom subset of sentry's vite plugins\n */\nexport async function makeCustomSentryVitePlugins(options: SentryReactRouterBuildOptions): Promise<Plugin[]> {\n const {\n debug,\n unstable_sentryVitePluginOptions,\n bundleSizeOptimizations,\n applicationKey,\n authToken,\n org,\n project,\n telemetry,\n reactComponentAnnotation,\n release,\n } = options;\n\n const unstableSourcemapsDisable = unstable_sentryVitePluginOptions?.sourcemaps?.disable;\n\n // Anything other than `true` would have the Vite plugin inject debug IDs on top of the\n // ones `sentryOnBuildEnd` injects, which breaks source map resolution. The value still\n // applies to the buildEnd hook - only the Vite plugin ignores it.\n if (unstableSourcemapsDisable !== undefined && unstableSourcemapsDisable !== true) {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] \\`unstable_sentryVitePluginOptions.sourcemaps.disable: ${JSON.stringify(\n unstableSourcemapsDisable,\n )}\\` does not apply to the Vite plugin. Debug ID injection and source map upload are handled by the \\`sentryOnBuildEnd\\` hook for React Router, so letting the Vite plugin do it as well would inject a second debug ID per chunk. The option still applies to \\`sentryOnBuildEnd\\`.`,\n );\n }\n\n const sentryVitePlugins = sentryVitePlugin({\n applicationKey,\n authToken: authToken ?? process.env.SENTRY_AUTH_TOKEN,\n bundleSizeOptimizations,\n debug: debug ?? false,\n org: org ?? process.env.SENTRY_ORG,\n project: project ?? process.env.SENTRY_PROJECT,\n telemetry: telemetry ?? true,\n // Spread here so it can override the plain options above, but not the objects\n // merged below - object spread replaces whole keys rather than deep-merging.\n ...unstable_sentryVitePluginOptions,\n _metaOptions: {\n ...unstable_sentryVitePluginOptions?._metaOptions,\n telemetry: {\n ...unstable_sentryVitePluginOptions?._metaOptions?.telemetry,\n metaFramework: 'react-router',\n },\n },\n reactComponentAnnotation: {\n // Only assign when set, as an explicit `undefined` would erase the unstable value\n ...(reactComponentAnnotation?.enabled !== undefined && { enabled: reactComponentAnnotation.enabled }),\n ...(reactComponentAnnotation?.ignoredComponents !== undefined && {\n ignoredComponents: reactComponentAnnotation.ignoredComponents,\n }),\n ...unstable_sentryVitePluginOptions?.reactComponentAnnotation,\n },\n release: {\n ...unstable_sentryVitePluginOptions?.release,\n ...release,\n },\n sourcemaps: {\n ...unstable_sentryVitePluginOptions?.sourcemaps,\n // Injection and upload are handled in the buildEnd hook, so the Vite plugin must\n // never do it too. This is deliberately not overridable - see the warning above.\n disable: true,\n // The plugin deletes these in a `finally` block that runs regardless of `disable`,\n // which would remove the maps before `sentryOnBuildEnd` gets to upload them.\n // Deletion is handled there instead, from the same option.\n filesToDeleteAfterUpload: undefined,\n },\n }) as Plugin[];\n\n return sentryVitePlugins;\n}\n"],"names":["sentryVitePlugin"],"mappings":";;;;AAOA,eAAsB,4BAA4B,OAAA,EAA2D;AAC3G,EAAA,MAAM;AAAA,IACJ,KAAA;AAAA,IACA,gCAAA;AAAA,IACA,uBAAA;AAAA,IACA,cAAA;AAAA,IACA,SAAA;AAAA,IACA,GAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAA;AAAA,IACA,wBAAA;AAAA,IACA;AAAA,GACF,GAAI,OAAA;AAEJ,EAAA,MAAM,yBAAA,GAA4B,kCAAkC,UAAA,EAAY,OAAA;AAKhF,EAAA,IAAI,yBAAA,KAA8B,MAAA,IAAa,yBAAA,KAA8B,IAAA,EAAM;AAEjF,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,mEAAmE,IAAA,CAAK,SAAA;AAAA,QACtE;AAAA,OACD,CAAA,kRAAA;AAAA,KACH;AAAA,EACF;AAEA,EAAA,MAAM,oBAAoBA,qBAAA,CAAiB;AAAA,IACzC,cAAA;AAAA,IACA,SAAA,EAAW,SAAA,IAAa,OAAA,CAAQ,GAAA,CAAI,iBAAA;AAAA,IACpC,uBAAA;AAAA,IACA,OAAO,KAAA,IAAS,KAAA;AAAA,IAChB,GAAA,EAAK,GAAA,IAAO,OAAA,CAAQ,GAAA,CAAI,UAAA;AAAA,IACxB,OAAA,EAAS,OAAA,IAAW,OAAA,CAAQ,GAAA,CAAI,cAAA;AAAA,IAChC,WAAW,SAAA,IAAa,IAAA;AAAA;AAAA;AAAA,IAGxB,GAAG,gCAAA;AAAA,IACH,YAAA,EAAc;AAAA,MACZ,GAAG,gCAAA,EAAkC,YAAA;AAAA,MACrC,SAAA,EAAW;AAAA,QACT,GAAG,kCAAkC,YAAA,EAAc,SAAA;AAAA,QACnD,aAAA,EAAe;AAAA;AACjB,KACF;AAAA,IACA,wBAAA,EAA0B;AAAA;AAAA,MAExB,GAAI,wBAAA,EAA0B,OAAA,KAAY,UAAa,EAAE,OAAA,EAAS,yBAAyB,OAAA,EAAQ;AAAA,MACnG,GAAI,wBAAA,EAA0B,iBAAA,KAAsB,MAAA,IAAa;AAAA,QAC/D,mBAAmB,wBAAA,CAAyB;AAAA,OAC9C;AAAA,MACA,GAAG,gCAAA,EAAkC;AAAA,KACvC;AAAA,IACA,OAAA,EAAS;AAAA,MACP,GAAG,gCAAA,EAAkC,OAAA;AAAA,MACrC,GAAG;AAAA,KACL;AAAA,IACA,UAAA,EAAY;AAAA,MACV,GAAG,gCAAA,EAAkC,UAAA;AAAA;AAAA;AAAA,MAGrC,OAAA,EAAS,IAAA;AAAA;AAAA;AAAA;AAAA,MAIT,wBAAA,EAA0B;AAAA;AAC5B,GACD,CAAA;AAED,EAAA,OAAO,iBAAA;AACT;;;;"}
|
|
@@ -4,15 +4,11 @@ const serverBuild = require('../server/serverBuild.js');
|
|
|
4
4
|
|
|
5
5
|
const SERVER_BUILD_MODULE_ID = "virtual:react-router/server-build";
|
|
6
6
|
function makeServerBuildCapturePlugin() {
|
|
7
|
-
let isSsrBuild = false;
|
|
8
7
|
return {
|
|
9
8
|
name: "sentry-react-router-server-build-capture",
|
|
10
9
|
enforce: "post",
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
transform(code, id) {
|
|
15
|
-
if (!isSsrBuild) {
|
|
10
|
+
transform(code, id, options) {
|
|
11
|
+
if (!options?.ssr) {
|
|
16
12
|
return null;
|
|
17
13
|
}
|
|
18
14
|
if (!id.includes(SERVER_BUILD_MODULE_ID)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"makeServerBuildCapturePlugin.js","sources":["../../../src/vite/makeServerBuildCapturePlugin.ts"],"sourcesContent":["import { type Plugin } from 'vite';\nimport { GLOBAL_KEY } from '../server/serverBuild';\n\nconst SERVER_BUILD_MODULE_ID = 'virtual:react-router/server-build';\n\n/**\n * A Sentry plugin for React Router to capture the server build for middleware name resolution.\n */\nexport function makeServerBuildCapturePlugin(): Plugin {\n
|
|
1
|
+
{"version":3,"file":"makeServerBuildCapturePlugin.js","sources":["../../../src/vite/makeServerBuildCapturePlugin.ts"],"sourcesContent":["import { type Plugin } from 'vite';\nimport { GLOBAL_KEY } from '../server/serverBuild';\n\nconst SERVER_BUILD_MODULE_ID = 'virtual:react-router/server-build';\n\n/**\n * A Sentry plugin for React Router to capture the server build for middleware name resolution.\n */\nexport function makeServerBuildCapturePlugin(): Plugin {\n return {\n name: 'sentry-react-router-server-build-capture',\n enforce: 'post',\n\n transform(code, id, options) {\n // Only inject into the server build module when transforming for the SSR environment.\n // `options.ssr` is set for the SSR module in both dev (`react-router dev`) and production\n // builds, so this covers both - unlike `config.build.ssr`, which is only true during a build.\n if (!options?.ssr) {\n return null;\n }\n\n if (!id.includes(SERVER_BUILD_MODULE_ID)) {\n return null;\n }\n\n // `routes` is a module-scope export in the virtual:react-router/server-build module\n const injectedCode = `${code}\nif (typeof globalThis !== 'undefined' && typeof globalThis[\"${GLOBAL_KEY}\"] === 'function') {\n globalThis[\"${GLOBAL_KEY}\"]({ routes });\n}\n`;\n\n return { code: injectedCode, map: null };\n },\n };\n}\n"],"names":["GLOBAL_KEY"],"mappings":";;;;AAGA,MAAM,sBAAA,GAAyB,mCAAA;AAKxB,SAAS,4BAAA,GAAuC;AACrD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,0CAAA;AAAA,IACN,OAAA,EAAS,MAAA;AAAA,IAET,SAAA,CAAU,IAAA,EAAM,EAAA,EAAI,OAAA,EAAS;AAI3B,MAAA,IAAI,CAAC,SAAS,GAAA,EAAK;AACjB,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,IAAI,CAAC,EAAA,CAAG,QAAA,CAAS,sBAAsB,CAAA,EAAG;AACxC,QAAA,OAAO,IAAA;AAAA,MACT;AAGA,MAAA,MAAM,YAAA,GAAe,GAAG,IAAI;AAAA,4DAAA,EAC4BA,sBAAU,CAAA;AAAA,cAAA,EACxDA,sBAAU,CAAA;AAAA;AAAA,CAAA;AAIpB,MAAA,OAAO,EAAE,IAAA,EAAM,YAAA,EAAc,GAAA,EAAK,IAAA,EAAK;AAAA,IACzC;AAAA,GACF;AACF;;;;"}
|
package/build/cjs/vite/plugin.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
|
+
const vite = require('@sentry/server-utils/orchestrion/vite');
|
|
3
4
|
const makeConfigInjectorPlugin = require('./makeConfigInjectorPlugin.js');
|
|
4
5
|
const makeCustomSentryVitePlugins = require('./makeCustomSentryVitePlugins.js');
|
|
5
6
|
const makeEnableSourceMapsPlugin = require('./makeEnableSourceMapsPlugin.js');
|
|
@@ -10,6 +11,7 @@ async function sentryReactRouter(options = {}, viteConfig) {
|
|
|
10
11
|
plugins.push(makeConfigInjectorPlugin.makeConfigInjectorPlugin(options));
|
|
11
12
|
plugins.push(makeServerBuildCapturePlugin.makeServerBuildCapturePlugin());
|
|
12
13
|
if (process.env.NODE_ENV !== "development" && viteConfig.command === "build" && viteConfig.mode !== "development") {
|
|
14
|
+
plugins.push(vite.sentryOrchestrionPlugin({ buildTimeInstrumentation: options.buildTimeInstrumentation }));
|
|
13
15
|
plugins.push(makeEnableSourceMapsPlugin.makeEnableSourceMapsPlugin(options));
|
|
14
16
|
plugins.push(...await makeCustomSentryVitePlugins.makeCustomSentryVitePlugins(options));
|
|
15
17
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["../../../src/vite/plugin.ts"],"sourcesContent":["import type { ConfigEnv, Plugin } from 'vite';\nimport { makeConfigInjectorPlugin } from './makeConfigInjectorPlugin';\nimport { makeCustomSentryVitePlugins } from './makeCustomSentryVitePlugins';\nimport { makeEnableSourceMapsPlugin } from './makeEnableSourceMapsPlugin';\nimport { makeServerBuildCapturePlugin } from './makeServerBuildCapturePlugin';\nimport type { SentryReactRouterBuildOptions } from './types';\n\n/**\n * A Vite plugin for Sentry that handles source map uploads and bundle size optimizations.\n *\n * @param options - Configuration options for the Sentry Vite plugin\n * @param viteConfig - The Vite user config object\n * @returns An array of Vite plugins\n */\nexport async function sentryReactRouter(\n options: SentryReactRouterBuildOptions = {},\n viteConfig: ConfigEnv,\n): Promise<Plugin[]> {\n const plugins: Plugin[] = [];\n\n plugins.push(makeConfigInjectorPlugin(options));\n plugins.push(makeServerBuildCapturePlugin());\n\n if (process.env.NODE_ENV !== 'development' && viteConfig.command === 'build' && viteConfig.mode !== 'development') {\n plugins.push(makeEnableSourceMapsPlugin(options));\n plugins.push(...(await makeCustomSentryVitePlugins(options)));\n }\n\n return plugins;\n}\n"],"names":["makeConfigInjectorPlugin","makeServerBuildCapturePlugin","makeEnableSourceMapsPlugin","makeCustomSentryVitePlugins"],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["../../../src/vite/plugin.ts"],"sourcesContent":["import { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/vite';\nimport type { ConfigEnv, Plugin } from 'vite';\nimport { makeConfigInjectorPlugin } from './makeConfigInjectorPlugin';\nimport { makeCustomSentryVitePlugins } from './makeCustomSentryVitePlugins';\nimport { makeEnableSourceMapsPlugin } from './makeEnableSourceMapsPlugin';\nimport { makeServerBuildCapturePlugin } from './makeServerBuildCapturePlugin';\nimport type { SentryReactRouterBuildOptions } from './types';\n\n/**\n * A Vite plugin for Sentry that handles source map uploads and bundle size optimizations.\n *\n * @param options - Configuration options for the Sentry Vite plugin\n * @param viteConfig - The Vite user config object\n * @returns An array of Vite plugins\n */\nexport async function sentryReactRouter(\n options: SentryReactRouterBuildOptions = {},\n viteConfig: ConfigEnv,\n): Promise<Plugin[]> {\n const plugins: Plugin[] = [];\n\n plugins.push(makeConfigInjectorPlugin(options));\n plugins.push(makeServerBuildCapturePlugin());\n\n if (process.env.NODE_ENV !== 'development' && viteConfig.command === 'build' && viteConfig.mode !== 'development') {\n plugins.push(sentryOrchestrionPlugin({ buildTimeInstrumentation: options.buildTimeInstrumentation }));\n plugins.push(makeEnableSourceMapsPlugin(options));\n plugins.push(...(await makeCustomSentryVitePlugins(options)));\n }\n\n return plugins;\n}\n"],"names":["makeConfigInjectorPlugin","makeServerBuildCapturePlugin","sentryOrchestrionPlugin","makeEnableSourceMapsPlugin","makeCustomSentryVitePlugins"],"mappings":";;;;;;;;AAeA,eAAsB,iBAAA,CACpB,OAAA,GAAyC,EAAC,EAC1C,UAAA,EACmB;AACnB,EAAA,MAAM,UAAoB,EAAC;AAE3B,EAAA,OAAA,CAAQ,IAAA,CAAKA,iDAAA,CAAyB,OAAO,CAAC,CAAA;AAC9C,EAAA,OAAA,CAAQ,IAAA,CAAKC,2DAA8B,CAAA;AAE3C,EAAA,IAAI,OAAA,CAAQ,IAAI,QAAA,KAAa,aAAA,IAAiB,WAAW,OAAA,KAAY,OAAA,IAAW,UAAA,CAAW,IAAA,KAAS,aAAA,EAAe;AACjH,IAAA,OAAA,CAAQ,KAAKC,4BAAA,CAAwB,EAAE,0BAA0B,OAAA,CAAQ,wBAAA,EAA0B,CAAC,CAAA;AACpG,IAAA,OAAA,CAAQ,IAAA,CAAKC,qDAAA,CAA2B,OAAO,CAAC,CAAA;AAChD,IAAA,OAAA,CAAQ,IAAA,CAAK,GAAI,MAAMC,uDAAA,CAA4B,OAAO,CAAE,CAAA;AAAA,EAC9D;AAEA,EAAA,OAAO,OAAA;AACT;;;;"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { startBrowserTracingNavigationSpan, getAbsoluteUrl } from '@sentry/browser';
|
|
2
|
-
import { debug, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
|
|
2
|
+
import { debug, startSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_STATUS_ERROR, GLOBAL_OBJ, getClient, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, filterCollectedUrl, getActiveSpan, getRootSpan, spanToJSON, updateSpanName } from '@sentry/core';
|
|
3
3
|
import { DEBUG_BUILD } from '../common/debug-build.js';
|
|
4
4
|
import { captureInstrumentationError, getPathFromRequest, normalizeRoutePath, getPattern } from '../common/utils.js';
|
|
5
5
|
import { updateNavigationSpanUrlFromLocation, finalizeNavigationSpanFromHydratedRouter, resolveNavigateArg, resolveNavigateAbsoluteUrl } from './utils.js';
|
|
6
|
-
import { URL_TEMPLATE } from '@sentry/conventions/attributes';
|
|
6
|
+
import { CODE_FUNCTION_NAME, SENTRY_OP, URL_FULL, URL_TEMPLATE } from '@sentry/conventions/attributes';
|
|
7
|
+
import { GENERAL_FUNCTION_SPAN_OP, WEB_SERVER_MIDDLEWARE_SPAN_OP } from '@sentry/conventions/op';
|
|
7
8
|
|
|
8
9
|
const WINDOW = GLOBAL_OBJ;
|
|
9
10
|
let currentNumericNavigationSpan;
|
|
@@ -57,7 +58,7 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
57
58
|
const result2 = await callNavigate();
|
|
58
59
|
if (result2.status === "error" && result2.error instanceof Error) {
|
|
59
60
|
captureInstrumentationError(result2, captureErrors, "react_router.navigate", {
|
|
60
|
-
|
|
61
|
+
[URL_FULL]: filterCollectedUrl(info.currentUrl)
|
|
61
62
|
});
|
|
62
63
|
}
|
|
63
64
|
return;
|
|
@@ -94,7 +95,7 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
94
95
|
navigationSpan2.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
95
96
|
}
|
|
96
97
|
captureInstrumentationError(result2, captureErrors, "react_router.navigate", {
|
|
97
|
-
|
|
98
|
+
[URL_FULL]: WINDOW.location?.pathname || filterCollectedUrl(info.currentUrl)
|
|
98
99
|
});
|
|
99
100
|
}
|
|
100
101
|
} finally {
|
|
@@ -126,7 +127,7 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
126
127
|
navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
127
128
|
}
|
|
128
129
|
captureInstrumentationError(result, captureErrors, "react_router.navigate", {
|
|
129
|
-
|
|
130
|
+
[URL_FULL]: filterCollectedUrl(toPath)
|
|
130
131
|
});
|
|
131
132
|
}
|
|
132
133
|
return;
|
|
@@ -136,7 +137,8 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
136
137
|
{
|
|
137
138
|
name: `Fetcher ${info.fetcherKey}`,
|
|
138
139
|
attributes: {
|
|
139
|
-
[
|
|
140
|
+
[SENTRY_OP]: GENERAL_FUNCTION_SPAN_OP,
|
|
141
|
+
[CODE_FUNCTION_NAME]: "fetcher",
|
|
140
142
|
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
141
143
|
}
|
|
142
144
|
},
|
|
@@ -145,7 +147,7 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
145
147
|
if (result.status === "error" && result.error instanceof Error) {
|
|
146
148
|
span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
147
149
|
captureInstrumentationError(result, captureErrors, "react_router.fetcher", {
|
|
148
|
-
|
|
150
|
+
[URL_FULL]: filterCollectedUrl(info.href)
|
|
149
151
|
});
|
|
150
152
|
}
|
|
151
153
|
}
|
|
@@ -165,7 +167,8 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
165
167
|
{
|
|
166
168
|
name: routePattern,
|
|
167
169
|
attributes: {
|
|
168
|
-
[
|
|
170
|
+
[SENTRY_OP]: GENERAL_FUNCTION_SPAN_OP,
|
|
171
|
+
[CODE_FUNCTION_NAME]: "clientLoader",
|
|
169
172
|
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
170
173
|
}
|
|
171
174
|
},
|
|
@@ -174,7 +177,7 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
174
177
|
if (result.status === "error" && result.error instanceof Error) {
|
|
175
178
|
span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
176
179
|
captureInstrumentationError(result, captureErrors, "react_router.client_loader", {
|
|
177
|
-
|
|
180
|
+
[URL_FULL]: urlPath
|
|
178
181
|
});
|
|
179
182
|
}
|
|
180
183
|
}
|
|
@@ -189,7 +192,8 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
189
192
|
{
|
|
190
193
|
name: routePattern,
|
|
191
194
|
attributes: {
|
|
192
|
-
[
|
|
195
|
+
[SENTRY_OP]: GENERAL_FUNCTION_SPAN_OP,
|
|
196
|
+
[CODE_FUNCTION_NAME]: "clientAction",
|
|
193
197
|
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
194
198
|
}
|
|
195
199
|
},
|
|
@@ -198,7 +202,7 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
198
202
|
if (result.status === "error" && result.error instanceof Error) {
|
|
199
203
|
span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
200
204
|
captureInstrumentationError(result, captureErrors, "react_router.client_action", {
|
|
201
|
-
|
|
205
|
+
[URL_FULL]: urlPath
|
|
202
206
|
});
|
|
203
207
|
}
|
|
204
208
|
}
|
|
@@ -218,7 +222,8 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
218
222
|
{
|
|
219
223
|
name: `middleware ${routeId}`,
|
|
220
224
|
attributes: {
|
|
221
|
-
[
|
|
225
|
+
[SENTRY_OP]: WEB_SERVER_MIDDLEWARE_SPAN_OP,
|
|
226
|
+
[CODE_FUNCTION_NAME]: "clientMiddleware",
|
|
222
227
|
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api",
|
|
223
228
|
"react_router.route.id": routeId,
|
|
224
229
|
"http.route": routePattern,
|
|
@@ -230,7 +235,7 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
230
235
|
if (result.status === "error" && result.error instanceof Error) {
|
|
231
236
|
span.setStatus({ code: SPAN_STATUS_ERROR, message: "internal_error" });
|
|
232
237
|
captureInstrumentationError(result, captureErrors, "react_router.client_middleware", {
|
|
233
|
-
|
|
238
|
+
[URL_FULL]: urlPath
|
|
234
239
|
});
|
|
235
240
|
}
|
|
236
241
|
}
|
|
@@ -241,7 +246,8 @@ function createSentryClientInstrumentation(options = {}) {
|
|
|
241
246
|
{
|
|
242
247
|
name: "Lazy Route Load",
|
|
243
248
|
attributes: {
|
|
244
|
-
[
|
|
249
|
+
[SENTRY_OP]: GENERAL_FUNCTION_SPAN_OP,
|
|
250
|
+
[CODE_FUNCTION_NAME]: "lazy",
|
|
245
251
|
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
|
|
246
252
|
}
|
|
247
253
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createClientInstrumentation.js","sources":["../../../src/client/createClientInstrumentation.ts"],"sourcesContent":["// oxlint-disable max-lines\nimport { getAbsoluteUrl, startBrowserTracingNavigationSpan } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport {\n debug,\n getActiveSpan,\n getClient,\n getRootSpan,\n GLOBAL_OBJ,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n spanToJSON,\n SPAN_STATUS_ERROR,\n startSpan,\n updateSpanName,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport type { ClientInstrumentation, InstrumentableRoute, InstrumentableRouter } from '../common/types';\nimport { captureInstrumentationError, getPathFromRequest, getPattern, normalizeRoutePath } from '../common/utils';\nimport {\n resolveNavigateAbsoluteUrl,\n resolveNavigateArg,\n finalizeNavigationSpanFromHydratedRouter,\n updateNavigationSpanUrlFromLocation,\n} from './utils';\nimport { URL_TEMPLATE } from '@sentry/conventions/attributes';\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\n// Tracks active numeric navigation span to prevent duplicate spans when popstate fires\nlet currentNumericNavigationSpan: Span | undefined;\n\n// Per-request middleware counters, keyed by Request\nconst middlewareCountersMap = new WeakMap<object, Record<string, number>>();\n\nconst SENTRY_CLIENT_INSTRUMENTATION_FLAG = '__sentryReactRouterClientInstrumentationUsed';\n// Intentionally never reset - once set, instrumentation API handles all navigations for the session.\nconst SENTRY_NAVIGATE_HOOK_INVOKED_FLAG = '__sentryReactRouterNavigateHookInvoked';\nconst SENTRY_POPSTATE_LISTENER_ADDED_FLAG = '__sentryReactRouterPopstateListenerAdded';\n\ntype GlobalObjWithFlags = typeof GLOBAL_OBJ & {\n [SENTRY_CLIENT_INSTRUMENTATION_FLAG]?: boolean;\n [SENTRY_NAVIGATE_HOOK_INVOKED_FLAG]?: boolean;\n [SENTRY_POPSTATE_LISTENER_ADDED_FLAG]?: boolean;\n};\n\nconst GLOBAL_WITH_FLAGS = GLOBAL_OBJ as GlobalObjWithFlags;\n\n/**\n * Options for creating Sentry client instrumentation.\n */\nexport interface CreateSentryClientInstrumentationOptions {\n /**\n * Whether to capture errors from loaders/actions automatically.\n * Set to `false` to avoid duplicates if using custom error handlers.\n * @default true\n */\n captureErrors?: boolean;\n}\n\n/**\n * Creates a Sentry client instrumentation for React Router's instrumentation API.\n */\nexport function createSentryClientInstrumentation(\n options: CreateSentryClientInstrumentationOptions = {},\n): ClientInstrumentation {\n const { captureErrors = true } = options;\n\n DEBUG_BUILD && debug.log('React Router client instrumentation API created.');\n\n return {\n router(router: InstrumentableRouter) {\n // Set the flag when React Router actually invokes our instrumentation.\n // This ensures the flag is only set in Library Mode (where hooks run),\n // not in Framework Mode (where hooks are never called).\n // See: https://github.com/remix-run/react-router/discussions/13749\n GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG] = true;\n DEBUG_BUILD && debug.log('React Router client instrumentation API router hook registered.');\n\n // Add popstate listener for browser back/forward navigation (persists for session, one listener only)\n if (!GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] && WINDOW.addEventListener) {\n GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] = true;\n\n WINDOW.addEventListener('popstate', () => {\n const client = getClient();\n if (!client) {\n currentNumericNavigationSpan = undefined;\n return;\n }\n\n const pathname = WINDOW.location?.pathname || '/';\n\n // If there's an active numeric navigation span, update it instead of creating a duplicate\n if (currentNumericNavigationSpan) {\n if (currentNumericNavigationSpan.isRecording()) {\n updateNavigationSpanUrlFromLocation(currentNumericNavigationSpan);\n }\n currentNumericNavigationSpan = undefined;\n return;\n }\n\n // Only create a new span for actual browser back/forward button clicks\n startBrowserTracingNavigationSpan(\n client,\n {\n name: pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': 'browser.popstate',\n },\n },\n { url: getAbsoluteUrl(pathname) },\n );\n });\n\n DEBUG_BUILD && debug.log('React Router popstate listener registered for browser back/forward navigation.');\n }\n\n router.instrument({\n async navigate(callNavigate, info) {\n // navigate(0) triggers a page reload - skip span creation, but still capture errors\n // (navigation can be rejected before reload, e.g., by a navigation guard)\n if (info.to === 0) {\n const result = await callNavigate();\n if (result.status === 'error' && result.error instanceof Error) {\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n 'http.url': info.currentUrl,\n });\n }\n return;\n }\n\n GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG] = true;\n\n // Handle numeric navigations (navigate(-1), navigate(1), etc.)\n if (typeof info.to === 'number') {\n const client = getClient();\n let navigationSpan;\n\n if (client) {\n const navigationType = info.to < 0 ? 'router.back' : 'router.forward';\n const currentPathname = WINDOW.location?.pathname || info.currentUrl;\n\n navigationSpan = startBrowserTracingNavigationSpan(\n client,\n {\n name: currentPathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': navigationType,\n },\n },\n { url: getAbsoluteUrl(currentPathname) },\n );\n\n // Store ref so popstate listener can update it instead of creating a duplicate\n currentNumericNavigationSpan = navigationSpan;\n }\n\n try {\n const result = await callNavigate();\n\n if (navigationSpan && WINDOW.location) {\n finalizeNavigationSpanFromHydratedRouter(navigationSpan);\n }\n\n if (result.status === 'error' && result.error instanceof Error) {\n if (navigationSpan) {\n navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n }\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n 'http.url': WINDOW.location?.pathname || info.currentUrl,\n });\n }\n } finally {\n currentNumericNavigationSpan = undefined;\n }\n return;\n }\n\n // Handle string/object navigations (e.g., navigate('/about') or navigate({ pathname: '/about' }))\n const client = getClient();\n const toPath = resolveNavigateArg(info.to);\n let navigationSpan;\n\n if (client) {\n navigationSpan = startBrowserTracingNavigationSpan(\n client,\n {\n name: toPath,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': 'router.navigate',\n },\n },\n { url: resolveNavigateAbsoluteUrl(info.to, info.currentUrl) },\n );\n }\n\n const result = await callNavigate();\n if (result.status === 'error' && result.error instanceof Error) {\n if (navigationSpan) {\n navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n }\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n 'http.url': toPath,\n });\n }\n return;\n },\n\n async fetch(callFetch, info) {\n await startSpan(\n {\n name: `Fetcher ${info.fetcherKey}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.fetcher',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callFetch();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.fetcher', {\n 'http.url': info.href,\n });\n }\n },\n );\n },\n });\n },\n\n route(route: InstrumentableRoute) {\n const routeId = route.id;\n\n route.instrument({\n async loader(callLoader, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = normalizeRoutePath(getPattern(info));\n const routePattern = pattern || urlPath;\n // Parameterize the active navigation root span. (Route hooks don't fire on initial\n // pageload, so this only affects navigations.)\n updateRootSpanRoute(routePattern, !!pattern);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_loader',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLoader();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.client_loader', {\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async action(callAction, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = normalizeRoutePath(getPattern(info));\n const routePattern = pattern || urlPath;\n updateRootSpanRoute(routePattern, !!pattern);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_action',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callAction();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.client_action', {\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async middleware(callMiddleware, info) {\n const urlPath = getPathFromRequest(info.request);\n const routePattern = normalizeRoutePath(getPattern(info)) || urlPath;\n\n let counters = middlewareCountersMap.get(info.request);\n if (!counters) {\n counters = {};\n middlewareCountersMap.set(info.request, counters);\n }\n\n const middlewareIndex = counters[routeId] ?? 0;\n counters[routeId] = middlewareIndex + 1;\n\n await startSpan(\n {\n name: `middleware ${routeId}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_middleware',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n 'react_router.route.id': routeId,\n 'http.route': routePattern,\n 'react_router.middleware.index': middlewareIndex,\n },\n },\n async span => {\n const result = await callMiddleware();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.client_middleware', {\n 'http.url': urlPath,\n });\n }\n },\n );\n },\n\n async lazy(callLazy) {\n await startSpan(\n {\n name: 'Lazy Route Load',\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'function.react_router.client_lazy',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLazy();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.client_lazy', {});\n }\n },\n );\n },\n });\n },\n };\n}\n\n/**\n * Updates the active navigation/pageload root span name with the parameterized route, so the\n * transaction reflects the parameterized route pattern (e.g. `/users/:id`).\n */\nfunction updateRootSpanRoute(routeName: string, hasPattern: boolean): void {\n if (!hasPattern) {\n return;\n }\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan && getRootSpan(activeSpan);\n if (!rootSpan) {\n return;\n }\n\n const { op } = spanToJSON(rootSpan);\n if (op !== 'navigation' && op !== 'pageload') {\n return;\n }\n\n updateSpanName(rootSpan, routeName);\n rootSpan.setAttributes({ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route', [URL_TEMPLATE]: routeName });\n}\n\n/**\n * Check if React Router's instrumentation API is being used on the client.\n */\nexport function isClientInstrumentationApiUsed(): boolean {\n return !!GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG];\n}\n\n/**\n * Check if React Router's instrumentation API's navigate hook was invoked.\n */\nexport function isNavigateHookInvoked(): boolean {\n return !!GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG];\n}\n"],"names":["result","client","navigationSpan"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createClientInstrumentation.js","sources":["../../../src/client/createClientInstrumentation.ts"],"sourcesContent":["// oxlint-disable max-lines\nimport { getAbsoluteUrl, startBrowserTracingNavigationSpan } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport {\n debug,\n getActiveSpan,\n getClient,\n getRootSpan,\n GLOBAL_OBJ,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n spanToJSON,\n SPAN_STATUS_ERROR,\n startSpan,\n updateSpanName,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport type { ClientInstrumentation, InstrumentableRoute, InstrumentableRouter } from '../common/types';\nimport { captureInstrumentationError, getPathFromRequest, getPattern, normalizeRoutePath } from '../common/utils';\nimport {\n resolveNavigateAbsoluteUrl,\n resolveNavigateArg,\n finalizeNavigationSpanFromHydratedRouter,\n updateNavigationSpanUrlFromLocation,\n} from './utils';\nimport { CODE_FUNCTION_NAME, SENTRY_OP, URL_FULL, URL_TEMPLATE } from '@sentry/conventions/attributes';\nimport { GENERAL_FUNCTION_SPAN_OP, WEB_SERVER_MIDDLEWARE_SPAN_OP } from '@sentry/conventions/op';\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\n// Tracks active numeric navigation span to prevent duplicate spans when popstate fires\nlet currentNumericNavigationSpan: Span | undefined;\n\n// Per-request middleware counters, keyed by Request\nconst middlewareCountersMap = new WeakMap<object, Record<string, number>>();\n\nconst SENTRY_CLIENT_INSTRUMENTATION_FLAG = '__sentryReactRouterClientInstrumentationUsed';\n// Intentionally never reset - once set, instrumentation API handles all navigations for the session.\nconst SENTRY_NAVIGATE_HOOK_INVOKED_FLAG = '__sentryReactRouterNavigateHookInvoked';\nconst SENTRY_POPSTATE_LISTENER_ADDED_FLAG = '__sentryReactRouterPopstateListenerAdded';\n\ntype GlobalObjWithFlags = typeof GLOBAL_OBJ & {\n [SENTRY_CLIENT_INSTRUMENTATION_FLAG]?: boolean;\n [SENTRY_NAVIGATE_HOOK_INVOKED_FLAG]?: boolean;\n [SENTRY_POPSTATE_LISTENER_ADDED_FLAG]?: boolean;\n};\n\nconst GLOBAL_WITH_FLAGS = GLOBAL_OBJ as GlobalObjWithFlags;\n\n/**\n * Options for creating Sentry client instrumentation.\n */\nexport interface CreateSentryClientInstrumentationOptions {\n /**\n * Whether to capture errors from loaders/actions automatically.\n * Set to `false` to avoid duplicates if using custom error handlers.\n * @default true\n */\n captureErrors?: boolean;\n}\n\n/**\n * Creates a Sentry client instrumentation for React Router's instrumentation API.\n */\nexport function createSentryClientInstrumentation(\n options: CreateSentryClientInstrumentationOptions = {},\n): ClientInstrumentation {\n const { captureErrors = true } = options;\n\n DEBUG_BUILD && debug.log('React Router client instrumentation API created.');\n\n return {\n router(router: InstrumentableRouter) {\n // Set the flag when React Router actually invokes our instrumentation.\n // This ensures the flag is only set in Library Mode (where hooks run),\n // not in Framework Mode (where hooks are never called).\n // See: https://github.com/remix-run/react-router/discussions/13749\n GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG] = true;\n DEBUG_BUILD && debug.log('React Router client instrumentation API router hook registered.');\n\n // Add popstate listener for browser back/forward navigation (persists for session, one listener only)\n if (!GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] && WINDOW.addEventListener) {\n GLOBAL_WITH_FLAGS[SENTRY_POPSTATE_LISTENER_ADDED_FLAG] = true;\n\n WINDOW.addEventListener('popstate', () => {\n const client = getClient();\n if (!client) {\n currentNumericNavigationSpan = undefined;\n return;\n }\n\n const pathname = WINDOW.location?.pathname || '/';\n\n // If there's an active numeric navigation span, update it instead of creating a duplicate\n if (currentNumericNavigationSpan) {\n if (currentNumericNavigationSpan.isRecording()) {\n updateNavigationSpanUrlFromLocation(currentNumericNavigationSpan);\n }\n currentNumericNavigationSpan = undefined;\n return;\n }\n\n // Only create a new span for actual browser back/forward button clicks\n startBrowserTracingNavigationSpan(\n client,\n {\n name: pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': 'browser.popstate',\n },\n },\n { url: getAbsoluteUrl(pathname) },\n );\n });\n\n DEBUG_BUILD && debug.log('React Router popstate listener registered for browser back/forward navigation.');\n }\n\n router.instrument({\n async navigate(callNavigate, info) {\n // navigate(0) triggers a page reload - skip span creation, but still capture errors\n // (navigation can be rejected before reload, e.g., by a navigation guard)\n if (info.to === 0) {\n const result = await callNavigate();\n if (result.status === 'error' && result.error instanceof Error) {\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n [URL_FULL]: filterCollectedUrl(info.currentUrl),\n });\n }\n return;\n }\n\n GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG] = true;\n\n // Handle numeric navigations (navigate(-1), navigate(1), etc.)\n if (typeof info.to === 'number') {\n const client = getClient();\n let navigationSpan;\n\n if (client) {\n const navigationType = info.to < 0 ? 'router.back' : 'router.forward';\n const currentPathname = WINDOW.location?.pathname || info.currentUrl;\n\n navigationSpan = startBrowserTracingNavigationSpan(\n client,\n {\n name: currentPathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': navigationType,\n },\n },\n { url: getAbsoluteUrl(currentPathname) },\n );\n\n // Store ref so popstate listener can update it instead of creating a duplicate\n currentNumericNavigationSpan = navigationSpan;\n }\n\n try {\n const result = await callNavigate();\n\n if (navigationSpan && WINDOW.location) {\n finalizeNavigationSpanFromHydratedRouter(navigationSpan);\n }\n\n if (result.status === 'error' && result.error instanceof Error) {\n if (navigationSpan) {\n navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n }\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n [URL_FULL]: WINDOW.location?.pathname || filterCollectedUrl(info.currentUrl),\n });\n }\n } finally {\n currentNumericNavigationSpan = undefined;\n }\n return;\n }\n\n // Handle string/object navigations (e.g., navigate('/about') or navigate({ pathname: '/about' }))\n const client = getClient();\n const toPath = resolveNavigateArg(info.to);\n let navigationSpan;\n\n if (client) {\n navigationSpan = startBrowserTracingNavigationSpan(\n client,\n {\n name: toPath,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router.instrumentation_api',\n 'navigation.type': 'router.navigate',\n },\n },\n { url: resolveNavigateAbsoluteUrl(info.to, info.currentUrl) },\n );\n }\n\n const result = await callNavigate();\n if (result.status === 'error' && result.error instanceof Error) {\n if (navigationSpan) {\n navigationSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n }\n captureInstrumentationError(result, captureErrors, 'react_router.navigate', {\n [URL_FULL]: filterCollectedUrl(toPath),\n });\n }\n return;\n },\n\n async fetch(callFetch, info) {\n await startSpan(\n {\n name: `Fetcher ${info.fetcherKey}`,\n attributes: {\n [SENTRY_OP]: GENERAL_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'fetcher',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callFetch();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.fetcher', {\n [URL_FULL]: filterCollectedUrl(info.href),\n });\n }\n },\n );\n },\n });\n },\n\n route(route: InstrumentableRoute) {\n const routeId = route.id;\n\n route.instrument({\n async loader(callLoader, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = normalizeRoutePath(getPattern(info));\n const routePattern = pattern || urlPath;\n // Parameterize the active navigation root span. (Route hooks don't fire on initial\n // pageload, so this only affects navigations.)\n updateRootSpanRoute(routePattern, !!pattern);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: GENERAL_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'clientLoader',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLoader();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.client_loader', {\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async action(callAction, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = normalizeRoutePath(getPattern(info));\n const routePattern = pattern || urlPath;\n updateRootSpanRoute(routePattern, !!pattern);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: GENERAL_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'clientAction',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callAction();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.client_action', {\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async middleware(callMiddleware, info) {\n const urlPath = getPathFromRequest(info.request);\n const routePattern = normalizeRoutePath(getPattern(info)) || urlPath;\n\n let counters = middlewareCountersMap.get(info.request);\n if (!counters) {\n counters = {};\n middlewareCountersMap.set(info.request, counters);\n }\n\n const middlewareIndex = counters[routeId] ?? 0;\n counters[routeId] = middlewareIndex + 1;\n\n await startSpan(\n {\n name: `middleware ${routeId}`,\n attributes: {\n [SENTRY_OP]: WEB_SERVER_MIDDLEWARE_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'clientMiddleware',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n 'react_router.route.id': routeId,\n 'http.route': routePattern,\n 'react_router.middleware.index': middlewareIndex,\n },\n },\n async span => {\n const result = await callMiddleware();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.client_middleware', {\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async lazy(callLazy) {\n await startSpan(\n {\n name: 'Lazy Route Load',\n attributes: {\n [SENTRY_OP]: GENERAL_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'lazy',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n },\n },\n async span => {\n const result = await callLazy();\n if (result.status === 'error' && result.error instanceof Error) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.client_lazy', {});\n }\n },\n );\n },\n });\n },\n };\n}\n\n/**\n * Updates the active navigation/pageload root span name with the parameterized route, so the\n * transaction reflects the parameterized route pattern (e.g. `/users/:id`).\n */\nfunction updateRootSpanRoute(routeName: string, hasPattern: boolean): void {\n if (!hasPattern) {\n return;\n }\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan && getRootSpan(activeSpan);\n if (!rootSpan) {\n return;\n }\n\n const { op } = spanToJSON(rootSpan);\n if (op !== 'navigation' && op !== 'pageload') {\n return;\n }\n\n updateSpanName(rootSpan, routeName);\n rootSpan.setAttributes({ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route', [URL_TEMPLATE]: routeName });\n}\n\n/**\n * Check if React Router's instrumentation API is being used on the client.\n */\nexport function isClientInstrumentationApiUsed(): boolean {\n return !!GLOBAL_WITH_FLAGS[SENTRY_CLIENT_INSTRUMENTATION_FLAG];\n}\n\n/**\n * Check if React Router's instrumentation API's navigate hook was invoked.\n */\nexport function isNavigateHookInvoked(): boolean {\n return !!GLOBAL_WITH_FLAGS[SENTRY_NAVIGATE_HOOK_INVOKED_FLAG];\n}\n"],"names":["result","client","navigationSpan"],"mappings":"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"}
|
|
@@ -80,7 +80,10 @@ function instrumentHydratedRouter() {
|
|
|
80
80
|
// this event is for the currently active root span
|
|
81
81
|
(destinationPathname === normalizePathname(rootSpanName) || spanPathname && destinationPathname === normalizePathname(spanPathname))) {
|
|
82
82
|
rootSpan.updateName(parameterizedRoute);
|
|
83
|
-
rootSpan.setAttributes({
|
|
83
|
+
rootSpan.setAttributes({
|
|
84
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
|
|
85
|
+
[URL_TEMPLATE]: parameterizedRoute
|
|
86
|
+
});
|
|
84
87
|
}
|
|
85
88
|
});
|
|
86
89
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hydratedRouter.js","sources":["../../../src/client/hydratedRouter.ts"],"sourcesContent":["import { getAbsoluteUrl, startBrowserTracingNavigationSpan } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport {\n debug,\n getActiveSpan,\n getClient,\n getRootSpan,\n GLOBAL_OBJ,\n isThenable,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n spanToJSON,\n} from '@sentry/core';\nimport type { DataRouter } from 'react-router';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport { isClientInstrumentationApiUsed } from './createClientInstrumentation';\nimport {\n finalizeNavigationSpanFromRouterState,\n getParameterizedRoute,\n normalizePathname,\n resolveNavigateAbsoluteUrl,\n resolveNavigateArg,\n} from './utils';\nimport { URL_PATH, URL_TEMPLATE } from '@sentry/conventions/attributes';\n\nconst GLOBAL_OBJ_WITH_DATA_ROUTER = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n __reactRouterDataRouter?: DataRouter;\n};\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\nconst MAX_RETRIES = 40; // 2 seconds at 50ms interval\n\n/**\n * Instruments the React Router Data Router for pageloads and navigation.\n *\n * This function waits for the router to be available after hydration, then:\n * 1. Updates the pageload transaction with parameterized route info\n * 2. Patches router.navigate() to create navigation transactions\n * 3. Subscribes to router state changes to update navigation transactions with parameterized routes\n */\nexport function instrumentHydratedRouter(): void {\n function trySubscribe(): boolean {\n const router = GLOBAL_OBJ_WITH_DATA_ROUTER.__reactRouterDataRouter;\n\n if (router) {\n // The first time we hit the router, we try to update the pageload transaction\n const pageloadSpan = getActiveRootSpan();\n\n if (pageloadSpan) {\n const pageloadName = spanToJSON(pageloadSpan).description;\n const parameterizePageloadRoute = getParameterizedRoute(router.state);\n if (\n pageloadName &&\n // this event is for the currently active pageload\n normalizePathname(router.state.location.pathname) === normalizePathname(pageloadName)\n ) {\n pageloadSpan.updateName(parameterizePageloadRoute);\n pageloadSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.react_router',\n [URL_TEMPLATE]: parameterizePageloadRoute,\n });\n }\n }\n\n // Patching navigate for creating accurate navigation transactions\n if (typeof router.navigate === 'function') {\n const originalNav = router.navigate.bind(router);\n router.navigate = function sentryPatchedNavigate(...args) {\n // Skip if instrumentation API is enabled (it handles navigation spans itself)\n if (!isClientInstrumentationApiUsed()) {\n const target = args[0];\n\n if (typeof target === 'number') {\n // navigate(0) triggers a reload, not a route change — skip span creation\n if (target !== 0) {\n const currentPathname = WINDOW.location?.pathname || '/';\n const navigationSpan = maybeCreateNavigationTransaction(\n currentPathname,\n getAbsoluteUrl(currentPathname),\n 'url',\n );\n\n const result = originalNav(...args);\n\n // Numeric navigations (`navigate(-1)`/`navigate(1)`) don't carry a destination\n // path, so we can only resolve the real URL/route once the router has settled.\n if (navigationSpan) {\n // Finalize from the (updated) router state after navigation completes, in both\n // the resolve and reject paths, so a rejected navigation still ends up with the\n // correct URL attributes instead of the placeholder start pathname.\n if (isThenable(result)) {\n result.then(\n () => finalizeNavigationSpanFromRouterState(navigationSpan, router.state),\n () => finalizeNavigationSpanFromRouterState(navigationSpan, router.state),\n );\n } else {\n finalizeNavigationSpanFromRouterState(navigationSpan, router.state);\n }\n }\n\n return result;\n }\n } else {\n maybeCreateNavigationTransaction(\n resolveNavigateArg(target) || '<unknown route>',\n resolveNavigateAbsoluteUrl(target),\n 'url',\n );\n }\n }\n return originalNav(...args);\n };\n }\n\n // Subscribe to router state changes to update navigation transactions (and any pageload\n // whose route info only became available after `trySubscribe`, e.g. lazy routes) with the\n // parameterized route.\n router.subscribe(newState => {\n const rootSpan = getActiveRootSpan();\n\n if (!rootSpan) {\n return;\n }\n\n const rootSpanJson = spanToJSON(rootSpan);\n\n // When the instrumentation API is active, navigation roots are parameterized\n // by the native route hooks\n if (\n rootSpanJson.op === 'navigation' &&\n isClientInstrumentationApiUsed() &&\n rootSpanJson.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] === 'route'\n ) {\n return;\n }\n\n const rootSpanName = rootSpanJson.description;\n const parameterizedRoute = getParameterizedRoute(newState);\n const spanPathname = rootSpanJson.data?.[URL_PATH] as string | undefined;\n const destinationPathname = normalizePathname(newState.location.pathname);\n\n if (\n rootSpanName &&\n newState.navigation.state === 'idle' && // navigation has completed\n // this event is for the currently active root span\n (destinationPathname === normalizePathname(rootSpanName) ||\n (spanPathname && destinationPathname === normalizePathname(spanPathname)))\n ) {\n rootSpan.updateName(parameterizedRoute);\n rootSpan.setAttributes({ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route', [URL_TEMPLATE]: parameterizedRoute });\n }\n });\n return true;\n }\n return false;\n }\n\n // Wait until the router is available (since the SDK loads before hydration)\n if (!trySubscribe()) {\n let retryCount = 0;\n // Retry until the router is available or max retries reached\n const interval = setInterval(() => {\n if (trySubscribe() || retryCount >= MAX_RETRIES) {\n if (retryCount >= MAX_RETRIES) {\n DEBUG_BUILD && debug.warn('Unable to instrument React Router: router not found after hydration.');\n }\n clearInterval(interval);\n }\n retryCount++;\n }, 50);\n }\n}\n\nfunction maybeCreateNavigationTransaction(name: string, url: string, source: 'url' | 'route'): Span | undefined {\n const client = getClient();\n\n if (!client) {\n return undefined;\n }\n\n return startBrowserTracingNavigationSpan(\n client,\n {\n name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router',\n ...(source === 'route' ? { [URL_TEMPLATE]: name } : {}),\n },\n },\n { url },\n );\n}\n\nfunction getActiveRootSpan(): Span | undefined {\n const activeSpan = getActiveSpan();\n if (!activeSpan) {\n return undefined;\n }\n\n const rootSpan = getRootSpan(activeSpan);\n\n const op = spanToJSON(rootSpan).op;\n\n // Only use this root span if it is a pageload or navigation span\n return op === 'navigation' || op === 'pageload' ? rootSpan : undefined;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hydratedRouter.js","sources":["../../../src/client/hydratedRouter.ts"],"sourcesContent":["import { getAbsoluteUrl, startBrowserTracingNavigationSpan } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport {\n debug,\n getActiveSpan,\n getClient,\n getRootSpan,\n GLOBAL_OBJ,\n isThenable,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n spanToJSON,\n} from '@sentry/core';\nimport type { DataRouter } from 'react-router';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport { isClientInstrumentationApiUsed } from './createClientInstrumentation';\nimport {\n finalizeNavigationSpanFromRouterState,\n getParameterizedRoute,\n normalizePathname,\n resolveNavigateAbsoluteUrl,\n resolveNavigateArg,\n} from './utils';\nimport { URL_PATH, URL_TEMPLATE } from '@sentry/conventions/attributes';\n\nconst GLOBAL_OBJ_WITH_DATA_ROUTER = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n __reactRouterDataRouter?: DataRouter;\n};\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\nconst MAX_RETRIES = 40; // 2 seconds at 50ms interval\n\n/**\n * Instruments the React Router Data Router for pageloads and navigation.\n *\n * This function waits for the router to be available after hydration, then:\n * 1. Updates the pageload transaction with parameterized route info\n * 2. Patches router.navigate() to create navigation transactions\n * 3. Subscribes to router state changes to update navigation transactions with parameterized routes\n */\nexport function instrumentHydratedRouter(): void {\n function trySubscribe(): boolean {\n const router = GLOBAL_OBJ_WITH_DATA_ROUTER.__reactRouterDataRouter;\n\n if (router) {\n // The first time we hit the router, we try to update the pageload transaction\n const pageloadSpan = getActiveRootSpan();\n\n if (pageloadSpan) {\n const pageloadName = spanToJSON(pageloadSpan).description;\n const parameterizePageloadRoute = getParameterizedRoute(router.state);\n if (\n pageloadName &&\n // this event is for the currently active pageload\n normalizePathname(router.state.location.pathname) === normalizePathname(pageloadName)\n ) {\n pageloadSpan.updateName(parameterizePageloadRoute);\n pageloadSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.react_router',\n [URL_TEMPLATE]: parameterizePageloadRoute,\n });\n }\n }\n\n // Patching navigate for creating accurate navigation transactions\n if (typeof router.navigate === 'function') {\n const originalNav = router.navigate.bind(router);\n router.navigate = function sentryPatchedNavigate(...args) {\n // Skip if instrumentation API is enabled (it handles navigation spans itself)\n if (!isClientInstrumentationApiUsed()) {\n const target = args[0];\n\n if (typeof target === 'number') {\n // navigate(0) triggers a reload, not a route change — skip span creation\n if (target !== 0) {\n const currentPathname = WINDOW.location?.pathname || '/';\n const navigationSpan = maybeCreateNavigationTransaction(\n currentPathname,\n getAbsoluteUrl(currentPathname),\n 'url',\n );\n\n const result = originalNav(...args);\n\n // Numeric navigations (`navigate(-1)`/`navigate(1)`) don't carry a destination\n // path, so we can only resolve the real URL/route once the router has settled.\n if (navigationSpan) {\n // Finalize from the (updated) router state after navigation completes, in both\n // the resolve and reject paths, so a rejected navigation still ends up with the\n // correct URL attributes instead of the placeholder start pathname.\n if (isThenable(result)) {\n result.then(\n () => finalizeNavigationSpanFromRouterState(navigationSpan, router.state),\n () => finalizeNavigationSpanFromRouterState(navigationSpan, router.state),\n );\n } else {\n finalizeNavigationSpanFromRouterState(navigationSpan, router.state);\n }\n }\n\n return result;\n }\n } else {\n maybeCreateNavigationTransaction(\n resolveNavigateArg(target) || '<unknown route>',\n resolveNavigateAbsoluteUrl(target),\n 'url',\n );\n }\n }\n return originalNav(...args);\n };\n }\n\n // Subscribe to router state changes to update navigation transactions (and any pageload\n // whose route info only became available after `trySubscribe`, e.g. lazy routes) with the\n // parameterized route.\n router.subscribe(newState => {\n const rootSpan = getActiveRootSpan();\n\n if (!rootSpan) {\n return;\n }\n\n const rootSpanJson = spanToJSON(rootSpan);\n\n // When the instrumentation API is active, navigation roots are parameterized\n // by the native route hooks\n if (\n rootSpanJson.op === 'navigation' &&\n isClientInstrumentationApiUsed() &&\n rootSpanJson.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] === 'route'\n ) {\n return;\n }\n\n const rootSpanName = rootSpanJson.description;\n const parameterizedRoute = getParameterizedRoute(newState);\n const spanPathname = rootSpanJson.data?.[URL_PATH] as string | undefined;\n const destinationPathname = normalizePathname(newState.location.pathname);\n\n if (\n rootSpanName &&\n newState.navigation.state === 'idle' && // navigation has completed\n // this event is for the currently active root span\n (destinationPathname === normalizePathname(rootSpanName) ||\n (spanPathname && destinationPathname === normalizePathname(spanPathname)))\n ) {\n rootSpan.updateName(parameterizedRoute);\n rootSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [URL_TEMPLATE]: parameterizedRoute,\n });\n }\n });\n return true;\n }\n return false;\n }\n\n // Wait until the router is available (since the SDK loads before hydration)\n if (!trySubscribe()) {\n let retryCount = 0;\n // Retry until the router is available or max retries reached\n const interval = setInterval(() => {\n if (trySubscribe() || retryCount >= MAX_RETRIES) {\n if (retryCount >= MAX_RETRIES) {\n DEBUG_BUILD && debug.warn('Unable to instrument React Router: router not found after hydration.');\n }\n clearInterval(interval);\n }\n retryCount++;\n }, 50);\n }\n}\n\nfunction maybeCreateNavigationTransaction(name: string, url: string, source: 'url' | 'route'): Span | undefined {\n const client = getClient();\n\n if (!client) {\n return undefined;\n }\n\n return startBrowserTracingNavigationSpan(\n client,\n {\n name,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.react_router',\n ...(source === 'route' ? { [URL_TEMPLATE]: name } : {}),\n },\n },\n { url },\n );\n}\n\nfunction getActiveRootSpan(): Span | undefined {\n const activeSpan = getActiveSpan();\n if (!activeSpan) {\n return undefined;\n }\n\n const rootSpan = getRootSpan(activeSpan);\n\n const op = spanToJSON(rootSpan).op;\n\n // Only use this root span if it is a pageload or navigation span\n return op === 'navigation' || op === 'pageload' ? rootSpan : undefined;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,7 @@ function reactRouterTracingIntegration(options = {}) {
|
|
|
15
15
|
browserTracingIntegrationInstance.afterAllSetup(client);
|
|
16
16
|
instrumentHydratedRouter();
|
|
17
17
|
},
|
|
18
|
+
// oxlint-disable-next-line typescript/no-deprecated -- exposes the deprecated getter for back-compat until it is removed
|
|
18
19
|
get clientInstrumentation() {
|
|
19
20
|
return clientInstrumentationInstance;
|
|
20
21
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracingIntegration.js","sources":["../../../src/client/tracingIntegration.ts"],"sourcesContent":["import { browserTracingIntegration as originalBrowserTracingIntegration } from '@sentry/browser';\nimport type { Integration } from '@sentry/core';\nimport type { ClientInstrumentation } from '../common/types';\nimport {\n createSentryClientInstrumentation,\n type CreateSentryClientInstrumentationOptions,\n} from './createClientInstrumentation';\nimport { instrumentHydratedRouter } from './hydratedRouter';\n\n/**\n * Options for the React Router tracing integration.\n */\nexport interface ReactRouterTracingIntegrationOptions {\n /**\n * Options for React Router's instrumentation API.\n */\n instrumentationOptions?: CreateSentryClientInstrumentationOptions;\n\n /** @deprecated `clientInstrumentation` is always built, so this flag is a no-op. Will be removed in a future major. */\n useInstrumentationAPI?: boolean;\n}\n\n/**\n * React Router tracing integration with support for the instrumentation API.\n */\nexport interface ReactRouterTracingIntegration extends Integration {\n /**\n * Client instrumentation to pass to `HydratedRouter`'s `instrumentations` prop.\n *\n * @deprecated Use the standalone `createSentryClientInstrumentation()` export instead and pass its\n * result to `HydratedRouter`'s `instrumentations` prop. This mirrors the server-side\n * `createSentryServerInstrumentation()` API. Will be removed in a future major.\n */\n readonly clientInstrumentation: ClientInstrumentation;\n}\n\n/**\n * Browser tracing integration for React Router (Framework) applications.\n * This integration will create navigation spans and enhance transaction names with parameterized routes.\n */\nexport function reactRouterTracingIntegration(\n options: ReactRouterTracingIntegrationOptions = {},\n): ReactRouterTracingIntegration {\n const browserTracingIntegrationInstance = originalBrowserTracingIntegration({\n // Navigation transactions are started within the hydrated router instrumentation\n instrumentNavigation: false,\n });\n\n // Built eagerly so it can be passed to HydratedRouter's `instrumentations` prop. This has no\n // side effects - the API is only marked \"used\" once React Router invokes the `router()` hook.\n const clientInstrumentationInstance = createSentryClientInstrumentation(options.instrumentationOptions);\n\n return {\n ...browserTracingIntegrationInstance,\n name: 'ReactRouterTracingIntegration',\n afterAllSetup(client) {\n browserTracingIntegrationInstance.afterAllSetup(client);\n instrumentHydratedRouter();\n },\n get clientInstrumentation(): ClientInstrumentation {\n return clientInstrumentationInstance;\n },\n };\n}\n"],"names":["originalBrowserTracingIntegration"],"mappings":";;;;AAwCO,SAAS,6BAAA,CACd,OAAA,GAAgD,EAAC,EAClB;AAC/B,EAAA,MAAM,oCAAoCA,yBAAA,CAAkC;AAAA;AAAA,IAE1E,oBAAA,EAAsB;AAAA,GACvB,CAAA;AAID,EAAA,MAAM,6BAAA,GAAgC,iCAAA,CAAkC,OAAA,CAAQ,sBAAsB,CAAA;AAEtG,EAAA,OAAO;AAAA,IACL,GAAG,iCAAA;AAAA,IACH,IAAA,EAAM,+BAAA;AAAA,IACN,cAAc,MAAA,EAAQ;AACpB,MAAA,iCAAA,CAAkC,cAAc,MAAM,CAAA;AACtD,MAAA,wBAAA,EAAyB;AAAA,IAC3B,CAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"tracingIntegration.js","sources":["../../../src/client/tracingIntegration.ts"],"sourcesContent":["import { browserTracingIntegration as originalBrowserTracingIntegration } from '@sentry/browser';\nimport type { Integration } from '@sentry/core';\nimport type { ClientInstrumentation } from '../common/types';\nimport {\n createSentryClientInstrumentation,\n type CreateSentryClientInstrumentationOptions,\n} from './createClientInstrumentation';\nimport { instrumentHydratedRouter } from './hydratedRouter';\n\n/**\n * Options for the React Router tracing integration.\n */\nexport interface ReactRouterTracingIntegrationOptions {\n /**\n * Options for React Router's instrumentation API.\n */\n instrumentationOptions?: CreateSentryClientInstrumentationOptions;\n\n /** @deprecated `clientInstrumentation` is always built, so this flag is a no-op. Will be removed in a future major. */\n useInstrumentationAPI?: boolean;\n}\n\n/**\n * React Router tracing integration with support for the instrumentation API.\n */\nexport interface ReactRouterTracingIntegration extends Integration {\n /**\n * Client instrumentation to pass to `HydratedRouter`'s `instrumentations` prop.\n *\n * @deprecated Use the standalone `createSentryClientInstrumentation()` export instead and pass its\n * result to `HydratedRouter`'s `instrumentations` prop. This mirrors the server-side\n * `createSentryServerInstrumentation()` API. Will be removed in a future major.\n */\n readonly clientInstrumentation: ClientInstrumentation;\n}\n\n/**\n * Browser tracing integration for React Router (Framework) applications.\n * This integration will create navigation spans and enhance transaction names with parameterized routes.\n */\nexport function reactRouterTracingIntegration(\n options: ReactRouterTracingIntegrationOptions = {},\n): ReactRouterTracingIntegration {\n const browserTracingIntegrationInstance = originalBrowserTracingIntegration({\n // Navigation transactions are started within the hydrated router instrumentation\n instrumentNavigation: false,\n });\n\n // Built eagerly so it can be passed to HydratedRouter's `instrumentations` prop. This has no\n // side effects - the API is only marked \"used\" once React Router invokes the `router()` hook.\n const clientInstrumentationInstance = createSentryClientInstrumentation(options.instrumentationOptions);\n\n return {\n ...browserTracingIntegrationInstance,\n name: 'ReactRouterTracingIntegration',\n afterAllSetup(client) {\n browserTracingIntegrationInstance.afterAllSetup(client);\n instrumentHydratedRouter();\n },\n // oxlint-disable-next-line typescript/no-deprecated -- exposes the deprecated getter for back-compat until it is removed\n get clientInstrumentation(): ClientInstrumentation {\n return clientInstrumentationInstance;\n },\n };\n}\n"],"names":["originalBrowserTracingIntegration"],"mappings":";;;;AAwCO,SAAS,6BAAA,CACd,OAAA,GAAgD,EAAC,EAClB;AAC/B,EAAA,MAAM,oCAAoCA,yBAAA,CAAkC;AAAA;AAAA,IAE1E,oBAAA,EAAsB;AAAA,GACvB,CAAA;AAID,EAAA,MAAM,6BAAA,GAAgC,iCAAA,CAAkC,OAAA,CAAQ,sBAAsB,CAAA;AAEtG,EAAA,OAAO;AAAA,IACL,GAAG,iCAAA;AAAA,IACH,IAAA,EAAM,+BAAA;AAAA,IACN,cAAc,MAAA,EAAQ;AACpB,MAAA,iCAAA,CAAkC,cAAc,MAAM,CAAA;AACtD,MAAA,wBAAA,EAAyB;AAAA,IAC3B,CAAA;AAAA;AAAA,IAEA,IAAI,qBAAA,GAA+C;AACjD,MAAA,OAAO,6BAAA;AAAA,IACT;AAAA,GACF;AACF;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getAbsoluteUrl } from '@sentry/browser';
|
|
2
|
-
import { GLOBAL_OBJ, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
|
|
2
|
+
import { GLOBAL_OBJ, filterCollectedUrl, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';
|
|
3
3
|
import { URL_FULL, URL_PATH, URL_TEMPLATE } from '@sentry/conventions/attributes';
|
|
4
4
|
|
|
5
5
|
const WINDOW = GLOBAL_OBJ;
|
|
@@ -53,8 +53,9 @@ function updateNavigationSpanUrlFromLocation(span) {
|
|
|
53
53
|
const destinationUrl = getAbsoluteUrl(`${pathname}${search}${hash}`);
|
|
54
54
|
span.updateName(pathname);
|
|
55
55
|
span.setAttributes({
|
|
56
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
|
|
56
57
|
[URL_PATH]: pathname,
|
|
57
|
-
[URL_FULL]: destinationUrl
|
|
58
|
+
[URL_FULL]: filterCollectedUrl(destinationUrl)
|
|
58
59
|
});
|
|
59
60
|
}
|
|
60
61
|
function normalizePathname(pathname) {
|
|
@@ -77,7 +78,10 @@ function finalizeNavigationSpanFromRouterState(span, routerState) {
|
|
|
77
78
|
if (routerState.navigation?.state === "idle" && normalizePathname(routerState.location.pathname) === normalizePathname(pathname)) {
|
|
78
79
|
const parameterizedRoute = getParameterizedRoute(routerState);
|
|
79
80
|
span.updateName(parameterizedRoute);
|
|
80
|
-
span.setAttributes({
|
|
81
|
+
span.setAttributes({
|
|
82
|
+
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
|
|
83
|
+
[URL_TEMPLATE]: parameterizedRoute
|
|
84
|
+
});
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
function finalizeNavigationSpanFromHydratedRouter(span) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../../src/client/utils.ts"],"sourcesContent":["import { getAbsoluteUrl } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport { GLOBAL_OBJ, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '@sentry/core';\nimport { URL_FULL, URL_PATH, URL_TEMPLATE } from '@sentry/conventions/attributes';\nimport type { DataRouter, RouterState } from 'react-router';\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\nconst GLOBAL_OBJ_WITH_DATA_ROUTER = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n __reactRouterDataRouter?: DataRouter;\n};\n\n/**\n * Resolves a navigate argument to a pathname string.\n *\n * React Router's navigate() accepts a string, number, or a To object ({ pathname, search, hash }).\n * All fields in the To object are optional (Partial<Path>), so we need to detect object args\n * to avoid \"[object Object]\" transaction names.\n */\nexport function resolveNavigateArg(target: unknown): string {\n if (typeof target !== 'object' || target === null) {\n // string or number\n return String(target);\n }\n\n // Object `to` with pathname\n const pathname = (target as Record<string, unknown>).pathname;\n if (typeof pathname === 'string') {\n return pathname || '/';\n }\n\n // Object `to` without pathname - navigation stays on current path\n return WINDOW.location?.pathname || '/';\n}\n\n/**\n * Resolves a navigate argument to the full destination path, preserving `search`/`hash` from a\n * To object. Unlike `resolveNavigateArg` (used for span/route naming, which should stay a bare\n * path), this is used to derive `url.full`/`url.path`, which should reflect the actual\n * destination the user is navigating to, including any query string.\n */\nexport function resolveNavigateUrl(target: unknown): string {\n if (typeof target !== 'object' || target === null) {\n // string or number\n return String(target);\n }\n\n const { pathname, search, hash } = target as Record<string, unknown>;\n const path = typeof pathname === 'string' && pathname !== '' ? pathname : WINDOW.location?.pathname || '/';\n\n return `${path}${typeof search === 'string' ? search : ''}${typeof hash === 'string' ? hash : ''}`;\n}\n\nfunction getNavigateBaseUrl(currentUrl?: string): string {\n const origin = WINDOW.location?.origin || 'http://localhost';\n\n // Prefer the live pathname, but fall back to the hook-provided `currentUrl` (which may be a full\n // URL or a bare path) when `location` is unavailable (e.g. SSR/non-browser environments).\n let pathname = WINDOW.location?.pathname;\n if (!pathname && currentUrl) {\n try {\n pathname = new URL(currentUrl, origin).pathname;\n } catch {\n pathname = currentUrl.startsWith('/') ? currentUrl : `/${currentUrl}`;\n }\n }\n pathname = pathname || '/';\n\n // React Router resolves relative navigate targets against the current path treated as a\n // *directory* (it appends segments), whereas the WHATWG `URL` parser treats the last path\n // segment as a file and drops it. Enforce a trailing slash so relative resolution matches\n // React Router, e.g. `navigate('ssr')` from `/performance` -> `/performance/ssr` (not `/ssr`).\n const directory = pathname.endsWith('/') ? pathname : `${pathname}/`;\n\n return `${origin}${directory}`;\n}\n\n/**\n * Resolves a navigate argument to an absolute URL for `url.full`/`url.path`, correctly handling\n * relative targets (no leading slash) by resolving them against the current URL instead of the\n * document origin alone.\n */\nexport function resolveNavigateAbsoluteUrl(target: unknown, currentUrl?: string): string {\n const destination = resolveNavigateUrl(target);\n\n try {\n const resolved = new URL(destination, getNavigateBaseUrl(currentUrl));\n return getAbsoluteUrl(`${resolved.pathname}${resolved.search}${resolved.hash}`);\n } catch {\n return getAbsoluteUrl(destination);\n }\n}\n\n/**\n * Updates a navigation span's name and `url.path`/`url.full` from the current `location`.\n */\nexport function updateNavigationSpanUrlFromLocation(span: Span): void {\n if (!WINDOW.location) {\n return;\n }\n\n const { pathname, search = '', hash = '' } = WINDOW.location;\n const destinationUrl = getAbsoluteUrl(`${pathname}${search}${hash}`);\n\n span.updateName(pathname);\n span.setAttributes({\n [URL_PATH]: pathname,\n [URL_FULL]: destinationUrl,\n });\n}\n\nexport function normalizePathname(pathname: string): string {\n let normalized = pathname.startsWith('/') ? pathname : `/${pathname}`;\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n return normalized;\n}\n\nexport function getParameterizedRoute(routerState: RouterState): string {\n const lastMatch = routerState.matches[routerState.matches.length - 1];\n return normalizePathname(lastMatch?.route.path || routerState.location.pathname);\n}\n\n/**\n * Updates a navigation span's URL attributes and parameterizes its name from the router state.\n * Used after numeric navigations (`navigate(-1)` / `navigate(1)`) where route hooks may not\n * supply a pattern (e.g. index routes).\n *\n * `url.path` reflects raw `location.pathname` (may include a trailing slash when the server\n * redirects index routes), while `url.template` is normalized without trailing slashes.\n */\nexport function finalizeNavigationSpanFromRouterState(span: Span, routerState: RouterState): void {\n updateNavigationSpanUrlFromLocation(span);\n\n if (!WINDOW.location) {\n return;\n }\n\n const { pathname } = WINDOW.location;\n\n if (\n routerState.navigation?.state === 'idle' &&\n normalizePathname(routerState.location.pathname) === normalizePathname(pathname)\n ) {\n const parameterizedRoute = getParameterizedRoute(routerState);\n span.updateName(parameterizedRoute);\n span.setAttributes({
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../src/client/utils.ts"],"sourcesContent":["import { getAbsoluteUrl } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport { GLOBAL_OBJ, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, filterCollectedUrl } from '@sentry/core';\nimport { URL_FULL, URL_PATH, URL_TEMPLATE } from '@sentry/conventions/attributes';\nimport type { DataRouter, RouterState } from 'react-router';\n\nconst WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\nconst GLOBAL_OBJ_WITH_DATA_ROUTER = GLOBAL_OBJ as typeof GLOBAL_OBJ & {\n __reactRouterDataRouter?: DataRouter;\n};\n\n/**\n * Resolves a navigate argument to a pathname string.\n *\n * React Router's navigate() accepts a string, number, or a To object ({ pathname, search, hash }).\n * All fields in the To object are optional (Partial<Path>), so we need to detect object args\n * to avoid \"[object Object]\" transaction names.\n */\nexport function resolveNavigateArg(target: unknown): string {\n if (typeof target !== 'object' || target === null) {\n // string or number\n return String(target);\n }\n\n // Object `to` with pathname\n const pathname = (target as Record<string, unknown>).pathname;\n if (typeof pathname === 'string') {\n return pathname || '/';\n }\n\n // Object `to` without pathname - navigation stays on current path\n return WINDOW.location?.pathname || '/';\n}\n\n/**\n * Resolves a navigate argument to the full destination path, preserving `search`/`hash` from a\n * To object. Unlike `resolveNavigateArg` (used for span/route naming, which should stay a bare\n * path), this is used to derive `url.full`/`url.path`, which should reflect the actual\n * destination the user is navigating to, including any query string.\n */\nexport function resolveNavigateUrl(target: unknown): string {\n if (typeof target !== 'object' || target === null) {\n // string or number\n return String(target);\n }\n\n const { pathname, search, hash } = target as Record<string, unknown>;\n const path = typeof pathname === 'string' && pathname !== '' ? pathname : WINDOW.location?.pathname || '/';\n\n return `${path}${typeof search === 'string' ? search : ''}${typeof hash === 'string' ? hash : ''}`;\n}\n\nfunction getNavigateBaseUrl(currentUrl?: string): string {\n const origin = WINDOW.location?.origin || 'http://localhost';\n\n // Prefer the live pathname, but fall back to the hook-provided `currentUrl` (which may be a full\n // URL or a bare path) when `location` is unavailable (e.g. SSR/non-browser environments).\n let pathname = WINDOW.location?.pathname;\n if (!pathname && currentUrl) {\n try {\n pathname = new URL(currentUrl, origin).pathname;\n } catch {\n pathname = currentUrl.startsWith('/') ? currentUrl : `/${currentUrl}`;\n }\n }\n pathname = pathname || '/';\n\n // React Router resolves relative navigate targets against the current path treated as a\n // *directory* (it appends segments), whereas the WHATWG `URL` parser treats the last path\n // segment as a file and drops it. Enforce a trailing slash so relative resolution matches\n // React Router, e.g. `navigate('ssr')` from `/performance` -> `/performance/ssr` (not `/ssr`).\n const directory = pathname.endsWith('/') ? pathname : `${pathname}/`;\n\n return `${origin}${directory}`;\n}\n\n/**\n * Resolves a navigate argument to an absolute URL for `url.full`/`url.path`, correctly handling\n * relative targets (no leading slash) by resolving them against the current URL instead of the\n * document origin alone.\n */\nexport function resolveNavigateAbsoluteUrl(target: unknown, currentUrl?: string): string {\n const destination = resolveNavigateUrl(target);\n\n try {\n const resolved = new URL(destination, getNavigateBaseUrl(currentUrl));\n return getAbsoluteUrl(`${resolved.pathname}${resolved.search}${resolved.hash}`);\n } catch {\n return getAbsoluteUrl(destination);\n }\n}\n\n/**\n * Updates a navigation span's name and `url.path`/`url.full` from the current `location`.\n */\nexport function updateNavigationSpanUrlFromLocation(span: Span): void {\n if (!WINDOW.location) {\n return;\n }\n\n const { pathname, search = '', hash = '' } = WINDOW.location;\n const destinationUrl = getAbsoluteUrl(`${pathname}${search}${hash}`);\n\n span.updateName(pathname);\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [URL_PATH]: pathname,\n [URL_FULL]: filterCollectedUrl(destinationUrl),\n });\n}\n\nexport function normalizePathname(pathname: string): string {\n let normalized = pathname.startsWith('/') ? pathname : `/${pathname}`;\n if (normalized.length > 1 && normalized.endsWith('/')) {\n normalized = normalized.slice(0, -1);\n }\n return normalized;\n}\n\nexport function getParameterizedRoute(routerState: RouterState): string {\n const lastMatch = routerState.matches[routerState.matches.length - 1];\n return normalizePathname(lastMatch?.route.path || routerState.location.pathname);\n}\n\n/**\n * Updates a navigation span's URL attributes and parameterizes its name from the router state.\n * Used after numeric navigations (`navigate(-1)` / `navigate(1)`) where route hooks may not\n * supply a pattern (e.g. index routes).\n *\n * `url.path` reflects raw `location.pathname` (may include a trailing slash when the server\n * redirects index routes), while `url.template` is normalized without trailing slashes.\n */\nexport function finalizeNavigationSpanFromRouterState(span: Span, routerState: RouterState): void {\n updateNavigationSpanUrlFromLocation(span);\n\n if (!WINDOW.location) {\n return;\n }\n\n const { pathname } = WINDOW.location;\n\n if (\n routerState.navigation?.state === 'idle' &&\n normalizePathname(routerState.location.pathname) === normalizePathname(pathname)\n ) {\n const parameterizedRoute = getParameterizedRoute(routerState);\n span.updateName(parameterizedRoute);\n span.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [URL_TEMPLATE]: parameterizedRoute,\n });\n }\n}\n\n/**\n * Finalizes a navigation span after numeric navigation using the hydrated data router when\n * available, otherwise falls back to URL attributes from `location` alone.\n */\nexport function finalizeNavigationSpanFromHydratedRouter(span: Span): void {\n const router = GLOBAL_OBJ_WITH_DATA_ROUTER.__reactRouterDataRouter;\n if (router) {\n finalizeNavigationSpanFromRouterState(span, router.state);\n } else {\n updateNavigationSpanUrlFromLocation(span);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,8 +2,6 @@ export * from '@sentry/node';
|
|
|
2
2
|
export { init } from './server/sdk.js';
|
|
3
3
|
export { sentryHandleRequest, wrapSentryHandleRequest } from './server/wrapSentryHandleRequest.js';
|
|
4
4
|
export { createSentryHandleRequest } from './server/createSentryHandleRequest.js';
|
|
5
|
-
export { wrapServerAction } from './server/wrapServerAction.js';
|
|
6
|
-
export { wrapServerLoader } from './server/wrapServerLoader.js';
|
|
7
5
|
export { createSentryHandleError } from './server/createSentryHandleError.js';
|
|
8
6
|
export { getMetaTagTransformer } from './server/getMetaTagTransformer.js';
|
|
9
7
|
export { createSentryServerInstrumentation } from './server/createServerInstrumentation.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"
|
|
1
|
+
{"type":"module","version":"11.0.0-alpha.0"}
|