@sentry/react-router 11.0.0-alpha.0 → 11.0.0-alpha.2

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.
Files changed (88) hide show
  1. package/README.md +2 -2
  2. package/build/cjs/client/createClientInstrumentation.js +32 -24
  3. package/build/cjs/client/createClientInstrumentation.js.map +1 -1
  4. package/build/cjs/client/hydratedRouter.js +15 -22
  5. package/build/cjs/client/hydratedRouter.js.map +1 -1
  6. package/build/cjs/client/tracingIntegration.js.map +1 -1
  7. package/build/cjs/client/utils.js +32 -12
  8. package/build/cjs/client/utils.js.map +1 -1
  9. package/build/cjs/cloudflare/index.js +3 -2
  10. package/build/cjs/cloudflare/index.js.map +1 -1
  11. package/build/cjs/common/utils.js.map +1 -1
  12. package/build/cjs/index.server.js +0 -7
  13. package/build/cjs/index.server.js.map +1 -1
  14. package/build/cjs/server/createServerInstrumentation.js +22 -15
  15. package/build/cjs/server/createServerInstrumentation.js.map +1 -1
  16. package/build/cjs/server/getMetaTagTransformer.js +3 -2
  17. package/build/cjs/server/getMetaTagTransformer.js.map +1 -1
  18. package/build/cjs/server/integration/lowQualityTransactionsFilterIntegration.js +4 -3
  19. package/build/cjs/server/integration/lowQualityTransactionsFilterIntegration.js.map +1 -1
  20. package/build/cjs/server/sdk.js +1 -1
  21. package/build/cjs/server/sdk.js.map +1 -1
  22. package/build/cjs/server/wrapSentryHandleRequest.js +2 -4
  23. package/build/cjs/server/wrapSentryHandleRequest.js.map +1 -1
  24. package/build/cjs/vite/buildEnd/handleOnBuildEnd.js +19 -41
  25. package/build/cjs/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
  26. package/build/cjs/vite/index.js +12 -0
  27. package/build/cjs/vite/index.js.map +1 -0
  28. package/build/cjs/vite/makeCustomSentryVitePlugins.js +21 -32
  29. package/build/cjs/vite/makeCustomSentryVitePlugins.js.map +1 -1
  30. package/build/esm/client/createClientInstrumentation.js +24 -16
  31. package/build/esm/client/createClientInstrumentation.js.map +1 -1
  32. package/build/esm/client/hydratedRouter.js +18 -25
  33. package/build/esm/client/hydratedRouter.js.map +1 -1
  34. package/build/esm/client/tracingIntegration.js.map +1 -1
  35. package/build/esm/client/utils.js +34 -14
  36. package/build/esm/client/utils.js.map +1 -1
  37. package/build/esm/cloudflare/index.js +3 -2
  38. package/build/esm/cloudflare/index.js.map +1 -1
  39. package/build/esm/common/utils.js.map +1 -1
  40. package/build/esm/index.server.js +1 -4
  41. package/build/esm/index.server.js.map +1 -1
  42. package/build/esm/package.json +1 -1
  43. package/build/esm/server/createServerInstrumentation.js +25 -18
  44. package/build/esm/server/createServerInstrumentation.js.map +1 -1
  45. package/build/esm/server/getMetaTagTransformer.js +3 -2
  46. package/build/esm/server/getMetaTagTransformer.js.map +1 -1
  47. package/build/esm/server/integration/lowQualityTransactionsFilterIntegration.js +4 -3
  48. package/build/esm/server/integration/lowQualityTransactionsFilterIntegration.js.map +1 -1
  49. package/build/esm/server/sdk.js +1 -1
  50. package/build/esm/server/sdk.js.map +1 -1
  51. package/build/esm/server/wrapSentryHandleRequest.js +5 -6
  52. package/build/esm/server/wrapSentryHandleRequest.js.map +1 -1
  53. package/build/esm/vite/buildEnd/handleOnBuildEnd.js +19 -41
  54. package/build/esm/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
  55. package/build/esm/vite/index.js +4 -0
  56. package/build/esm/vite/index.js.map +1 -0
  57. package/build/esm/vite/makeCustomSentryVitePlugins.js +21 -32
  58. package/build/esm/vite/makeCustomSentryVitePlugins.js.map +1 -1
  59. package/build/types/client/createClientInstrumentation.d.ts +1 -1
  60. package/build/types/client/createClientInstrumentation.d.ts.map +1 -1
  61. package/build/types/client/hydratedRouter.d.ts.map +1 -1
  62. package/build/types/client/tracingIntegration.d.ts +1 -1
  63. package/build/types/client/tracingIntegration.d.ts.map +1 -1
  64. package/build/types/client/utils.d.ts +7 -1
  65. package/build/types/client/utils.d.ts.map +1 -1
  66. package/build/types/cloudflare/index.d.ts.map +1 -1
  67. package/build/types/common/utils.d.ts +3 -2
  68. package/build/types/common/utils.d.ts.map +1 -1
  69. package/build/types/index.server.d.ts +0 -1
  70. package/build/types/index.server.d.ts.map +1 -1
  71. package/build/types/index.types.d.ts +3 -1
  72. package/build/types/index.types.d.ts.map +1 -1
  73. package/build/types/server/createServerInstrumentation.d.ts +1 -1
  74. package/build/types/server/createServerInstrumentation.d.ts.map +1 -1
  75. package/build/types/server/getMetaTagTransformer.d.ts.map +1 -1
  76. package/build/types/server/index.d.ts +1 -1
  77. package/build/types/server/index.d.ts.map +1 -1
  78. package/build/types/server/integration/lowQualityTransactionsFilterIntegration.d.ts +1 -2
  79. package/build/types/server/integration/lowQualityTransactionsFilterIntegration.d.ts.map +1 -1
  80. package/build/types/server/wrapSentryHandleRequest.d.ts +0 -2
  81. package/build/types/server/wrapSentryHandleRequest.d.ts.map +1 -1
  82. package/build/types/vite/buildEnd/handleOnBuildEnd.d.ts.map +1 -1
  83. package/build/types/vite/makeCustomSentryVitePlugins.d.ts.map +1 -1
  84. package/build/types/vite/types.d.ts +12 -58
  85. package/build/types/vite/types.d.ts.map +1 -1
  86. package/package.json +16 -10
  87. package/build/types/common/types.d.ts +0 -86
  88. package/build/types/common/types.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/cloudflare/index.ts"],"sourcesContent":["import { getTraceMetaTags } from '@sentry/core';\n\nexport * from '../client';\n\nexport { wrapSentryHandleRequest } from '../server/wrapSentryHandleRequest';\n\n/**\n * Injects Sentry trace meta tags into the HTML response by transforming the ReadableStream.\n * This enables distributed tracing by adding trace context to the HTML document head.\n * @param body - ReadableStream containing the HTML response body to modify\n * @returns A new ReadableStream with Sentry trace meta tags injected into the head section\n */\nexport function injectTraceMetaTags(body: ReadableStream): ReadableStream {\n const headClosingTag = '</head>';\n\n const reader = body.getReader();\n const stream = new ReadableStream({\n async pull(controller) {\n const { done, value } = await reader.read();\n\n if (done) {\n controller.close();\n return;\n }\n\n const encoder = new TextEncoder();\n const html = value instanceof Uint8Array ? new TextDecoder().decode(value) : String(value);\n\n if (html.includes(headClosingTag)) {\n const modifiedHtml = html.replace(headClosingTag, `${getTraceMetaTags()}${headClosingTag}`);\n\n controller.enqueue(encoder.encode(modifiedHtml));\n return;\n }\n\n controller.enqueue(encoder.encode(html));\n },\n });\n\n return stream;\n}\n"],"names":["getTraceMetaTags"],"mappings":";;;;;;;;;;;AAYO,SAAS,oBAAoB,IAAA,EAAsC;AACxE,EAAA,MAAM,cAAA,GAAiB,SAAA;AAEvB,EAAA,MAAM,MAAA,GAAS,KAAK,SAAA,EAAU;AAC9B,EAAA,MAAM,MAAA,GAAS,IAAI,cAAA,CAAe;AAAA,IAChC,MAAM,KAAK,UAAA,EAAY;AACrB,MAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,OAAO,IAAA,EAAK;AAE1C,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,UAAA,CAAW,KAAA,EAAM;AACjB,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,MAAA,MAAM,IAAA,GAAO,KAAA,YAAiB,UAAA,GAAa,IAAI,WAAA,GAAc,MAAA,CAAO,KAAK,CAAA,GAAI,MAAA,CAAO,KAAK,CAAA;AAEzF,MAAA,IAAI,IAAA,CAAK,QAAA,CAAS,cAAc,CAAA,EAAG;AACjC,QAAA,MAAM,YAAA,GAAe,KAAK,OAAA,CAAQ,cAAA,EAAgB,GAAGA,qBAAA,EAAkB,CAAA,EAAG,cAAc,CAAA,CAAE,CAAA;AAE1F,QAAA,UAAA,CAAW,OAAA,CAAQ,OAAA,CAAQ,MAAA,CAAO,YAAY,CAAC,CAAA;AAC/C,QAAA;AAAA,MACF;AAEA,MAAA,UAAA,CAAW,OAAA,CAAQ,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,IACzC;AAAA,GACD,CAAA;AAED,EAAA,OAAO,MAAA;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/cloudflare/index.ts"],"sourcesContent":["import { getTraceMetaTags } from '@sentry/core';\n\nexport * from '../client';\n\nexport { wrapSentryHandleRequest } from '../server/wrapSentryHandleRequest';\n\n/**\n * Injects Sentry trace meta tags into the HTML response by transforming the ReadableStream.\n * This enables distributed tracing by adding trace context to the HTML document head.\n * @param body - ReadableStream containing the HTML response body to modify\n * @returns A new ReadableStream with Sentry trace meta tags injected into the head section\n */\nexport function injectTraceMetaTags(body: ReadableStream): ReadableStream {\n const headClosingTag = '</head>';\n\n const reader = body.getReader();\n const encoder = new TextEncoder();\n // A single streaming decoder carries incomplete multi-byte sequences across chunk\n // boundaries. A fresh, non-streaming decoder per chunk would flush a split character\n // as U+FFFD, corrupting the response (see https://github.com/whatwg/encoding/issues/184).\n const decoder = new TextDecoder();\n const stream = new ReadableStream({\n async pull(controller) {\n const { done, value } = await reader.read();\n\n if (done) {\n controller.close();\n return;\n }\n\n const html = value instanceof Uint8Array ? decoder.decode(value, { stream: true }) : String(value);\n\n if (html.includes(headClosingTag)) {\n const modifiedHtml = html.replace(headClosingTag, `${getTraceMetaTags()}${headClosingTag}`);\n\n controller.enqueue(encoder.encode(modifiedHtml));\n return;\n }\n\n controller.enqueue(encoder.encode(html));\n },\n });\n\n return stream;\n}\n"],"names":["getTraceMetaTags"],"mappings":";;;;;;;;;;;AAYO,SAAS,oBAAoB,IAAA,EAAsC;AACxE,EAAA,MAAM,cAAA,GAAiB,SAAA;AAEvB,EAAA,MAAM,MAAA,GAAS,KAAK,SAAA,EAAU;AAC9B,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAIhC,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,MAAM,MAAA,GAAS,IAAI,cAAA,CAAe;AAAA,IAChC,MAAM,KAAK,UAAA,EAAY;AACrB,MAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,OAAO,IAAA,EAAK;AAE1C,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,UAAA,CAAW,KAAA,EAAM;AACjB,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,IAAA,GAAO,KAAA,YAAiB,UAAA,GAAa,OAAA,CAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,CAAA,GAAI,MAAA,CAAO,KAAK,CAAA;AAEjG,MAAA,IAAI,IAAA,CAAK,QAAA,CAAS,cAAc,CAAA,EAAG;AACjC,QAAA,MAAM,YAAA,GAAe,KAAK,OAAA,CAAQ,cAAA,EAAgB,GAAGA,qBAAA,EAAkB,CAAA,EAAG,cAAc,CAAA,CAAE,CAAA;AAE1F,QAAA,UAAA,CAAW,OAAA,CAAQ,OAAA,CAAQ,MAAA,CAAO,YAAY,CAAC,CAAA;AAC/C,QAAA;AAAA,MACF;AAEA,MAAA,UAAA,CAAW,OAAA,CAAQ,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAC,CAAA;AAAA,IACzC;AAAA,GACD,CAAA;AAED,EAAA,OAAO,MAAA;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../src/common/utils.ts"],"sourcesContent":["import { captureException, debug } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport type { InstrumentationResult } from './types';\n\n/**\n * Extracts pathname from request URL.\n * Falls back to '<unknown>' with DEBUG warning if URL cannot be parsed.\n */\nexport function getPathFromRequest(request: { url: string }): string {\n try {\n return new URL(request.url).pathname;\n } catch {\n try {\n // Fallback: use a dummy base URL since we only care about the pathname\n return new URL(request.url, 'http://example.com').pathname;\n } catch (error) {\n DEBUG_BUILD && debug.warn('Failed to parse URL from request:', request.url, error);\n return '<unknown>';\n }\n }\n}\n\n/**\n * Extracts route pattern from instrumentation info.\n * Prefers `pattern` (planned for v8) over `unstable_pattern` (v7.x).\n */\nexport function getPattern(info: { pattern?: string; unstable_pattern?: string }): string | undefined {\n return info.pattern ?? info.unstable_pattern;\n}\n\n/**\n * Normalizes route path by ensuring it starts with a slash.\n * Returns undefined if the input is falsy.\n */\nexport function normalizeRoutePath(pattern?: string): string | undefined {\n if (!pattern) {\n return undefined;\n }\n return pattern.startsWith('/') ? pattern : `/${pattern}`;\n}\n\n/**\n * Captures an error from instrumentation result.\n * Caller must verify result contains an Error before calling.\n */\nexport function captureInstrumentationError(\n result: InstrumentationResult,\n captureErrors: boolean,\n mechanismType: string,\n data: Record<string, string | boolean>,\n): void {\n if (captureErrors) {\n captureException(result.error, {\n mechanism: {\n type: mechanismType,\n handled: false,\n data,\n },\n });\n }\n}\n"],"names":["DEBUG_BUILD","debug","captureException"],"mappings":";;;;;AAQO,SAAS,mBAAmB,OAAA,EAAkC;AACnE,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA,CAAE,QAAA;AAAA,EAC9B,CAAA,CAAA,MAAQ;AACN,IAAA,IAAI;AAEF,MAAA,OAAO,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,EAAK,oBAAoB,CAAA,CAAE,QAAA;AAAA,IACpD,SAAS,KAAA,EAAO;AACd,MAAAA,sBAAA,IAAeC,UAAA,CAAM,IAAA,CAAK,mCAAA,EAAqC,OAAA,CAAQ,KAAK,KAAK,CAAA;AACjF,MAAA,OAAO,WAAA;AAAA,IACT;AAAA,EACF;AACF;AAMO,SAAS,WAAW,IAAA,EAA2E;AACpG,EAAA,OAAO,IAAA,CAAK,WAAW,IAAA,CAAK,gBAAA;AAC9B;AAMO,SAAS,mBAAmB,OAAA,EAAsC;AACvE,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,QAAQ,UAAA,CAAW,GAAG,CAAA,GAAI,OAAA,GAAU,IAAI,OAAO,CAAA,CAAA;AACxD;AAMO,SAAS,2BAAA,CACd,MAAA,EACA,aAAA,EACA,aAAA,EACA,IAAA,EACM;AACN,EAAA,IAAI,aAAA,EAAe;AACjB,IAAAC,qBAAA,CAAiB,OAAO,KAAA,EAAO;AAAA,MAC7B,SAAA,EAAW;AAAA,QACT,IAAA,EAAM,aAAA;AAAA,QACN,OAAA,EAAS,KAAA;AAAA,QACT;AAAA;AACF,KACD,CAAA;AAAA,EACH;AACF;;;;;;;"}
1
+ {"version":3,"file":"utils.js","sources":["../../../src/common/utils.ts"],"sourcesContent":["import { captureException, debug } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\n\n/**\n * Extracts pathname from request URL.\n * Falls back to '<unknown>' with DEBUG warning if URL cannot be parsed.\n */\nexport function getPathFromRequest(request: { url: string }): string {\n try {\n return new URL(request.url).pathname;\n } catch {\n try {\n // Fallback: use a dummy base URL since we only care about the pathname\n return new URL(request.url, 'http://example.com').pathname;\n } catch (error) {\n DEBUG_BUILD && debug.warn('Failed to parse URL from request:', request.url, error);\n return '<unknown>';\n }\n }\n}\n\n/**\n * Extracts route pattern from instrumentation info.\n * Prefers `pattern` (planned for v8) over `unstable_pattern` (v7.x).\n */\nexport function getPattern(info: { pattern?: string; unstable_pattern?: string }): string | undefined {\n return info.pattern ?? info.unstable_pattern;\n}\n\n/**\n * Normalizes route path by ensuring it starts with a slash.\n * Returns undefined if the input is falsy.\n */\nexport function normalizeRoutePath(pattern?: string): string | undefined {\n if (!pattern) {\n return undefined;\n }\n return pattern.startsWith('/') ? pattern : `/${pattern}`;\n}\n\n/**\n * Captures an error from instrumentation result.\n * Caller must verify result contains an Error before calling.\n */\nexport function captureInstrumentationError(\n result: { error: unknown },\n captureErrors: boolean,\n mechanismType: string,\n data: Record<string, string | boolean>,\n): void {\n if (captureErrors) {\n captureException(result.error, {\n mechanism: {\n type: mechanismType,\n handled: false,\n data,\n },\n });\n }\n}\n"],"names":["DEBUG_BUILD","debug","captureException"],"mappings":";;;;;AAOO,SAAS,mBAAmB,OAAA,EAAkC;AACnE,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA,CAAE,QAAA;AAAA,EAC9B,CAAA,CAAA,MAAQ;AACN,IAAA,IAAI;AAEF,MAAA,OAAO,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,EAAK,oBAAoB,CAAA,CAAE,QAAA;AAAA,IACpD,SAAS,KAAA,EAAO;AACd,MAAAA,sBAAA,IAAeC,UAAA,CAAM,IAAA,CAAK,mCAAA,EAAqC,OAAA,CAAQ,KAAK,KAAK,CAAA;AACjF,MAAA,OAAO,WAAA;AAAA,IACT;AAAA,EACF;AACF;AAMO,SAAS,WAAW,IAAA,EAA2E;AACpG,EAAA,OAAO,IAAA,CAAK,WAAW,IAAA,CAAK,gBAAA;AAC9B;AAMO,SAAS,mBAAmB,OAAA,EAAsC;AACvE,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,QAAQ,UAAA,CAAW,GAAG,CAAA,GAAI,OAAA,GAAU,IAAI,OAAO,CAAA,CAAA;AACxD;AAMO,SAAS,2BAAA,CACd,MAAA,EACA,aAAA,EACA,aAAA,EACA,IAAA,EACM;AACN,EAAA,IAAI,aAAA,EAAe;AACjB,IAAAC,qBAAA,CAAiB,OAAO,KAAA,EAAO;AAAA,MAC7B,SAAA,EAAW;AAAA,QACT,IAAA,EAAM,aAAA;AAAA,QACN,OAAA,EAAS,KAAA;AAAA,QACT;AAAA;AACF,KACD,CAAA;AAAA,EACH;AACF;;;;;;;"}
@@ -7,23 +7,16 @@ const createSentryHandleRequest = require('./server/createSentryHandleRequest.js
7
7
  const createSentryHandleError = require('./server/createSentryHandleError.js');
8
8
  const getMetaTagTransformer = require('./server/getMetaTagTransformer.js');
9
9
  const createServerInstrumentation = require('./server/createServerInstrumentation.js');
10
- const plugin = require('./vite/plugin.js');
11
- const handleOnBuildEnd = require('./vite/buildEnd/handleOnBuildEnd.js');
12
- const makeConfigInjectorPlugin = require('./vite/makeConfigInjectorPlugin.js');
13
10
  const serverGlobals = require('./server/serverGlobals.js');
14
11
 
15
12
 
16
13
 
17
14
  exports.init = sdk.init;
18
- exports.sentryHandleRequest = wrapSentryHandleRequest.sentryHandleRequest;
19
15
  exports.wrapSentryHandleRequest = wrapSentryHandleRequest.wrapSentryHandleRequest;
20
16
  exports.createSentryHandleRequest = createSentryHandleRequest.createSentryHandleRequest;
21
17
  exports.createSentryHandleError = createSentryHandleError.createSentryHandleError;
22
18
  exports.getMetaTagTransformer = getMetaTagTransformer.getMetaTagTransformer;
23
19
  exports.createSentryServerInstrumentation = createServerInstrumentation.createSentryServerInstrumentation;
24
- exports.sentryReactRouter = plugin.sentryReactRouter;
25
- exports.sentryOnBuildEnd = handleOnBuildEnd.sentryOnBuildEnd;
26
- exports.makeConfigInjectorPlugin = makeConfigInjectorPlugin.makeConfigInjectorPlugin;
27
20
  exports.isInstrumentationApiUsed = serverGlobals.isInstrumentationApiUsed;
28
21
  Object.prototype.hasOwnProperty.call(node, '__proto__') &&
29
22
  !Object.prototype.hasOwnProperty.call(exports, '__proto__') &&
@@ -1 +1 @@
1
- {"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -20,12 +20,14 @@ function createSentryServerInstrumentation(options = {}) {
20
20
  const pathname = utils.getPathFromRequest(info.request);
21
21
  const activeSpan = core.getActiveSpan();
22
22
  const existingRootSpan = activeSpan ? core.getRootSpan(activeSpan) : void 0;
23
+ const client = core.getClient();
24
+ const unparameterizedName = client && core.hasSpanStreamingEnabled(client) ? info.request.method?.toUpperCase() || core.HTTP_SPAN_NAME_FALLBACK : `${info.request.method} ${pathname}`;
23
25
  if (existingRootSpan) {
24
- core.updateSpanName(existingRootSpan, `${info.request.method} ${pathname}`);
26
+ core.updateSpanName(existingRootSpan, unparameterizedName);
25
27
  existingRootSpan.setAttributes({
26
28
  [core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
27
29
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.instrumentation_api",
28
- [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
30
+ [attributes.SENTRY_SEGMENT_NAME_SOURCE]: "url",
29
31
  [attributes.URL_FULL]: core.filterCollectedUrl(info.request.url),
30
32
  [attributes.URL_PATH]: pathname
31
33
  });
@@ -34,7 +36,7 @@ function createSentryServerInstrumentation(options = {}) {
34
36
  if (result.status === "error" && result.error instanceof Error) {
35
37
  existingRootSpan.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
36
38
  utils.captureInstrumentationError(result, captureErrors, "react_router.request_handler", {
37
- "http.method": info.request.method,
39
+ [attributes.HTTP_REQUEST_METHOD]: info.request.method,
38
40
  [attributes.URL_FULL]: pathname
39
41
  });
40
42
  }
@@ -44,12 +46,12 @@ function createSentryServerInstrumentation(options = {}) {
44
46
  } else {
45
47
  await core.startSpan(
46
48
  {
47
- name: `${info.request.method} ${pathname}`,
49
+ name: unparameterizedName,
48
50
  forceTransaction: true,
49
51
  attributes: {
50
52
  [core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "http.server",
51
53
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.instrumentation_api",
52
- [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
54
+ [attributes.SENTRY_SEGMENT_NAME_SOURCE]: "url",
53
55
  [attributes.HTTP_REQUEST_METHOD]: info.request.method,
54
56
  [attributes.URL_PATH]: pathname,
55
57
  [attributes.URL_FULL]: core.filterCollectedUrl(info.request.url)
@@ -61,7 +63,7 @@ function createSentryServerInstrumentation(options = {}) {
61
63
  if (result.status === "error" && result.error instanceof Error) {
62
64
  span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
63
65
  utils.captureInstrumentationError(result, captureErrors, "react_router.request_handler", {
64
- "http.method": info.request.method,
66
+ [attributes.HTTP_REQUEST_METHOD]: info.request.method,
65
67
  [attributes.URL_FULL]: pathname
66
68
  });
67
69
  }
@@ -87,7 +89,7 @@ function createSentryServerInstrumentation(options = {}) {
87
89
  {
88
90
  name: routePattern,
89
91
  attributes: {
90
- [attributes.SENTRY_OP]: op.WEB_SERVER_FUNCTION_SPAN_OP,
92
+ [attributes.SENTRY_OP]: op.FUNCTION,
91
93
  [attributes.CODE_FUNCTION_NAME]: "loader",
92
94
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
93
95
  }
@@ -97,7 +99,7 @@ function createSentryServerInstrumentation(options = {}) {
97
99
  if (result.status === "error" && result.error instanceof Error) {
98
100
  span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
99
101
  utils.captureInstrumentationError(result, captureErrors, "react_router.loader", {
100
- "http.method": info.request.method,
102
+ [attributes.HTTP_REQUEST_METHOD]: info.request.method,
101
103
  [attributes.URL_FULL]: urlPath
102
104
  });
103
105
  }
@@ -113,7 +115,7 @@ function createSentryServerInstrumentation(options = {}) {
113
115
  {
114
116
  name: routePattern,
115
117
  attributes: {
116
- [attributes.SENTRY_OP]: op.WEB_SERVER_FUNCTION_SPAN_OP,
118
+ [attributes.SENTRY_OP]: op.FUNCTION,
117
119
  [attributes.CODE_FUNCTION_NAME]: "action",
118
120
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
119
121
  }
@@ -123,7 +125,7 @@ function createSentryServerInstrumentation(options = {}) {
123
125
  if (result.status === "error" && result.error instanceof Error) {
124
126
  span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
125
127
  utils.captureInstrumentationError(result, captureErrors, "react_router.action", {
126
- "http.method": info.request.method,
128
+ [attributes.HTTP_REQUEST_METHOD]: info.request.method,
127
129
  [attributes.URL_FULL]: urlPath
128
130
  });
129
131
  }
@@ -152,7 +154,7 @@ function createSentryServerInstrumentation(options = {}) {
152
154
  {
153
155
  name: `middleware ${middlewareName || routeId}`,
154
156
  attributes: {
155
- [attributes.SENTRY_OP]: op.WEB_SERVER_MIDDLEWARE_SPAN_OP,
157
+ [attributes.SENTRY_OP]: op.MIDDLEWARE,
156
158
  [attributes.CODE_FUNCTION_NAME]: "middleware",
157
159
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api",
158
160
  "react_router.route.id": routeId,
@@ -166,7 +168,7 @@ function createSentryServerInstrumentation(options = {}) {
166
168
  if (result.status === "error" && result.error instanceof Error) {
167
169
  span.setStatus({ code: core.SPAN_STATUS_ERROR, message: "internal_error" });
168
170
  utils.captureInstrumentationError(result, captureErrors, "react_router.middleware", {
169
- "http.method": info.request.method,
171
+ [attributes.HTTP_REQUEST_METHOD]: info.request.method,
170
172
  [attributes.URL_FULL]: urlPath
171
173
  });
172
174
  }
@@ -178,7 +180,7 @@ function createSentryServerInstrumentation(options = {}) {
178
180
  {
179
181
  name: "Lazy Route Load",
180
182
  attributes: {
181
- [attributes.SENTRY_OP]: op.WEB_SERVER_FUNCTION_SPAN_OP,
183
+ [attributes.SENTRY_OP]: op.FUNCTION,
182
184
  [attributes.CODE_FUNCTION_NAME]: "lazy",
183
185
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.function.react_router.instrumentation_api"
184
186
  }
@@ -208,10 +210,15 @@ function updateRootSpanWithRoute(method, pattern, urlPath) {
208
210
  const hasPattern = !!pattern;
209
211
  const routeName = hasPattern ? utils.normalizeRoutePath(pattern) || urlPath : urlPath;
210
212
  const transactionName = `${method} ${routeName}`;
211
- core.updateSpanName(rootSpan, transactionName);
213
+ const client = core.getClient();
214
+ const isUnparameterizedStreamedSpan = !hasPattern && !!client && core.hasSpanStreamingEnabled(client);
215
+ core.updateSpanName(
216
+ rootSpan,
217
+ isUnparameterizedStreamedSpan ? method.toUpperCase() || core.HTTP_SPAN_NAME_FALLBACK : transactionName
218
+ );
212
219
  rootSpan.setAttributes({
213
220
  [attributes.HTTP_ROUTE]: routeName,
214
- [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: hasPattern ? "route" : "url"
221
+ [attributes.SENTRY_SEGMENT_NAME_SOURCE]: hasPattern ? "route" : "url"
215
222
  });
216
223
  core.getCurrentScope().setTransactionName(transactionName);
217
224
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createServerInstrumentation.js","sources":["../../../src/server/createServerInstrumentation.ts"],"sourcesContent":["import {\n CODE_FUNCTION_NAME,\n HTTP_REQUEST_METHOD,\n HTTP_ROUTE,\n SENTRY_OP,\n URL_FULL,\n URL_PATH,\n} from '@sentry/conventions/attributes';\nimport { WEB_SERVER_FUNCTION_SPAN_OP, WEB_SERVER_MIDDLEWARE_SPAN_OP } from '@sentry/conventions/op';\nimport {\n debug,\n flushIfServerless,\n getActiveSpan,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n SPAN_STATUS_ERROR,\n startSpan,\n updateSpanName,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport type { InstrumentableRequestHandler, InstrumentableRoute, ServerInstrumentation } from '../common/types';\nimport { captureInstrumentationError, getPathFromRequest, getPattern, normalizeRoutePath } from '../common/utils';\nimport { getMiddlewareName } from './serverBuild';\nimport { markInstrumentationApiUsed } from './serverGlobals';\n\n// Per-request middleware counters, keyed by the request's root span (the one transaction all of a\n// request's middlewares run under). The root span is the same instance across those middleware hooks\n// whether or not a Sentry OpenTelemetry tracer provider is set up, unlike the OTel context the counter\n// used to live on (which does not propagate without a provider).\nconst middlewareCountersByRootSpan = new WeakMap<object, Record<string, number>>();\n\n// Re-export for backward compatibility and external use\nexport { isInstrumentationApiUsed } from './serverGlobals';\n\n/**\n * Options for creating Sentry server instrumentation.\n */\nexport interface CreateSentryServerInstrumentationOptions {\n /**\n * Whether to capture errors from loaders/actions automatically.\n * @default true\n */\n captureErrors?: boolean;\n}\n\n/**\n * Creates a Sentry server instrumentation for React Router's instrumentation API.\n */\nexport function createSentryServerInstrumentation(\n options: CreateSentryServerInstrumentationOptions = {},\n): ServerInstrumentation {\n const { captureErrors = true } = options;\n\n DEBUG_BUILD && debug.log('React Router server instrumentation created.');\n\n return {\n handler(handler: InstrumentableRequestHandler) {\n // Mark the instrumentation API active only when React Router actually invokes this\n markInstrumentationApiUsed();\n handler.instrument({\n async request(handleRequest, info) {\n const pathname = getPathFromRequest(info.request);\n const activeSpan = getActiveSpan();\n const existingRootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n if (existingRootSpan) {\n updateSpanName(existingRootSpan, `${info.request.method} ${pathname}`);\n existingRootSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [URL_FULL]: filterCollectedUrl(info.request.url),\n [URL_PATH]: pathname,\n });\n\n try {\n const result = await handleRequest();\n if (result.status === 'error' && result.error instanceof Error) {\n existingRootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {\n 'http.method': info.request.method,\n [URL_FULL]: pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n } else {\n await startSpan(\n {\n name: `${info.request.method} ${pathname}`,\n forceTransaction: true,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_PATH]: pathname,\n [URL_FULL]: filterCollectedUrl(info.request.url),\n },\n },\n async span => {\n try {\n const result = await handleRequest();\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.request_handler', {\n 'http.method': info.request.method,\n [URL_FULL]: pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n },\n );\n }\n },\n });\n },\n\n route(route: InstrumentableRoute) {\n // Also mark active here, in case route registration runs (mirrors the handler callback above).\n markInstrumentationApiUsed();\n const routeId = route.id;\n\n route.instrument({\n async loader(callLoader, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: WEB_SERVER_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: '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.loader', {\n 'http.method': info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async action(callAction, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: WEB_SERVER_FUNCTION_SPAN_OP,\n [CODE_FUNCTION_NAME]: '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.action', {\n 'http.method': info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async middleware(callMiddleware, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n let middlewareIndex = 0;\n if (rootSpan) {\n let counters = middlewareCountersByRootSpan.get(rootSpan);\n if (!counters) {\n counters = {};\n middlewareCountersByRootSpan.set(rootSpan, counters);\n }\n middlewareIndex = counters[routeId] ?? 0;\n counters[routeId] = middlewareIndex + 1;\n }\n\n const middlewareName = getMiddlewareName(routeId, middlewareIndex);\n\n await startSpan(\n {\n name: `middleware ${middlewareName || routeId}`,\n attributes: {\n [SENTRY_OP]: WEB_SERVER_MIDDLEWARE_SPAN_OP,\n [CODE_FUNCTION_NAME]: 'middleware',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n 'react_router.route.id': routeId,\n [HTTP_ROUTE]: routePattern,\n ...(middlewareName && { 'react_router.middleware.name': middlewareName }),\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.middleware', {\n 'http.method': info.request.method,\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]: WEB_SERVER_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.lazy', {});\n }\n },\n );\n },\n });\n },\n };\n}\n\nfunction updateRootSpanWithRoute(method: string, pattern: string | undefined, urlPath: string): void {\n const activeSpan = getActiveSpan();\n if (!activeSpan) return;\n const rootSpan = getRootSpan(activeSpan);\n if (!rootSpan) return;\n\n // Skip update if URL path is invalid (failed to parse)\n if (!urlPath || urlPath === '<unknown>') {\n DEBUG_BUILD && debug.warn('Cannot update span with invalid URL path:', urlPath);\n return;\n }\n\n const hasPattern = !!pattern;\n const routeName = hasPattern ? normalizeRoutePath(pattern) || urlPath : urlPath;\n\n const transactionName = `${method} ${routeName}`;\n updateSpanName(rootSpan, transactionName);\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: hasPattern ? 'route' : 'url',\n });\n\n // Also update the scope's transaction name so errors captured during this request\n // have the correct transaction name (not the initial placeholder like \"GET *\")\n getCurrentScope().setTransactionName(transactionName);\n}\n"],"names":["DEBUG_BUILD","debug","markInstrumentationApiUsed","getPathFromRequest","getActiveSpan","getRootSpan","updateSpanName","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","URL_FULL","filterCollectedUrl","URL_PATH","SPAN_STATUS_ERROR","captureInstrumentationError","flushIfServerless","startSpan","HTTP_REQUEST_METHOD","getPattern","normalizeRoutePath","SENTRY_OP","WEB_SERVER_FUNCTION_SPAN_OP","CODE_FUNCTION_NAME","getMiddlewareName","WEB_SERVER_MIDDLEWARE_SPAN_OP","HTTP_ROUTE","getCurrentScope"],"mappings":"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"}
1
+ {"version":3,"file":"createServerInstrumentation.js","sources":["../../../src/server/createServerInstrumentation.ts"],"sourcesContent":["import {\n SENTRY_SEGMENT_NAME_SOURCE,\n CODE_FUNCTION_NAME,\n HTTP_REQUEST_METHOD,\n HTTP_ROUTE,\n SENTRY_OP,\n URL_FULL,\n URL_PATH,\n} from '@sentry/conventions/attributes';\nimport { FUNCTION, MIDDLEWARE } from '@sentry/conventions/op';\nimport {\n debug,\n flushIfServerless,\n getActiveSpan,\n getClient,\n getCurrentScope,\n getRootSpan,\n hasSpanStreamingEnabled,\n HTTP_SPAN_NAME_FALLBACK,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_ERROR,\n startSpan,\n updateSpanName,\n filterCollectedUrl,\n} from '@sentry/core';\nimport type { ServerInstrumentation } from 'react-router';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport { captureInstrumentationError, getPathFromRequest, getPattern, normalizeRoutePath } from '../common/utils';\nimport { getMiddlewareName } from './serverBuild';\nimport { markInstrumentationApiUsed } from './serverGlobals';\n\n// Per-request middleware counters, keyed by the request's root span (the one transaction all of a\n// request's middlewares run under). The root span is the same instance across those middleware hooks\n// whether or not a Sentry OpenTelemetry tracer provider is set up, unlike the OTel context the counter\n// used to live on (which does not propagate without a provider).\nconst middlewareCountersByRootSpan = new WeakMap<object, Record<string, number>>();\n\n// Re-export for backward compatibility and external use\nexport { isInstrumentationApiUsed } from './serverGlobals';\n\n/**\n * Options for creating Sentry server instrumentation.\n */\nexport interface CreateSentryServerInstrumentationOptions {\n /**\n * Whether to capture errors from loaders/actions automatically.\n * @default true\n */\n captureErrors?: boolean;\n}\n\n/**\n * Creates a Sentry server instrumentation for React Router's instrumentation API.\n */\nexport function createSentryServerInstrumentation(\n options: CreateSentryServerInstrumentationOptions = {},\n): ServerInstrumentation {\n const { captureErrors = true } = options;\n\n DEBUG_BUILD && debug.log('React Router server instrumentation created.');\n\n return {\n handler(handler) {\n // Mark the instrumentation API active only when React Router actually invokes this\n markInstrumentationApiUsed();\n handler.instrument({\n async request(handleRequest, info) {\n const pathname = getPathFromRequest(info.request);\n const activeSpan = getActiveSpan();\n const existingRootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n const client = getClient();\n // With span streaming, span names have to be low cardinality, so we can't fall back to the URL\n // path. `updateRootSpanWithRoute` renames the span once React Router matches a route.\n const unparameterizedName =\n client && hasSpanStreamingEnabled(client)\n ? info.request.method?.toUpperCase() || HTTP_SPAN_NAME_FALLBACK\n : `${info.request.method} ${pathname}`;\n\n if (existingRootSpan) {\n updateSpanName(existingRootSpan, unparameterizedName);\n existingRootSpan.setAttributes({\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'url',\n [URL_FULL]: filterCollectedUrl(info.request.url),\n [URL_PATH]: pathname,\n });\n\n try {\n const result = await handleRequest();\n if (result.status === 'error' && result.error instanceof Error) {\n existingRootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });\n captureInstrumentationError(result, captureErrors, 'react_router.request_handler', {\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_FULL]: pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n } else {\n await startSpan(\n {\n name: unparameterizedName,\n forceTransaction: true,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.server',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.instrumentation_api',\n [SENTRY_SEGMENT_NAME_SOURCE]: 'url',\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_PATH]: pathname,\n [URL_FULL]: filterCollectedUrl(info.request.url),\n },\n },\n async span => {\n try {\n const result = await handleRequest();\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.request_handler', {\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_FULL]: pathname,\n });\n }\n } finally {\n await flushIfServerless();\n }\n },\n );\n }\n },\n });\n },\n\n route(route) {\n // Also mark active here, in case route registration runs (mirrors the handler callback above).\n markInstrumentationApiUsed();\n const routeId = route.id;\n\n route.instrument({\n async loader(callLoader, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: FUNCTION,\n [CODE_FUNCTION_NAME]: '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.loader', {\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async action(callAction, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n await startSpan(\n {\n name: routePattern,\n attributes: {\n [SENTRY_OP]: FUNCTION,\n [CODE_FUNCTION_NAME]: '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.action', {\n [HTTP_REQUEST_METHOD]: info.request.method,\n [URL_FULL]: urlPath,\n });\n }\n },\n );\n },\n\n async middleware(callMiddleware, info) {\n const urlPath = getPathFromRequest(info.request);\n const pattern = getPattern(info);\n const routePattern = normalizeRoutePath(pattern) || urlPath;\n\n updateRootSpanWithRoute(info.request.method, pattern, urlPath);\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n let middlewareIndex = 0;\n if (rootSpan) {\n let counters = middlewareCountersByRootSpan.get(rootSpan);\n if (!counters) {\n counters = {};\n middlewareCountersByRootSpan.set(rootSpan, counters);\n }\n middlewareIndex = counters[routeId] ?? 0;\n counters[routeId] = middlewareIndex + 1;\n }\n\n const middlewareName = getMiddlewareName(routeId, middlewareIndex);\n\n await startSpan(\n {\n name: `middleware ${middlewareName || routeId}`,\n attributes: {\n [SENTRY_OP]: MIDDLEWARE,\n [CODE_FUNCTION_NAME]: 'middleware',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.react_router.instrumentation_api',\n 'react_router.route.id': routeId,\n [HTTP_ROUTE]: routePattern,\n ...(middlewareName && { 'react_router.middleware.name': middlewareName }),\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.middleware', {\n [HTTP_REQUEST_METHOD]: info.request.method,\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]: FUNCTION,\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.lazy', {});\n }\n },\n );\n },\n });\n },\n };\n}\n\nfunction updateRootSpanWithRoute(method: string, pattern: string | undefined, urlPath: string): void {\n const activeSpan = getActiveSpan();\n if (!activeSpan) return;\n const rootSpan = getRootSpan(activeSpan);\n if (!rootSpan) return;\n\n // Skip update if URL path is invalid (failed to parse)\n if (!urlPath || urlPath === '<unknown>') {\n DEBUG_BUILD && debug.warn('Cannot update span with invalid URL path:', urlPath);\n return;\n }\n\n const hasPattern = !!pattern;\n const routeName = hasPattern ? normalizeRoutePath(pattern) || urlPath : urlPath;\n\n const transactionName = `${method} ${routeName}`;\n\n const client = getClient();\n // With span streaming, span names have to be low cardinality, so we can't fall back to the URL path.\n const isUnparameterizedStreamedSpan = !hasPattern && !!client && hasSpanStreamingEnabled(client);\n updateSpanName(\n rootSpan,\n isUnparameterizedStreamedSpan ? method.toUpperCase() || HTTP_SPAN_NAME_FALLBACK : transactionName,\n );\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SENTRY_SEGMENT_NAME_SOURCE]: hasPattern ? 'route' : 'url',\n });\n\n // Also update the scope's transaction name so errors captured during this request\n // have the correct transaction name (not the initial placeholder like \"GET *\")\n getCurrentScope().setTransactionName(transactionName);\n}\n"],"names":["DEBUG_BUILD","debug","markInstrumentationApiUsed","getPathFromRequest","getActiveSpan","getRootSpan","getClient","hasSpanStreamingEnabled","HTTP_SPAN_NAME_FALLBACK","updateSpanName","SEMANTIC_ATTRIBUTE_SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SENTRY_SEGMENT_NAME_SOURCE","URL_FULL","filterCollectedUrl","URL_PATH","SPAN_STATUS_ERROR","captureInstrumentationError","HTTP_REQUEST_METHOD","flushIfServerless","startSpan","getPattern","normalizeRoutePath","SENTRY_OP","FUNCTION","CODE_FUNCTION_NAME","getMiddlewareName","MIDDLEWARE","HTTP_ROUTE","getCurrentScope"],"mappings":"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"}
@@ -5,15 +5,16 @@ const core = require('@sentry/core');
5
5
 
6
6
  function getMetaTagTransformer(body) {
7
7
  const headClosingTag = "</head>";
8
+ const decoder = new TextDecoder();
8
9
  const htmlMetaTagTransformer = new node_stream.Transform({
9
10
  transform(chunk, _encoding, callback) {
10
- const html = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);
11
+ const html = Buffer.isBuffer(chunk) ? decoder.decode(chunk, { stream: true }) : String(chunk);
11
12
  if (html.includes(headClosingTag)) {
12
13
  const modifiedHtml = html.replace(headClosingTag, `${core.getTraceMetaTags()}${headClosingTag}`);
13
14
  callback(null, modifiedHtml);
14
15
  return;
15
16
  }
16
- callback(null, chunk);
17
+ callback(null, html);
17
18
  }
18
19
  });
19
20
  htmlMetaTagTransformer.pipe(body);
@@ -1 +1 @@
1
- {"version":3,"file":"getMetaTagTransformer.js","sources":["../../../src/server/getMetaTagTransformer.ts"],"sourcesContent":["import type { PassThrough } from 'node:stream';\nimport { Transform } from 'node:stream';\nimport { getTraceMetaTags } from '@sentry/core';\n\n/**\n * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.\n * This enables distributed tracing by adding trace context to the HTML document head.\n *\n * @param body - PassThrough stream containing the HTML response body to modify\n */\nexport function getMetaTagTransformer(body: PassThrough): Transform {\n const headClosingTag = '</head>';\n const htmlMetaTagTransformer = new Transform({\n transform(chunk, _encoding, callback) {\n const html = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);\n if (html.includes(headClosingTag)) {\n const modifiedHtml = html.replace(headClosingTag, `${getTraceMetaTags()}${headClosingTag}`);\n callback(null, modifiedHtml);\n return;\n }\n callback(null, chunk);\n },\n });\n htmlMetaTagTransformer.pipe(body);\n return htmlMetaTagTransformer;\n}\n"],"names":["Transform","getTraceMetaTags"],"mappings":";;;;;AAUO,SAAS,sBAAsB,IAAA,EAA8B;AAClE,EAAA,MAAM,cAAA,GAAiB,SAAA;AACvB,EAAA,MAAM,sBAAA,GAAyB,IAAIA,qBAAA,CAAU;AAAA,IAC3C,SAAA,CAAU,KAAA,EAAO,SAAA,EAAW,QAAA,EAAU;AACpC,MAAA,MAAM,IAAA,GAAO,OAAO,QAAA,CAAS,KAAK,IAAI,KAAA,CAAM,QAAA,EAAS,GAAI,MAAA,CAAO,KAAK,CAAA;AACrE,MAAA,IAAI,IAAA,CAAK,QAAA,CAAS,cAAc,CAAA,EAAG;AACjC,QAAA,MAAM,YAAA,GAAe,KAAK,OAAA,CAAQ,cAAA,EAAgB,GAAGC,qBAAA,EAAkB,CAAA,EAAG,cAAc,CAAA,CAAE,CAAA;AAC1F,QAAA,QAAA,CAAS,MAAM,YAAY,CAAA;AAC3B,QAAA;AAAA,MACF;AACA,MAAA,QAAA,CAAS,MAAM,KAAK,CAAA;AAAA,IACtB;AAAA,GACD,CAAA;AACD,EAAA,sBAAA,CAAuB,KAAK,IAAI,CAAA;AAChC,EAAA,OAAO,sBAAA;AACT;;;;"}
1
+ {"version":3,"file":"getMetaTagTransformer.js","sources":["../../../src/server/getMetaTagTransformer.ts"],"sourcesContent":["import type { PassThrough } from 'node:stream';\nimport { Transform } from 'node:stream';\nimport { getTraceMetaTags } from '@sentry/core';\n\n/**\n * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.\n * This enables distributed tracing by adding trace context to the HTML document head.\n *\n * @param body - PassThrough stream containing the HTML response body to modify\n */\nexport function getMetaTagTransformer(body: PassThrough): Transform {\n const headClosingTag = '</head>';\n // A single streaming decoder carries incomplete multi-byte sequences across chunk\n // boundaries. Decoding each chunk on its own (e.g. `Buffer.toString()`) would flush a\n // split character as U+FFFD, corrupting the response (see\n // https://github.com/whatwg/encoding/issues/184).\n const decoder = new TextDecoder();\n const htmlMetaTagTransformer = new Transform({\n transform(chunk, _encoding, callback) {\n const html = Buffer.isBuffer(chunk) ? decoder.decode(chunk, { stream: true }) : String(chunk);\n if (html.includes(headClosingTag)) {\n const modifiedHtml = html.replace(headClosingTag, `${getTraceMetaTags()}${headClosingTag}`);\n callback(null, modifiedHtml);\n return;\n }\n callback(null, html);\n },\n });\n htmlMetaTagTransformer.pipe(body);\n return htmlMetaTagTransformer;\n}\n"],"names":["Transform","getTraceMetaTags"],"mappings":";;;;;AAUO,SAAS,sBAAsB,IAAA,EAA8B;AAClE,EAAA,MAAM,cAAA,GAAiB,SAAA;AAKvB,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,MAAM,sBAAA,GAAyB,IAAIA,qBAAA,CAAU;AAAA,IAC3C,SAAA,CAAU,KAAA,EAAO,SAAA,EAAW,QAAA,EAAU;AACpC,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,QAAA,CAAS,KAAK,IAAI,OAAA,CAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,MAAA,EAAQ,IAAA,EAAM,CAAA,GAAI,OAAO,KAAK,CAAA;AAC5F,MAAA,IAAI,IAAA,CAAK,QAAA,CAAS,cAAc,CAAA,EAAG;AACjC,QAAA,MAAM,YAAA,GAAe,KAAK,OAAA,CAAQ,cAAA,EAAgB,GAAGC,qBAAA,EAAkB,CAAA,EAAG,cAAc,CAAA,CAAE,CAAA;AAC1F,QAAA,QAAA,CAAS,MAAM,YAAY,CAAA;AAC3B,QAAA;AAAA,MACF;AACA,MAAA,QAAA,CAAS,MAAM,IAAI,CAAA;AAAA,IACrB;AAAA,GACD,CAAA;AACD,EAAA,sBAAA,CAAuB,KAAK,IAAI,CAAA;AAChC,EAAA,OAAO,sBAAA;AACT;;;;"}
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
+ const attributes = require('@sentry/conventions/attributes');
3
4
  const core = require('@sentry/core');
4
5
 
5
6
  const LOW_QUALITY_TRANSACTIONS_FILTERS = [
@@ -7,10 +8,10 @@ const LOW_QUALITY_TRANSACTIONS_FILTERS = [
7
8
  /GET \/favicon\.ico/,
8
9
  /GET \/@id\//,
9
10
  // The span description for the `__manifest` endpoint is `GET *` (`http.route` resolves to `*`).
10
- // Filter by `http.target` instead, which carries the raw request path.
11
- { attributes: { "http.target": /\/__manifest/ } }
11
+ // Filter by `url.path` instead, which carries the raw request path.
12
+ { attributes: { [attributes.URL_PATH]: /\/__manifest/ } }
12
13
  ];
13
- const _lowQualityTransactionsFilterIntegration = ((_options) => ({
14
+ const _lowQualityTransactionsFilterIntegration = (() => ({
14
15
  name: "LowQualityTransactionsFilter",
15
16
  beforeSetup(client) {
16
17
  const opts = client.getOptions();
@@ -1 +1 @@
1
- {"version":3,"file":"lowQualityTransactionsFilterIntegration.js","sources":["../../../../src/server/integration/lowQualityTransactionsFilterIntegration.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\nimport type { NodeOptions } from '@sentry/node';\n\nconst LOW_QUALITY_TRANSACTIONS_FILTERS = [\n /GET \\/node_modules\\//,\n /GET \\/favicon\\.ico/,\n /GET \\/@id\\//,\n // The span description for the `__manifest` endpoint is `GET *` (`http.route` resolves to `*`).\n // Filter by `http.target` instead, which carries the raw request path.\n { attributes: { 'http.target': /\\/__manifest/ } },\n];\n\n// TODO(v11): Remove the `_options` parameter (unused and only kept for back-compat with the previous signature)\nconst _lowQualityTransactionsFilterIntegration = ((_options?: NodeOptions) => ({\n name: 'LowQualityTransactionsFilter' as const,\n beforeSetup(client) {\n const opts = client.getOptions();\n opts.ignoreSpans = [...(opts.ignoreSpans || []), ...LOW_QUALITY_TRANSACTIONS_FILTERS];\n },\n})) satisfies IntegrationFn;\n\n/**\n * Integration that filters out noisy http transactions such as requests to node_modules, favicon.ico, @id/, __manifest.\n * Adds entries to `ignoreSpans` so the filter applies in both static and streaming trace lifecycles.\n */\nexport const lowQualityTransactionsFilterIntegration = defineIntegration(_lowQualityTransactionsFilterIntegration);\n"],"names":["defineIntegration"],"mappings":";;;;AAIA,MAAM,gCAAA,GAAmC;AAAA,EACvC,sBAAA;AAAA,EACA,oBAAA;AAAA,EACA,aAAA;AAAA;AAAA;AAAA,EAGA,EAAE,UAAA,EAAY,EAAE,aAAA,EAAe,gBAAe;AAChD,CAAA;AAGA,MAAM,wCAAA,IAA4C,CAAC,QAAA,MAA4B;AAAA,EAC7E,IAAA,EAAM,8BAAA;AAAA,EACN,YAAY,MAAA,EAAQ;AAClB,IAAA,MAAM,IAAA,GAAO,OAAO,UAAA,EAAW;AAC/B,IAAA,IAAA,CAAK,WAAA,GAAc,CAAC,GAAI,IAAA,CAAK,eAAe,EAAC,EAAI,GAAG,gCAAgC,CAAA;AAAA,EACtF;AACF,CAAA,CAAA,CAAA;AAMO,MAAM,uCAAA,GAA0CA,uBAAkB,wCAAwC;;;;"}
1
+ {"version":3,"file":"lowQualityTransactionsFilterIntegration.js","sources":["../../../../src/server/integration/lowQualityTransactionsFilterIntegration.ts"],"sourcesContent":["import { URL_PATH } from '@sentry/conventions/attributes';\nimport type { IntegrationFn } from '@sentry/core';\nimport { defineIntegration } from '@sentry/core';\n\nconst LOW_QUALITY_TRANSACTIONS_FILTERS = [\n /GET \\/node_modules\\//,\n /GET \\/favicon\\.ico/,\n /GET \\/@id\\//,\n // The span description for the `__manifest` endpoint is `GET *` (`http.route` resolves to `*`).\n // Filter by `url.path` instead, which carries the raw request path.\n { attributes: { [URL_PATH]: /\\/__manifest/ } },\n];\n\nconst _lowQualityTransactionsFilterIntegration = (() => ({\n name: 'LowQualityTransactionsFilter' as const,\n beforeSetup(client) {\n const opts = client.getOptions();\n opts.ignoreSpans = [...(opts.ignoreSpans || []), ...LOW_QUALITY_TRANSACTIONS_FILTERS];\n },\n})) satisfies IntegrationFn;\n\n/**\n * Integration that filters out noisy http transactions such as requests to node_modules, favicon.ico, @id/, __manifest.\n * Adds entries to `ignoreSpans` so the filter applies in both static and streaming trace lifecycles.\n */\nexport const lowQualityTransactionsFilterIntegration = defineIntegration(_lowQualityTransactionsFilterIntegration);\n"],"names":["URL_PATH","defineIntegration"],"mappings":";;;;;AAIA,MAAM,gCAAA,GAAmC;AAAA,EACvC,sBAAA;AAAA,EACA,oBAAA;AAAA,EACA,aAAA;AAAA;AAAA;AAAA,EAGA,EAAE,UAAA,EAAY,EAAE,CAACA,mBAAQ,GAAG,gBAAe;AAC7C,CAAA;AAEA,MAAM,4CAA4C,OAAO;AAAA,EACvD,IAAA,EAAM,8BAAA;AAAA,EACN,YAAY,MAAA,EAAQ;AAClB,IAAA,MAAM,IAAA,GAAO,OAAO,UAAA,EAAW;AAC/B,IAAA,IAAA,CAAK,WAAA,GAAc,CAAC,GAAI,IAAA,CAAK,eAAe,EAAC,EAAI,GAAG,gCAAgC,CAAA;AAAA,EACtF;AACF,CAAA,CAAA,CAAA;AAMO,MAAM,uCAAA,GAA0CC,uBAAkB,wCAAwC;;;;"}
@@ -9,7 +9,7 @@ const reactRouterServer = require('./integration/reactRouterServer.js');
9
9
  function getDefaultReactRouterServerIntegrations(options) {
10
10
  return [
11
11
  ...node.getDefaultIntegrations(options),
12
- lowQualityTransactionsFilterIntegration.lowQualityTransactionsFilterIntegration(options),
12
+ lowQualityTransactionsFilterIntegration.lowQualityTransactionsFilterIntegration(),
13
13
  reactRouterServer.reactRouterServerIntegration()
14
14
  ];
15
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { applySdkMetadata, debug, setTag } from '@sentry/core';\nimport type { NodeClient, NodeOptions } from '@sentry/node';\nimport { getDefaultIntegrations as getNodeDefaultIntegrations, init as initNodeSdk } from '@sentry/node';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport { lowQualityTransactionsFilterIntegration } from './integration/lowQualityTransactionsFilterIntegration';\nimport { reactRouterServerIntegration } from './integration/reactRouterServer';\n\n/**\n * Returns the default integrations for the React Router SDK.\n * @param options The options for the SDK.\n */\nexport function getDefaultReactRouterServerIntegrations(options: NodeOptions): Integration[] {\n return [\n ...getNodeDefaultIntegrations(options),\n lowQualityTransactionsFilterIntegration(options),\n reactRouterServerIntegration(),\n ];\n}\n\n/**\n * Initializes the server side of the React Router SDK\n */\nexport function init(options: NodeOptions): NodeClient | undefined {\n const opts: NodeOptions = {\n ...options,\n defaultIntegrations: getDefaultReactRouterServerIntegrations(options),\n };\n\n DEBUG_BUILD && debug.log('Initializing SDK...');\n\n applySdkMetadata(opts, 'react-router', ['react-router', 'node']);\n\n const client = initNodeSdk(opts);\n\n setTag('runtime', 'node');\n\n DEBUG_BUILD && debug.log('SDK successfully initialized');\n\n return client;\n}\n"],"names":["getNodeDefaultIntegrations","lowQualityTransactionsFilterIntegration","reactRouterServerIntegration","DEBUG_BUILD","debug","applySdkMetadata","initNodeSdk","setTag"],"mappings":";;;;;;;;AAYO,SAAS,wCAAwC,OAAA,EAAqC;AAC3F,EAAA,OAAO;AAAA,IACL,GAAGA,4BAA2B,OAAO,CAAA;AAAA,IACrCC,gFAAwC,OAAO,CAAA;AAAA,IAC/CC,8CAAA;AAA6B,GAC/B;AACF;AAKO,SAAS,KAAK,OAAA,EAA8C;AACjE,EAAA,MAAM,IAAA,GAAoB;AAAA,IACxB,GAAG,OAAA;AAAA,IACH,mBAAA,EAAqB,wCAAwC,OAAO;AAAA,GACtE;AAEA,EAAAC,sBAAA,IAAeC,UAAA,CAAM,IAAI,qBAAqB,CAAA;AAE9C,EAAAC,qBAAA,CAAiB,IAAA,EAAM,cAAA,EAAgB,CAAC,cAAA,EAAgB,MAAM,CAAC,CAAA;AAE/D,EAAA,MAAM,MAAA,GAASC,UAAY,IAAI,CAAA;AAE/B,EAAAC,WAAA,CAAO,WAAW,MAAM,CAAA;AAExB,EAAAJ,sBAAA,IAAeC,UAAA,CAAM,IAAI,8BAA8B,CAAA;AAEvD,EAAA,OAAO,MAAA;AACT;;;;;"}
1
+ {"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import type { Integration } from '@sentry/core';\nimport { applySdkMetadata, debug, setTag } from '@sentry/core';\nimport type { NodeClient, NodeOptions } from '@sentry/node';\nimport { getDefaultIntegrations as getNodeDefaultIntegrations, init as initNodeSdk } from '@sentry/node';\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport { lowQualityTransactionsFilterIntegration } from './integration/lowQualityTransactionsFilterIntegration';\nimport { reactRouterServerIntegration } from './integration/reactRouterServer';\n\n/**\n * Returns the default integrations for the React Router SDK.\n * @param options The options for the SDK.\n */\nexport function getDefaultReactRouterServerIntegrations(options: NodeOptions): Integration[] {\n return [\n ...getNodeDefaultIntegrations(options),\n lowQualityTransactionsFilterIntegration(),\n reactRouterServerIntegration(),\n ];\n}\n\n/**\n * Initializes the server side of the React Router SDK\n */\nexport function init(options: NodeOptions): NodeClient | undefined {\n const opts: NodeOptions = {\n ...options,\n defaultIntegrations: getDefaultReactRouterServerIntegrations(options),\n };\n\n DEBUG_BUILD && debug.log('Initializing SDK...');\n\n applySdkMetadata(opts, 'react-router', ['react-router', 'node']);\n\n const client = initNodeSdk(opts);\n\n setTag('runtime', 'node');\n\n DEBUG_BUILD && debug.log('SDK successfully initialized');\n\n return client;\n}\n"],"names":["getNodeDefaultIntegrations","lowQualityTransactionsFilterIntegration","reactRouterServerIntegration","DEBUG_BUILD","debug","applySdkMetadata","initNodeSdk","setTag"],"mappings":";;;;;;;;AAYO,SAAS,wCAAwC,OAAA,EAAqC;AAC3F,EAAA,OAAO;AAAA,IACL,GAAGA,4BAA2B,OAAO,CAAA;AAAA,IACrCC,+EAAA,EAAwC;AAAA,IACxCC,8CAAA;AAA6B,GAC/B;AACF;AAKO,SAAS,KAAK,OAAA,EAA8C;AACjE,EAAA,MAAM,IAAA,GAAoB;AAAA,IACxB,GAAG,OAAA;AAAA,IACH,mBAAA,EAAqB,wCAAwC,OAAO;AAAA,GACtE;AAEA,EAAAC,sBAAA,IAAeC,UAAA,CAAM,IAAI,qBAAqB,CAAA;AAE9C,EAAAC,qBAAA,CAAiB,IAAA,EAAM,cAAA,EAAgB,CAAC,cAAA,EAAgB,MAAM,CAAC,CAAA;AAE/D,EAAA,MAAM,MAAA,GAASC,UAAY,IAAI,CAAA;AAE/B,EAAAC,WAAA,CAAO,WAAW,MAAM,CAAA;AAExB,EAAAJ,sBAAA,IAAeC,UAAA,CAAM,IAAI,8BAA8B,CAAA;AAEvD,EAAA,OAAO,MAAA;AACT;;;;;"}
@@ -17,12 +17,12 @@ function wrapSentryHandleRequest(originalHandle) {
17
17
  if (serverGlobals.isInstrumentationApiUsed()) {
18
18
  rootSpan.setAttributes({
19
19
  [attributes.HTTP_ROUTE]: routeName,
20
- [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route"
20
+ [attributes.SENTRY_SEGMENT_NAME_SOURCE]: "route"
21
21
  });
22
22
  } else {
23
23
  rootSpan.setAttributes({
24
24
  [attributes.HTTP_ROUTE]: routeName,
25
- [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "route",
25
+ [attributes.SENTRY_SEGMENT_NAME_SOURCE]: "route",
26
26
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.react_router.request_handler"
27
27
  });
28
28
  }
@@ -53,8 +53,6 @@ function wrapSentryHandleRequest(originalHandle) {
53
53
  }
54
54
  };
55
55
  }
56
- const sentryHandleRequest = wrapSentryHandleRequest;
57
56
 
58
- exports.sentryHandleRequest = sentryHandleRequest;
59
57
  exports.wrapSentryHandleRequest = wrapSentryHandleRequest;
60
58
  //# sourceMappingURL=wrapSentryHandleRequest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { HTTP_ROUTE } from '@sentry/conventions/attributes';\nimport {\n flushIfServerless,\n getActiveSpan,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n updateSpanName,\n} from '@sentry/core';\nimport type { AppLoadContext, EntryContext, RouterContextProvider } from 'react-router';\nimport { isInstrumentationApiUsed } from './serverGlobals';\n\ntype OriginalHandleRequestWithoutMiddleware = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown>;\n\ntype OriginalHandleRequestWithMiddleware = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: RouterContextProvider,\n) => Promise<unknown>;\n\n/**\n * Wraps the original handleRequest function to add Sentry instrumentation.\n *\n * @param originalHandle - The original handleRequest function to wrap\n * @returns A wrapped version of the handle request function with Sentry instrumentation\n */\nexport function wrapSentryHandleRequest(\n originalHandle: OriginalHandleRequestWithoutMiddleware,\n): OriginalHandleRequestWithoutMiddleware;\n/**\n * Wraps the original handleRequest function to add Sentry instrumentation.\n *\n * @param originalHandle - The original handleRequest function to wrap\n * @returns A wrapped version of the handle request function with Sentry instrumentation\n */\nexport function wrapSentryHandleRequest(\n originalHandle: OriginalHandleRequestWithMiddleware,\n): OriginalHandleRequestWithMiddleware;\n/**\n * Wraps the original handleRequest function to add Sentry instrumentation.\n *\n * @param originalHandle - The original handleRequest function to wrap\n * @returns A wrapped version of the handle request function with Sentry instrumentation\n */\nexport function wrapSentryHandleRequest(\n originalHandle: OriginalHandleRequestWithoutMiddleware | OriginalHandleRequestWithMiddleware,\n): OriginalHandleRequestWithoutMiddleware | OriginalHandleRequestWithMiddleware {\n return async function sentryInstrumentedHandleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext | RouterContextProvider,\n ) {\n const parameterizedPath =\n routerContext?.staticHandlerContext?.matches?.[routerContext.staticHandlerContext.matches.length - 1]?.route.path;\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n if (parameterizedPath && rootSpan) {\n // Normalize route name - avoid \"//\" for root routes\n const routeName = parameterizedPath.startsWith('/') ? parameterizedPath : `/${parameterizedPath}`;\n\n const transactionName = `${request.method} ${routeName}`;\n\n updateSpanName(rootSpan, transactionName);\n getCurrentScope().setTransactionName(transactionName);\n\n // Set route attributes - acts as fallback for lazy-only routes when using instrumentation API\n // Don't override origin when instrumentation API is used (preserve instrumentation_api origin)\n if (isInstrumentationApiUsed()) {\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n });\n } else {\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.request_handler',\n });\n }\n }\n\n try {\n // Type guard to call the correct overload based on loadContext type\n if (isRouterContextProvider(loadContext)) {\n // loadContext is RouterContextProvider\n return await (originalHandle as OriginalHandleRequestWithMiddleware)(\n request,\n responseStatusCode,\n responseHeaders,\n routerContext,\n loadContext,\n );\n } else {\n // loadContext is AppLoadContext\n return await (originalHandle as OriginalHandleRequestWithoutMiddleware)(\n request,\n responseStatusCode,\n responseHeaders,\n routerContext,\n loadContext,\n );\n }\n } finally {\n await flushIfServerless();\n }\n\n /**\n * Helper type guard to determine if the context is a RouterContextProvider.\n *\n * @param ctx - The context to check\n * @returns True if the context is a RouterContextProvider\n */\n function isRouterContextProvider(ctx: AppLoadContext | RouterContextProvider): ctx is RouterContextProvider {\n return typeof (ctx as RouterContextProvider)?.get === 'function';\n }\n };\n}\n\n// todo(v11): remove this\n/** @deprecated Use `wrapSentryHandleRequest` instead. */\nexport const sentryHandleRequest = wrapSentryHandleRequest;\n"],"names":["getActiveSpan","getRootSpan","updateSpanName","getCurrentScope","isInstrumentationApiUsed","HTTP_ROUTE","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","flushIfServerless"],"mappings":";;;;;;AAqDO,SAAS,wBACd,cAAA,EAC8E;AAC9E,EAAA,OAAO,eAAe,+BAAA,CACpB,OAAA,EACA,kBAAA,EACA,eAAA,EACA,eACA,WAAA,EACA;AACA,IAAA,MAAM,iBAAA,GACJ,aAAA,EAAe,oBAAA,EAAsB,OAAA,GAAU,aAAA,CAAc,qBAAqB,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA,EAAG,KAAA,CAAM,IAAA;AAE/G,IAAA,MAAM,aAAaA,kBAAA,EAAc;AACjC,IAAA,MAAM,QAAA,GAAW,UAAA,GAAaC,gBAAA,CAAY,UAAU,CAAA,GAAI,MAAA;AAExD,IAAA,IAAI,qBAAqB,QAAA,EAAU;AAEjC,MAAA,MAAM,YAAY,iBAAA,CAAkB,UAAA,CAAW,GAAG,CAAA,GAAI,iBAAA,GAAoB,IAAI,iBAAiB,CAAA,CAAA;AAE/F,MAAA,MAAM,eAAA,GAAkB,CAAA,EAAG,OAAA,CAAQ,MAAM,IAAI,SAAS,CAAA,CAAA;AAEtD,MAAAC,mBAAA,CAAe,UAAU,eAAe,CAAA;AACxC,MAAAC,oBAAA,EAAgB,CAAE,mBAAmB,eAAe,CAAA;AAIpD,MAAA,IAAIC,wCAAyB,EAAG;AAC9B,QAAA,QAAA,CAAS,aAAA,CAAc;AAAA,UACrB,CAACC,qBAAU,GAAG,SAAA;AAAA,UACd,CAACC,qCAAgC,GAAG;AAAA,SACrC,CAAA;AAAA,MACH,CAAA,MAAO;AACL,QAAA,QAAA,CAAS,aAAA,CAAc;AAAA,UACrB,CAACD,qBAAU,GAAG,SAAA;AAAA,UACd,CAACC,qCAAgC,GAAG,OAAA;AAAA,UACpC,CAACC,qCAAgC,GAAG;AAAA,SACrC,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,IAAI;AAEF,MAAA,IAAI,uBAAA,CAAwB,WAAW,CAAA,EAAG;AAExC,QAAA,OAAO,MAAO,cAAA;AAAA,UACZ,OAAA;AAAA,UACA,kBAAA;AAAA,UACA,eAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,OAAO,MAAO,cAAA;AAAA,UACZ,OAAA;AAAA,UACA,kBAAA;AAAA,UACA,eAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF;AAAA,IACF,CAAA,SAAE;AACA,MAAA,MAAMC,sBAAA,EAAkB;AAAA,IAC1B;AAQA,IAAA,SAAS,wBAAwB,GAAA,EAA2E;AAC1G,MAAA,OAAO,OAAQ,KAA+B,GAAA,KAAQ,UAAA;AAAA,IACxD;AAAA,EACF,CAAA;AACF;AAIO,MAAM,mBAAA,GAAsB;;;;;"}
1
+ {"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { SENTRY_SEGMENT_NAME_SOURCE, HTTP_ROUTE } from '@sentry/conventions/attributes';\nimport {\n flushIfServerless,\n getActiveSpan,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n updateSpanName,\n} from '@sentry/core';\nimport type { AppLoadContext, EntryContext, RouterContextProvider } from 'react-router';\nimport { isInstrumentationApiUsed } from './serverGlobals';\n\ntype OriginalHandleRequestWithoutMiddleware = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown>;\n\ntype OriginalHandleRequestWithMiddleware = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: RouterContextProvider,\n) => Promise<unknown>;\n\n/**\n * Wraps the original handleRequest function to add Sentry instrumentation.\n *\n * @param originalHandle - The original handleRequest function to wrap\n * @returns A wrapped version of the handle request function with Sentry instrumentation\n */\nexport function wrapSentryHandleRequest(\n originalHandle: OriginalHandleRequestWithoutMiddleware,\n): OriginalHandleRequestWithoutMiddleware;\n/**\n * Wraps the original handleRequest function to add Sentry instrumentation.\n *\n * @param originalHandle - The original handleRequest function to wrap\n * @returns A wrapped version of the handle request function with Sentry instrumentation\n */\nexport function wrapSentryHandleRequest(\n originalHandle: OriginalHandleRequestWithMiddleware,\n): OriginalHandleRequestWithMiddleware;\n/**\n * Wraps the original handleRequest function to add Sentry instrumentation.\n *\n * @param originalHandle - The original handleRequest function to wrap\n * @returns A wrapped version of the handle request function with Sentry instrumentation\n */\nexport function wrapSentryHandleRequest(\n originalHandle: OriginalHandleRequestWithoutMiddleware | OriginalHandleRequestWithMiddleware,\n): OriginalHandleRequestWithoutMiddleware | OriginalHandleRequestWithMiddleware {\n return async function sentryInstrumentedHandleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext | RouterContextProvider,\n ) {\n const parameterizedPath =\n routerContext?.staticHandlerContext?.matches?.[routerContext.staticHandlerContext.matches.length - 1]?.route.path;\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n if (parameterizedPath && rootSpan) {\n // Normalize route name - avoid \"//\" for root routes\n const routeName = parameterizedPath.startsWith('/') ? parameterizedPath : `/${parameterizedPath}`;\n\n const transactionName = `${request.method} ${routeName}`;\n\n updateSpanName(rootSpan, transactionName);\n getCurrentScope().setTransactionName(transactionName);\n\n // Set route attributes - acts as fallback for lazy-only routes when using instrumentation API\n // Don't override origin when instrumentation API is used (preserve instrumentation_api origin)\n if (isInstrumentationApiUsed()) {\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SENTRY_SEGMENT_NAME_SOURCE]: 'route',\n });\n } else {\n rootSpan.setAttributes({\n [HTTP_ROUTE]: routeName,\n [SENTRY_SEGMENT_NAME_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react_router.request_handler',\n });\n }\n }\n\n try {\n // Type guard to call the correct overload based on loadContext type\n if (isRouterContextProvider(loadContext)) {\n // loadContext is RouterContextProvider\n return await (originalHandle as OriginalHandleRequestWithMiddleware)(\n request,\n responseStatusCode,\n responseHeaders,\n routerContext,\n loadContext,\n );\n } else {\n // loadContext is AppLoadContext\n return await (originalHandle as OriginalHandleRequestWithoutMiddleware)(\n request,\n responseStatusCode,\n responseHeaders,\n routerContext,\n loadContext,\n );\n }\n } finally {\n await flushIfServerless();\n }\n\n /**\n * Helper type guard to determine if the context is a RouterContextProvider.\n *\n * @param ctx - The context to check\n * @returns True if the context is a RouterContextProvider\n */\n function isRouterContextProvider(ctx: AppLoadContext | RouterContextProvider): ctx is RouterContextProvider {\n return typeof (ctx as RouterContextProvider)?.get === 'function';\n }\n };\n}\n"],"names":["getActiveSpan","getRootSpan","updateSpanName","getCurrentScope","isInstrumentationApiUsed","HTTP_ROUTE","SENTRY_SEGMENT_NAME_SOURCE","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","flushIfServerless"],"mappings":";;;;;;AAoDO,SAAS,wBACd,cAAA,EAC8E;AAC9E,EAAA,OAAO,eAAe,+BAAA,CACpB,OAAA,EACA,kBAAA,EACA,eAAA,EACA,eACA,WAAA,EACA;AACA,IAAA,MAAM,iBAAA,GACJ,aAAA,EAAe,oBAAA,EAAsB,OAAA,GAAU,aAAA,CAAc,qBAAqB,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA,EAAG,KAAA,CAAM,IAAA;AAE/G,IAAA,MAAM,aAAaA,kBAAA,EAAc;AACjC,IAAA,MAAM,QAAA,GAAW,UAAA,GAAaC,gBAAA,CAAY,UAAU,CAAA,GAAI,MAAA;AAExD,IAAA,IAAI,qBAAqB,QAAA,EAAU;AAEjC,MAAA,MAAM,YAAY,iBAAA,CAAkB,UAAA,CAAW,GAAG,CAAA,GAAI,iBAAA,GAAoB,IAAI,iBAAiB,CAAA,CAAA;AAE/F,MAAA,MAAM,eAAA,GAAkB,CAAA,EAAG,OAAA,CAAQ,MAAM,IAAI,SAAS,CAAA,CAAA;AAEtD,MAAAC,mBAAA,CAAe,UAAU,eAAe,CAAA;AACxC,MAAAC,oBAAA,EAAgB,CAAE,mBAAmB,eAAe,CAAA;AAIpD,MAAA,IAAIC,wCAAyB,EAAG;AAC9B,QAAA,QAAA,CAAS,aAAA,CAAc;AAAA,UACrB,CAACC,qBAAU,GAAG,SAAA;AAAA,UACd,CAACC,qCAA0B,GAAG;AAAA,SAC/B,CAAA;AAAA,MACH,CAAA,MAAO;AACL,QAAA,QAAA,CAAS,aAAA,CAAc;AAAA,UACrB,CAACD,qBAAU,GAAG,SAAA;AAAA,UACd,CAACC,qCAA0B,GAAG,OAAA;AAAA,UAC9B,CAACC,qCAAgC,GAAG;AAAA,SACrC,CAAA;AAAA,MACH;AAAA,IACF;AAEA,IAAA,IAAI;AAEF,MAAA,IAAI,uBAAA,CAAwB,WAAW,CAAA,EAAG;AAExC,QAAA,OAAO,MAAO,cAAA;AAAA,UACZ,OAAA;AAAA,UACA,kBAAA;AAAA,UACA,eAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,OAAO,MAAO,cAAA;AAAA,UACZ,OAAA;AAAA,UACA,kBAAA;AAAA,UACA,eAAA;AAAA,UACA,aAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF;AAAA,IACF,CAAA,SAAE;AACA,MAAA,MAAMC,sBAAA,EAAkB;AAAA,IAC1B;AAQA,IAAA,SAAS,wBAAwB,GAAA,EAA2E;AAC1G,MAAA,OAAO,OAAQ,KAA+B,GAAA,KAAQ,UAAA;AAAA,IACxD;AAAA,EACF,CAAA;AACF;;;;"}
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const promises = require('node:fs/promises');
4
- const SentryCli = require('@sentry/cli');
4
+ const sentry = require('sentry');
5
5
  const glob = require('glob');
6
6
 
7
7
  function getSentryConfig(viteConfig) {
@@ -10,53 +10,38 @@ function getSentryConfig(viteConfig) {
10
10
  }
11
11
  return viteConfig.sentryConfig;
12
12
  }
13
- function resolveSourceMapsDisable(sentryConfig) {
14
- if (sentryConfig.sourceMapsUploadOptions?.enabled === false) {
15
- return true;
16
- }
17
- return sentryConfig.sourcemaps?.disable ?? sentryConfig.unstable_sentryVitePluginOptions?.sourcemaps?.disable;
18
- }
19
13
  const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
20
14
  const sentryConfig = getSentryConfig(viteConfig);
21
- const {
22
- sourceMapsUploadOptions,
23
- // extract to exclude from rest config
24
- ...sentryConfigWithoutDeprecatedSourceMapOption
25
- } = sentryConfig;
26
- const unstableSentryVitePluginOptions = sentryConfig.unstable_sentryVitePluginOptions;
27
15
  const {
28
16
  authToken,
17
+ headers,
29
18
  org,
30
19
  project,
31
20
  release,
21
+ sentryUrl,
32
22
  sourcemaps = { disable: false },
33
23
  debug = false
34
24
  } = {
35
- ...unstableSentryVitePluginOptions,
36
- ...sentryConfigWithoutDeprecatedSourceMapOption,
37
- // spread in the config without the deprecated sourceMapsUploadOptions
25
+ ...sentryConfig,
38
26
  sourcemaps: {
39
- ...unstableSentryVitePluginOptions?.sourcemaps,
40
27
  ...sentryConfig.sourcemaps,
41
- ...sourceMapsUploadOptions,
42
- disable: resolveSourceMapsDisable(sentryConfig)
28
+ disable: sentryConfig.sourcemaps?.disable
43
29
  },
44
30
  release: {
45
- ...unstableSentryVitePluginOptions?.release,
46
31
  ...sentryConfig.release
47
- },
48
- project: unstableSentryVitePluginOptions?.project ? Array.isArray(unstableSentryVitePluginOptions?.project) ? unstableSentryVitePluginOptions?.project[0] : unstableSentryVitePluginOptions?.project : sentryConfigWithoutDeprecatedSourceMapOption.project
32
+ }
49
33
  };
50
- const cliInstance = new SentryCli.default(null, {
51
- authToken,
34
+ const sentryOptions = {
35
+ token: authToken,
52
36
  org,
53
- ...sentryConfig.unstable_sentryVitePluginOptions,
54
- // same handling as in bundler plugins: https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/05084f214c763a05137d863ff5a05ef38254f68d/packages/bundler-plugin-core/src/build-plugin-manager.ts#L102-L103
55
- project: Array.isArray(project) ? project[0] : project
56
- });
37
+ url: sentryUrl,
38
+ project,
39
+ headers
40
+ };
41
+ const sentry$1 = sentry.createSentrySDK(sentryOptions);
57
42
  if (release?.name) {
58
43
  try {
59
- await cliInstance.releases.new(release.name);
44
+ await sentry$1.release.create({ orgVersion: release.name });
60
45
  } catch (error) {
61
46
  console.error("[Sentry] Could not create release", error);
62
47
  }
@@ -65,22 +50,15 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
65
50
  const uploadDisabled = sourceMapsFullyDisabled || sourcemaps?.disable === "disable-upload";
66
51
  if (!sourceMapsFullyDisabled && viteConfig.build.sourcemap !== false) {
67
52
  try {
68
- await cliInstance.execute(
69
- ["sourcemaps", "inject", reactRouterConfig.buildDirectory],
70
- debug ? "rejectOnError" : false
71
- );
53
+ await sentry$1.sourcemap.inject({ directory: reactRouterConfig.buildDirectory });
72
54
  } catch (error) {
73
55
  console.error("[Sentry] Could not inject debug ids", error);
74
56
  }
75
57
  if (!uploadDisabled) {
76
58
  try {
77
- await cliInstance.releases.uploadSourceMaps(release?.name || "undefined", {
78
- include: [
79
- {
80
- paths: [reactRouterConfig.buildDirectory]
81
- }
82
- ],
83
- live: "rejectOnError"
59
+ await sentry$1.sourcemap.upload({
60
+ directory: reactRouterConfig.buildDirectory,
61
+ release: release?.name || "undefined"
84
62
  });
85
63
  } catch (error) {
86
64
  console.error("[Sentry] Could not upload sourcemaps", error);
@@ -95,7 +73,7 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
95
73
  updatedFilesToDeleteAfterUpload = [`${reactRouterConfig.buildDirectory}/**/*.map`];
96
74
  debug && // eslint-disable-next-line no-console
97
75
  console.info(
98
- `[Sentry] Automatically setting \`sourceMapsUploadOptions.filesToDeleteAfterUpload: ${JSON.stringify(
76
+ `[Sentry] Automatically setting \`sourcemaps.filesToDeleteAfterUpload: ${JSON.stringify(
99
77
  updatedFilesToDeleteAfterUpload
100
78
  )}\` to delete generated source maps after they were uploaded to Sentry.`
101
79
  );
@@ -1 +1 @@
1
- {"version":3,"file":"handleOnBuildEnd.js","sources":["../../../../src/vite/buildEnd/handleOnBuildEnd.ts"],"sourcesContent":["import { rm } from 'node:fs/promises';\nimport type { Config } from '@react-router/dev/config';\nimport SentryCli from '@sentry/cli';\nimport type { SentryVitePluginOptions } from '@sentry/bundler-plugins/vite';\nimport { glob } from 'glob';\nimport type { SentryReactRouterBuildOptions } from '../types';\n\ntype BuildEndHook = NonNullable<Config['buildEnd']>;\n\nfunction getSentryConfig(viteConfig: unknown): SentryReactRouterBuildOptions {\n if (!viteConfig || typeof viteConfig !== 'object' || !('sentryConfig' in viteConfig)) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] sentryConfig not found - it needs to be passed to vite.config.ts');\n }\n\n return (viteConfig as { sentryConfig: SentryReactRouterBuildOptions }).sentryConfig;\n}\n\n/**\n * This hook is the only place that injects debug IDs and uploads source maps for React\n * Router, so `disable` has to be honoured wherever the user set it. Reading it from the\n * top-level config only would silently ignore `unstable_sentryVitePluginOptions`.\n */\nfunction resolveSourceMapsDisable(sentryConfig: SentryReactRouterBuildOptions): boolean | 'disable-upload' | undefined {\n // eslint-disable-next-line typescript/no-deprecated\n if (sentryConfig.sourceMapsUploadOptions?.enabled === false) {\n return true;\n }\n\n return sentryConfig.sourcemaps?.disable ?? sentryConfig.unstable_sentryVitePluginOptions?.sourcemaps?.disable;\n}\n\n/**\n * A build end hook that handles Sentry release creation and source map uploads.\n * It creates a new Sentry release if configured, uploads source maps to Sentry,\n * and optionally deletes the source map files after upload.\n */\nexport const sentryOnBuildEnd: BuildEndHook = async ({ reactRouterConfig, viteConfig }) => {\n const sentryConfig = getSentryConfig(viteConfig);\n\n // todo(v11): Remove deprecated sourceMapsUploadOptions support (no need for spread/pick anymore)\n const {\n sourceMapsUploadOptions, // extract to exclude from rest config\n ...sentryConfigWithoutDeprecatedSourceMapOption\n } = sentryConfig;\n\n const unstableSentryVitePluginOptions = sentryConfig.unstable_sentryVitePluginOptions;\n\n const {\n authToken,\n org,\n project,\n release,\n sourcemaps = { disable: false },\n debug = false,\n }: Omit<SentryReactRouterBuildOptions, 'sourcemaps' | 'sourceMapsUploadOptions'> &\n // Pick 'sourcemaps' from Vite plugin options as the types allow more (e.g. Promise values for `deleteFilesAfterUpload`)\n Pick<SentryVitePluginOptions, 'sourcemaps'> = {\n ...unstableSentryVitePluginOptions,\n ...sentryConfigWithoutDeprecatedSourceMapOption, // spread in the config without the deprecated sourceMapsUploadOptions\n sourcemaps: {\n ...unstableSentryVitePluginOptions?.sourcemaps,\n ...sentryConfig.sourcemaps,\n ...sourceMapsUploadOptions,\n disable: resolveSourceMapsDisable(sentryConfig),\n },\n release: {\n ...unstableSentryVitePluginOptions?.release,\n ...sentryConfig.release,\n },\n project: unstableSentryVitePluginOptions?.project\n ? Array.isArray(unstableSentryVitePluginOptions?.project)\n ? unstableSentryVitePluginOptions?.project[0]\n : unstableSentryVitePluginOptions?.project\n : sentryConfigWithoutDeprecatedSourceMapOption.project,\n };\n\n const cliInstance = new SentryCli(null, {\n authToken,\n org,\n ...sentryConfig.unstable_sentryVitePluginOptions,\n // same handling as in bundler plugins: https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/05084f214c763a05137d863ff5a05ef38254f68d/packages/bundler-plugin-core/src/build-plugin-manager.ts#L102-L103\n project: Array.isArray(project) ? project[0] : project,\n });\n\n // check if release should be created\n if (release?.name) {\n try {\n await cliInstance.releases.new(release.name);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not create release', error);\n }\n }\n\n // `disable: 'disable-upload'` still injects debug IDs, so that source maps can be\n // uploaded manually at a later point - only `true` turns source maps off entirely.\n const sourceMapsFullyDisabled = sourcemaps?.disable === true;\n const uploadDisabled = sourceMapsFullyDisabled || sourcemaps?.disable === 'disable-upload';\n\n if (!sourceMapsFullyDisabled && viteConfig.build.sourcemap !== false) {\n // inject debugIds\n try {\n await cliInstance.execute(\n ['sourcemaps', 'inject', reactRouterConfig.buildDirectory],\n debug ? 'rejectOnError' : false,\n );\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not inject debug ids', error);\n }\n\n if (!uploadDisabled) {\n // upload sourcemaps\n try {\n await cliInstance.releases.uploadSourceMaps(release?.name || 'undefined', {\n include: [\n {\n paths: [reactRouterConfig.buildDirectory],\n },\n ],\n live: 'rejectOnError',\n });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not upload sourcemaps', error);\n }\n }\n }\n\n // Only clean up source maps that were actually uploaded. Deleting them after skipping\n // the upload would leave the user with neither, breaking a manual upload.\n if (uploadDisabled) {\n return;\n }\n\n // delete sourcemaps after upload\n let updatedFilesToDeleteAfterUpload = await sourcemaps?.filesToDeleteAfterUpload;\n\n // set a default value no option was set\n if (typeof updatedFilesToDeleteAfterUpload === 'undefined') {\n updatedFilesToDeleteAfterUpload = [`${reactRouterConfig.buildDirectory}/**/*.map`];\n debug &&\n // eslint-disable-next-line no-console\n console.info(\n `[Sentry] Automatically setting \\`sourceMapsUploadOptions.filesToDeleteAfterUpload: ${JSON.stringify(\n updatedFilesToDeleteAfterUpload,\n )}\\` to delete generated source maps after they were uploaded to Sentry.`,\n );\n }\n if (updatedFilesToDeleteAfterUpload) {\n try {\n const filePathsToDelete = await glob(updatedFilesToDeleteAfterUpload, {\n absolute: true,\n nodir: true,\n });\n if (debug) {\n filePathsToDelete.forEach(filePathToDelete => {\n // eslint-disable-next-line no-console\n console.info(`Deleting asset after upload: ${filePathToDelete}`);\n });\n }\n await Promise.all(\n filePathsToDelete.map(filePathToDelete =>\n rm(filePathToDelete, { force: true }).catch((e: unknown) => {\n // This is allowed to fail - we just don't do anything\n debug &&\n // eslint-disable-next-line no-console\n console.debug(`An error occurred while attempting to delete asset: ${filePathToDelete}`, e);\n }),\n ),\n );\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error deleting files after sourcemap upload:', error);\n }\n }\n};\n"],"names":["SentryCli","glob","rm"],"mappings":"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"}
1
+ {"version":3,"file":"handleOnBuildEnd.js","sources":["../../../../src/vite/buildEnd/handleOnBuildEnd.ts"],"sourcesContent":["import { rm } from 'node:fs/promises';\nimport type { Config } from '@react-router/dev/config';\nimport { createSentrySDK } from 'sentry';\nimport type { SentryVitePluginOptions } from '@sentry/bundler-plugins/vite';\nimport { glob } from 'glob';\nimport type { SentryReactRouterBuildOptions } from '../types';\n\ntype BuildEndHook = NonNullable<Config['buildEnd']>;\ntype SentryOptions = NonNullable<Parameters<typeof createSentrySDK>[0]>;\n\n/**\n * The CLI accepts `headers` since 0.44.0, but its bundled type declarations do not list the\n * option yet.\n * TODO: Drop once `SentryOptions` in the `sentry` package declares `headers`: https://github.com/getsentry/cli/pull/1500\n */\ntype SentryOptionsWithHeaders = SentryOptions & { headers?: Record<string, string> };\n\nfunction getSentryConfig(viteConfig: unknown): SentryReactRouterBuildOptions {\n if (!viteConfig || typeof viteConfig !== 'object' || !('sentryConfig' in viteConfig)) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] sentryConfig not found - it needs to be passed to vite.config.ts');\n }\n\n return (viteConfig as { sentryConfig: SentryReactRouterBuildOptions }).sentryConfig;\n}\n\n/**\n * A build end hook that handles Sentry release creation and source map uploads.\n * It creates a new Sentry release if configured, uploads source maps to Sentry,\n * and optionally deletes the source map files after upload.\n */\nexport const sentryOnBuildEnd: BuildEndHook = async ({ reactRouterConfig, viteConfig }) => {\n const sentryConfig = getSentryConfig(viteConfig);\n\n const {\n authToken,\n headers,\n org,\n project,\n release,\n sentryUrl,\n sourcemaps = { disable: false },\n debug = false,\n }: Omit<SentryReactRouterBuildOptions, 'sourcemaps'> &\n // Pick 'sourcemaps' from Vite plugin options as the types allow more (e.g. Promise values for `deleteFilesAfterUpload`)\n Pick<SentryVitePluginOptions, 'sourcemaps'> = {\n ...sentryConfig,\n sourcemaps: {\n ...sentryConfig.sourcemaps,\n disable: sentryConfig.sourcemaps?.disable,\n },\n release: {\n ...sentryConfig.release,\n },\n };\n\n const sentryOptions: SentryOptionsWithHeaders = {\n token: authToken,\n org,\n url: sentryUrl,\n project,\n headers,\n };\n\n const sentry = createSentrySDK(sentryOptions);\n\n // check if release should be created\n if (release?.name) {\n try {\n await sentry.release.create({ orgVersion: release.name });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not create release', error);\n }\n }\n\n // `disable: 'disable-upload'` still injects debug IDs, so that source maps can be\n // uploaded manually at a later point - only `true` turns source maps off entirely.\n const sourceMapsFullyDisabled = sourcemaps?.disable === true;\n const uploadDisabled = sourceMapsFullyDisabled || sourcemaps?.disable === 'disable-upload';\n\n if (!sourceMapsFullyDisabled && viteConfig.build.sourcemap !== false) {\n // inject debugIds\n try {\n await sentry.sourcemap.inject({ directory: reactRouterConfig.buildDirectory });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not inject debug ids', error);\n }\n\n if (!uploadDisabled) {\n // upload sourcemaps\n try {\n await sentry.sourcemap.upload({\n directory: reactRouterConfig.buildDirectory,\n release: release?.name || 'undefined',\n });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not upload sourcemaps', error);\n }\n }\n }\n\n // Only clean up source maps that were actually uploaded. Deleting them after skipping\n // the upload would leave the user with neither, breaking a manual upload.\n if (uploadDisabled) {\n return;\n }\n\n // delete sourcemaps after upload\n let updatedFilesToDeleteAfterUpload = await sourcemaps?.filesToDeleteAfterUpload;\n\n // set a default value no option was set\n if (typeof updatedFilesToDeleteAfterUpload === 'undefined') {\n updatedFilesToDeleteAfterUpload = [`${reactRouterConfig.buildDirectory}/**/*.map`];\n debug &&\n // eslint-disable-next-line no-console\n console.info(\n `[Sentry] Automatically setting \\`sourcemaps.filesToDeleteAfterUpload: ${JSON.stringify(\n updatedFilesToDeleteAfterUpload,\n )}\\` to delete generated source maps after they were uploaded to Sentry.`,\n );\n }\n if (updatedFilesToDeleteAfterUpload) {\n try {\n const filePathsToDelete = await glob(updatedFilesToDeleteAfterUpload, {\n absolute: true,\n nodir: true,\n });\n if (debug) {\n filePathsToDelete.forEach(filePathToDelete => {\n // eslint-disable-next-line no-console\n console.info(`Deleting asset after upload: ${filePathToDelete}`);\n });\n }\n await Promise.all(\n filePathsToDelete.map(filePathToDelete =>\n rm(filePathToDelete, { force: true }).catch((e: unknown) => {\n // This is allowed to fail - we just don't do anything\n debug &&\n // eslint-disable-next-line no-console\n console.debug(`An error occurred while attempting to delete asset: ${filePathToDelete}`, e);\n }),\n ),\n );\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('Error deleting files after sourcemap upload:', error);\n }\n }\n};\n"],"names":["sentry","createSentrySDK","glob","rm"],"mappings":"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"}