@sentry/react-router 10.1.0 → 10.3.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.
Files changed (41) hide show
  1. package/build/cjs/cloudflare/index.js +67 -0
  2. package/build/cjs/cloudflare/index.js.map +1 -0
  3. package/build/cjs/index.server.js +2 -1
  4. package/build/cjs/index.server.js.map +1 -1
  5. package/build/cjs/server/createSentryHandleRequest.js +2 -1
  6. package/build/cjs/server/createSentryHandleRequest.js.map +1 -1
  7. package/build/cjs/server/getMetaTagTransformer.js +30 -0
  8. package/build/cjs/server/getMetaTagTransformer.js.map +1 -0
  9. package/build/cjs/server/wrapSentryHandleRequest.js +0 -25
  10. package/build/cjs/server/wrapSentryHandleRequest.js.map +1 -1
  11. package/build/cjs/vite/buildEnd/handleOnBuildEnd.js +8 -6
  12. package/build/cjs/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
  13. package/build/cjs/vite/makeEnableSourceMapsPlugin.js +14 -17
  14. package/build/cjs/vite/makeEnableSourceMapsPlugin.js.map +1 -1
  15. package/build/esm/cloudflare/index.js +45 -0
  16. package/build/esm/cloudflare/index.js.map +1 -0
  17. package/build/esm/index.server.js +2 -1
  18. package/build/esm/index.server.js.map +1 -1
  19. package/build/esm/package.json +1 -1
  20. package/build/esm/server/createSentryHandleRequest.js +2 -1
  21. package/build/esm/server/createSentryHandleRequest.js.map +1 -1
  22. package/build/esm/server/getMetaTagTransformer.js +28 -0
  23. package/build/esm/server/getMetaTagTransformer.js.map +1 -0
  24. package/build/esm/server/wrapSentryHandleRequest.js +2 -26
  25. package/build/esm/server/wrapSentryHandleRequest.js.map +1 -1
  26. package/build/esm/vite/buildEnd/handleOnBuildEnd.js +8 -6
  27. package/build/esm/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
  28. package/build/esm/vite/makeEnableSourceMapsPlugin.js +14 -17
  29. package/build/esm/vite/makeEnableSourceMapsPlugin.js.map +1 -1
  30. package/build/types/cloudflare/index.d.ts +10 -0
  31. package/build/types/cloudflare/index.d.ts.map +1 -0
  32. package/build/types/server/createSentryHandleRequest.d.ts.map +1 -1
  33. package/build/types/server/getMetaTagTransformer.d.ts +11 -0
  34. package/build/types/server/getMetaTagTransformer.d.ts.map +1 -0
  35. package/build/types/server/index.d.ts +2 -1
  36. package/build/types/server/index.d.ts.map +1 -1
  37. package/build/types/server/wrapSentryHandleRequest.d.ts +0 -10
  38. package/build/types/server/wrapSentryHandleRequest.d.ts.map +1 -1
  39. package/build/types/vite/buildEnd/handleOnBuildEnd.d.ts.map +1 -1
  40. package/build/types/vite/makeEnableSourceMapsPlugin.d.ts.map +1 -1
  41. package/package.json +17 -6
@@ -0,0 +1,67 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const browser = require('@sentry/browser');
5
+ const sdk = require('../client/sdk.js');
6
+ const tracingIntegration = require('../client/tracingIntegration.js');
7
+ const react = require('@sentry/react');
8
+ const wrapSentryHandleRequest = require('../server/wrapSentryHandleRequest.js');
9
+
10
+ /**
11
+ * Injects Sentry trace meta tags into the HTML response by transforming the ReadableStream.
12
+ * This enables distributed tracing by adding trace context to the HTML document head.
13
+ * @param body - ReadableStream containing the HTML response body to modify
14
+ * @returns A new ReadableStream with Sentry trace meta tags injected into the head section
15
+ */
16
+ function injectTraceMetaTags(body) {
17
+ const headClosingTag = '</head>';
18
+
19
+ const reader = body.getReader();
20
+ const stream = new ReadableStream({
21
+ async pull(controller) {
22
+ const { done, value } = await reader.read();
23
+
24
+ if (done) {
25
+ controller.close();
26
+ return;
27
+ }
28
+
29
+ const encoder = new TextEncoder();
30
+ const html = value instanceof Uint8Array ? new TextDecoder().decode(value) : String(value);
31
+
32
+ if (html.includes(headClosingTag)) {
33
+ const modifiedHtml = html.replace(headClosingTag, `${core.getTraceMetaTags()}${headClosingTag}`);
34
+
35
+ controller.enqueue(encoder.encode(modifiedHtml));
36
+ return;
37
+ }
38
+
39
+ controller.enqueue(encoder.encode(html));
40
+ },
41
+ });
42
+
43
+ return stream;
44
+ }
45
+
46
+ exports.init = sdk.init;
47
+ exports.reactRouterTracingIntegration = tracingIntegration.reactRouterTracingIntegration;
48
+ exports.ErrorBoundary = react.ErrorBoundary;
49
+ exports.Profiler = react.Profiler;
50
+ exports.captureReactException = react.captureReactException;
51
+ exports.reactErrorHandler = react.reactErrorHandler;
52
+ exports.useProfiler = react.useProfiler;
53
+ exports.withErrorBoundary = react.withErrorBoundary;
54
+ exports.withProfiler = react.withProfiler;
55
+ exports.wrapSentryHandleRequest = wrapSentryHandleRequest.wrapSentryHandleRequest;
56
+ exports.injectTraceMetaTags = injectTraceMetaTags;
57
+ Object.prototype.hasOwnProperty.call(browser, '__proto__') &&
58
+ !Object.prototype.hasOwnProperty.call(exports, '__proto__') &&
59
+ Object.defineProperty(exports, '__proto__', {
60
+ enumerable: true,
61
+ value: browser['__proto__']
62
+ });
63
+
64
+ Object.keys(browser).forEach(k => {
65
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = browser[k];
66
+ });
67
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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":";;;;;;;;;AAMA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,mBAAmB,CAAC,IAAI,EAAkC;AAC1E,EAAE,MAAM,cAAA,GAAiB,SAAS;;AAElC,EAAE,MAAM,MAAA,GAAS,IAAI,CAAC,SAAS,EAAE;AACjC,EAAE,MAAM,MAAA,GAAS,IAAI,cAAc,CAAC;AACpC,IAAI,MAAM,IAAI,CAAC,UAAU,EAAE;AAC3B,MAAM,MAAM,EAAE,IAAI,EAAE,KAAA,EAAM,GAAI,MAAM,MAAM,CAAC,IAAI,EAAE;;AAEjD,MAAM,IAAI,IAAI,EAAE;AAChB,QAAQ,UAAU,CAAC,KAAK,EAAE;AAC1B,QAAQ;AACR;;AAEA,MAAM,MAAM,OAAA,GAAU,IAAI,WAAW,EAAE;AACvC,MAAM,MAAM,OAAO,KAAA,YAAiB,UAAA,GAAa,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAA,GAAI,MAAM,CAAC,KAAK,CAAC;;AAEhG,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE;AACzC,QAAQ,MAAM,YAAA,GAAe,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,EAAAA,qBAAA,EAAA,CAAA,EAAA,cAAA,CAAA,CAAA,CAAA;;AAEA,QAAA,UAAA,CAAA,OAAA,CAAA,OAAA,CAAA,MAAA,CAAA,YAAA,CAAA,CAAA;AACA,QAAA;AACA;;AAEA,MAAA,UAAA,CAAA,OAAA,CAAA,OAAA,CAAA,MAAA,CAAA,IAAA,CAAA,CAAA;AACA,KAAA;AACA,GAAA,CAAA;;AAEA,EAAA,OAAA,MAAA;AACA;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -7,6 +7,7 @@ const createSentryHandleRequest = require('./server/createSentryHandleRequest.js
7
7
  const wrapServerAction = require('./server/wrapServerAction.js');
8
8
  const wrapServerLoader = require('./server/wrapServerLoader.js');
9
9
  const createSentryHandleError = require('./server/createSentryHandleError.js');
10
+ const getMetaTagTransformer = require('./server/getMetaTagTransformer.js');
10
11
  const plugin = require('./vite/plugin.js');
11
12
  const handleOnBuildEnd = require('./vite/buildEnd/handleOnBuildEnd.js');
12
13
  const makeConfigInjectorPlugin = require('./vite/makeConfigInjectorPlugin.js');
@@ -14,13 +15,13 @@ const makeConfigInjectorPlugin = require('./vite/makeConfigInjectorPlugin.js');
14
15
 
15
16
 
16
17
  exports.init = sdk.init;
17
- exports.getMetaTagTransformer = wrapSentryHandleRequest.getMetaTagTransformer;
18
18
  exports.sentryHandleRequest = wrapSentryHandleRequest.sentryHandleRequest;
19
19
  exports.wrapSentryHandleRequest = wrapSentryHandleRequest.wrapSentryHandleRequest;
20
20
  exports.createSentryHandleRequest = createSentryHandleRequest.createSentryHandleRequest;
21
21
  exports.wrapServerAction = wrapServerAction.wrapServerAction;
22
22
  exports.wrapServerLoader = wrapServerLoader.wrapServerLoader;
23
23
  exports.createSentryHandleError = createSentryHandleError.createSentryHandleError;
24
+ exports.getMetaTagTransformer = getMetaTagTransformer.getMetaTagTransformer;
24
25
  exports.sentryReactRouter = plugin.sentryReactRouter;
25
26
  exports.sentryOnBuildEnd = handleOnBuildEnd.sentryOnBuildEnd;
26
27
  exports.makeConfigInjectorPlugin = makeConfigInjectorPlugin.makeConfigInjectorPlugin;
@@ -1 +1 @@
1
- {"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -2,6 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  const React = require('react');
4
4
  const stream = require('stream');
5
+ const getMetaTagTransformer = require('./getMetaTagTransformer.js');
5
6
  const wrapSentryHandleRequest = require('./wrapSentryHandleRequest.js');
6
7
 
7
8
  /**
@@ -58,7 +59,7 @@ function createSentryHandleRequest(
58
59
  );
59
60
 
60
61
  // this injects trace data to the HTML head
61
- pipe(wrapSentryHandleRequest.getMetaTagTransformer(body));
62
+ pipe(getMetaTagTransformer.getMetaTagTransformer(body));
62
63
  },
63
64
  onShellError(error) {
64
65
  reject(error);
@@ -1 +1 @@
1
- {"version":3,"file":"createSentryHandleRequest.js","sources":["../../../src/server/createSentryHandleRequest.tsx"],"sourcesContent":["import type { createReadableStreamFromReadable } from '@react-router/node';\nimport type { ReactNode } from 'react';\nimport React from 'react';\nimport type { AppLoadContext, EntryContext, ServerRouter } from 'react-router';\nimport { PassThrough } from 'stream';\nimport { getMetaTagTransformer, wrapSentryHandleRequest } from './wrapSentryHandleRequest';\n\ntype RenderToPipeableStreamOptions = {\n [key: string]: unknown;\n onShellReady?: () => void;\n onAllReady?: () => void;\n onShellError?: (error: unknown) => void;\n onError?: (error: unknown) => void;\n};\n\ntype RenderToPipeableStreamResult = {\n pipe: (destination: NodeJS.WritableStream) => void;\n abort: () => void;\n};\n\ntype RenderToPipeableStreamFunction = (\n node: ReactNode,\n options: RenderToPipeableStreamOptions,\n) => RenderToPipeableStreamResult;\n\nexport interface SentryHandleRequestOptions {\n /**\n * Timeout in milliseconds after which the rendering stream will be aborted\n * @default 10000\n */\n streamTimeout?: number;\n\n /**\n * React's renderToPipeableStream function from 'react-dom/server'\n */\n renderToPipeableStream: RenderToPipeableStreamFunction;\n\n /**\n * The <ServerRouter /> component from '@react-router/server'\n */\n ServerRouter: typeof ServerRouter;\n\n /**\n * createReadableStreamFromReadable from '@react-router/node'\n */\n createReadableStreamFromReadable: typeof createReadableStreamFromReadable;\n\n /**\n * Regular expression to identify bot user agents\n * @default /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i\n */\n botRegex?: RegExp;\n}\n\n/**\n * A complete Sentry-instrumented handleRequest implementation that handles both\n * route parametrization and trace meta tag injection.\n *\n * @param options Configuration options\n * @returns A Sentry-instrumented handleRequest function\n */\nexport function createSentryHandleRequest(\n options: SentryHandleRequestOptions,\n): (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown> {\n const {\n streamTimeout = 10000,\n renderToPipeableStream,\n ServerRouter,\n createReadableStreamFromReadable,\n botRegex = /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i,\n } = options;\n\n const handleRequest = function handleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n _loadContext: AppLoadContext,\n ): Promise<Response> {\n return new Promise((resolve, reject) => {\n let shellRendered = false;\n const userAgent = request.headers.get('user-agent');\n\n // Determine if we should use onAllReady or onShellReady\n const isBot = typeof userAgent === 'string' && botRegex.test(userAgent);\n const isSpaMode = !!(routerContext as { isSpaMode?: boolean }).isSpaMode;\n\n const readyOption = isBot || isSpaMode ? 'onAllReady' : 'onShellReady';\n\n const { pipe, abort } = renderToPipeableStream(<ServerRouter context={routerContext} url={request.url} />, {\n [readyOption]() {\n shellRendered = true;\n const body = new PassThrough();\n\n const stream = createReadableStreamFromReadable(body);\n\n responseHeaders.set('Content-Type', 'text/html');\n\n resolve(\n new Response(stream, {\n headers: responseHeaders,\n status: responseStatusCode,\n }),\n );\n\n // this injects trace data to the HTML head\n pipe(getMetaTagTransformer(body));\n },\n onShellError(error: unknown) {\n reject(error);\n },\n onError(error: unknown) {\n // eslint-disable-next-line no-param-reassign\n responseStatusCode = 500;\n // Log streaming rendering errors from inside the shell. Don't log\n // errors encountered during initial shell rendering since they'll\n // reject and get logged in handleDocumentRequest.\n if (shellRendered) {\n // eslint-disable-next-line no-console\n console.error(error);\n }\n },\n });\n\n // Abort the rendering stream after the `streamTimeout`\n setTimeout(abort, streamTimeout);\n });\n };\n\n // Wrap the handle request function for request parametrization\n return wrapSentryHandleRequest(handleRequest);\n}\n"],"names":["React","PassThrough","stream","getMetaTagTransformer","wrapSentryHandleRequest"],"mappings":";;;;;;AAsDA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,yBAAyB;AACzC,EAAE,OAAO;AACT;;AAMA,CAAsB;AACtB,EAAE,MAAM;AACR,IAAI,aAAA,GAAgB,KAAK;AACzB,IAAI,sBAAsB;AAC1B,IAAI,YAAY;AAChB,IAAI,gCAAgC;AACpC,IAAI,QAAA,GAAW,oFAAoF;AACnG,GAAE,GAAI,OAAO;;AAEb,EAAE,MAAM,aAAA,GAAgB,SAAS,aAAa;AAC9C,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,YAAY;AAChB,IAAuB;AACvB,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK;AAC5C,MAAM,IAAI,aAAA,GAAgB,KAAK;AAC/B,MAAM,MAAM,SAAA,GAAY,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;;AAEzD;AACA,MAAM,MAAM,KAAA,GAAQ,OAAO,SAAA,KAAc,QAAA,IAAY,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;AAC7E,MAAM,MAAM,YAAY,CAAC,CAAC,CAAC,aAAA,GAA0C,SAAS;;AAE9E,MAAM,MAAM,cAAc,KAAA,IAAS,SAAA,GAAY,YAAA,GAAe,cAAc;;AAE5E,MAAM,MAAM,EAAE,IAAI,EAAE,OAAM,GAAI,sBAAsB,CAACA,aAAA,CAAA,aAAA,CAAC,YAAA,EAAA,EAAa,OAAO,EAAC,aAAc,EAAE,GAAG,EAAC,OAAQ,CAAC,GAAG,EAAA,EAAI,EAAE;AACjH,QAAQ,CAAC,WAAW,CAAC,GAAG;AACxB,UAAU,aAAA,GAAgB,IAAI;AAC9B,UAAU,MAAM,IAAA,GAAO,IAAIC,kBAAW,EAAE;;AAExC,UAAU,MAAMC,QAAA,GAAS,gCAAgC,CAAC,IAAI,CAAC;;AAE/D,UAAU,eAAe,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC;;AAE1D,UAAU,OAAO;AACjB,YAAY,IAAI,QAAQ,CAACA,QAAM,EAAE;AACjC,cAAc,OAAO,EAAE,eAAe;AACtC,cAAc,MAAM,EAAE,kBAAkB;AACxC,aAAa,CAAC;AACd,WAAW;;AAEX;AACA,UAAU,IAAI,CAACC,6CAAqB,CAAC,IAAI,CAAC,CAAC;AAC3C,SAAS;AACT,QAAQ,YAAY,CAAC,KAAK,EAAW;AACrC,UAAU,MAAM,CAAC,KAAK,CAAC;AACvB,SAAS;AACT,QAAQ,OAAO,CAAC,KAAK,EAAW;AAChC;AACA,UAAU,kBAAA,GAAqB,GAAG;AAClC;AACA;AACA;AACA,UAAU,IAAI,aAAa,EAAE;AAC7B;AACA,YAAY,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;AAChC;AACA,SAAS;AACT,OAAO,CAAC;;AAER;AACA,MAAM,UAAU,CAAC,KAAK,EAAE,aAAa,CAAC;AACtC,KAAK,CAAC;AACN,GAAG;;AAEH;AACA,EAAE,OAAOC,+CAAuB,CAAC,aAAa,CAAC;AAC/C;;;;"}
1
+ {"version":3,"file":"createSentryHandleRequest.js","sources":["../../../src/server/createSentryHandleRequest.tsx"],"sourcesContent":["import type { createReadableStreamFromReadable } from '@react-router/node';\nimport type { ReactNode } from 'react';\nimport React from 'react';\nimport type { AppLoadContext, EntryContext, ServerRouter } from 'react-router';\nimport { PassThrough } from 'stream';\nimport { getMetaTagTransformer } from './getMetaTagTransformer';\nimport { wrapSentryHandleRequest } from './wrapSentryHandleRequest';\n\ntype RenderToPipeableStreamOptions = {\n [key: string]: unknown;\n onShellReady?: () => void;\n onAllReady?: () => void;\n onShellError?: (error: unknown) => void;\n onError?: (error: unknown) => void;\n};\n\ntype RenderToPipeableStreamResult = {\n pipe: (destination: NodeJS.WritableStream) => void;\n abort: () => void;\n};\n\ntype RenderToPipeableStreamFunction = (\n node: ReactNode,\n options: RenderToPipeableStreamOptions,\n) => RenderToPipeableStreamResult;\n\nexport interface SentryHandleRequestOptions {\n /**\n * Timeout in milliseconds after which the rendering stream will be aborted\n * @default 10000\n */\n streamTimeout?: number;\n\n /**\n * React's renderToPipeableStream function from 'react-dom/server'\n */\n renderToPipeableStream: RenderToPipeableStreamFunction;\n\n /**\n * The <ServerRouter /> component from '@react-router/server'\n */\n ServerRouter: typeof ServerRouter;\n\n /**\n * createReadableStreamFromReadable from '@react-router/node'\n */\n createReadableStreamFromReadable: typeof createReadableStreamFromReadable;\n\n /**\n * Regular expression to identify bot user agents\n * @default /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i\n */\n botRegex?: RegExp;\n}\n\n/**\n * A complete Sentry-instrumented handleRequest implementation that handles both\n * route parametrization and trace meta tag injection.\n *\n * @param options Configuration options\n * @returns A Sentry-instrumented handleRequest function\n */\nexport function createSentryHandleRequest(\n options: SentryHandleRequestOptions,\n): (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown> {\n const {\n streamTimeout = 10000,\n renderToPipeableStream,\n ServerRouter,\n createReadableStreamFromReadable,\n botRegex = /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i,\n } = options;\n\n const handleRequest = function handleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n _loadContext: AppLoadContext,\n ): Promise<Response> {\n return new Promise((resolve, reject) => {\n let shellRendered = false;\n const userAgent = request.headers.get('user-agent');\n\n // Determine if we should use onAllReady or onShellReady\n const isBot = typeof userAgent === 'string' && botRegex.test(userAgent);\n const isSpaMode = !!(routerContext as { isSpaMode?: boolean }).isSpaMode;\n\n const readyOption = isBot || isSpaMode ? 'onAllReady' : 'onShellReady';\n\n const { pipe, abort } = renderToPipeableStream(<ServerRouter context={routerContext} url={request.url} />, {\n [readyOption]() {\n shellRendered = true;\n const body = new PassThrough();\n\n const stream = createReadableStreamFromReadable(body);\n\n responseHeaders.set('Content-Type', 'text/html');\n\n resolve(\n new Response(stream, {\n headers: responseHeaders,\n status: responseStatusCode,\n }),\n );\n\n // this injects trace data to the HTML head\n pipe(getMetaTagTransformer(body));\n },\n onShellError(error: unknown) {\n reject(error);\n },\n onError(error: unknown) {\n // eslint-disable-next-line no-param-reassign\n responseStatusCode = 500;\n // Log streaming rendering errors from inside the shell. Don't log\n // errors encountered during initial shell rendering since they'll\n // reject and get logged in handleDocumentRequest.\n if (shellRendered) {\n // eslint-disable-next-line no-console\n console.error(error);\n }\n },\n });\n\n // Abort the rendering stream after the `streamTimeout`\n setTimeout(abort, streamTimeout);\n });\n };\n\n // Wrap the handle request function for request parametrization\n return wrapSentryHandleRequest(handleRequest);\n}\n"],"names":["React","PassThrough","stream","getMetaTagTransformer","wrapSentryHandleRequest"],"mappings":";;;;;;;AAuDA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,yBAAyB;AACzC,EAAE,OAAO;AACT;;AAMA,CAAsB;AACtB,EAAE,MAAM;AACR,IAAI,aAAA,GAAgB,KAAK;AACzB,IAAI,sBAAsB;AAC1B,IAAI,YAAY;AAChB,IAAI,gCAAgC;AACpC,IAAI,QAAA,GAAW,oFAAoF;AACnG,GAAE,GAAI,OAAO;;AAEb,EAAE,MAAM,aAAA,GAAgB,SAAS,aAAa;AAC9C,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,YAAY;AAChB,IAAuB;AACvB,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK;AAC5C,MAAM,IAAI,aAAA,GAAgB,KAAK;AAC/B,MAAM,MAAM,SAAA,GAAY,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;;AAEzD;AACA,MAAM,MAAM,KAAA,GAAQ,OAAO,SAAA,KAAc,QAAA,IAAY,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;AAC7E,MAAM,MAAM,YAAY,CAAC,CAAC,CAAC,aAAA,GAA0C,SAAS;;AAE9E,MAAM,MAAM,cAAc,KAAA,IAAS,SAAA,GAAY,YAAA,GAAe,cAAc;;AAE5E,MAAM,MAAM,EAAE,IAAI,EAAE,OAAM,GAAI,sBAAsB,CAACA,aAAA,CAAA,aAAA,CAAC,YAAA,EAAA,EAAa,OAAO,EAAC,aAAc,EAAE,GAAG,EAAC,OAAQ,CAAC,GAAG,EAAA,EAAI,EAAE;AACjH,QAAQ,CAAC,WAAW,CAAC,GAAG;AACxB,UAAU,aAAA,GAAgB,IAAI;AAC9B,UAAU,MAAM,IAAA,GAAO,IAAIC,kBAAW,EAAE;;AAExC,UAAU,MAAMC,QAAA,GAAS,gCAAgC,CAAC,IAAI,CAAC;;AAE/D,UAAU,eAAe,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC;;AAE1D,UAAU,OAAO;AACjB,YAAY,IAAI,QAAQ,CAACA,QAAM,EAAE;AACjC,cAAc,OAAO,EAAE,eAAe;AACtC,cAAc,MAAM,EAAE,kBAAkB;AACxC,aAAa,CAAC;AACd,WAAW;;AAEX;AACA,UAAU,IAAI,CAACC,2CAAqB,CAAC,IAAI,CAAC,CAAC;AAC3C,SAAS;AACT,QAAQ,YAAY,CAAC,KAAK,EAAW;AACrC,UAAU,MAAM,CAAC,KAAK,CAAC;AACvB,SAAS;AACT,QAAQ,OAAO,CAAC,KAAK,EAAW;AAChC;AACA,UAAU,kBAAA,GAAqB,GAAG;AAClC;AACA;AACA;AACA,UAAU,IAAI,aAAa,EAAE;AAC7B;AACA,YAAY,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;AAChC;AACA,SAAS;AACT,OAAO,CAAC;;AAER;AACA,MAAM,UAAU,CAAC,KAAK,EAAE,aAAa,CAAC;AACtC,KAAK,CAAC;AACN,GAAG;;AAEH;AACA,EAAE,OAAOC,+CAAuB,CAAC,aAAa,CAAC;AAC/C;;;;"}
@@ -0,0 +1,30 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const node_stream = require('node:stream');
4
+ const core = require('@sentry/core');
5
+
6
+ /**
7
+ * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.
8
+ * This enables distributed tracing by adding trace context to the HTML document head.
9
+ *
10
+ * @param body - PassThrough stream containing the HTML response body to modify
11
+ */
12
+ function getMetaTagTransformer(body) {
13
+ const headClosingTag = '</head>';
14
+ const htmlMetaTagTransformer = new node_stream.Transform({
15
+ transform(chunk, _encoding, callback) {
16
+ const html = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);
17
+ if (html.includes(headClosingTag)) {
18
+ const modifiedHtml = html.replace(headClosingTag, `${core.getTraceMetaTags()}${headClosingTag}`);
19
+ callback(null, modifiedHtml);
20
+ return;
21
+ }
22
+ callback(null, chunk);
23
+ },
24
+ });
25
+ htmlMetaTagTransformer.pipe(body);
26
+ return htmlMetaTagTransformer;
27
+ }
28
+
29
+ exports.getMetaTagTransformer = getMetaTagTransformer;
30
+ //# sourceMappingURL=getMetaTagTransformer.js.map
@@ -0,0 +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":";;;;;AAIA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,qBAAqB,CAAC,IAAI,EAA0B;AACpE,EAAE,MAAM,cAAA,GAAiB,SAAS;AAClC,EAAE,MAAM,sBAAA,GAAyB,IAAIA,qBAAS,CAAC;AAC/C,IAAI,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE;AAC1C,MAAM,MAAM,IAAA,GAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAA,GAAI,KAAK,CAAC,QAAQ,EAAC,GAAI,MAAM,CAAC,KAAK,CAAC;AAC5E,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE;AACzC,QAAQ,MAAM,YAAA,GAAe,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,EAAAC,qBAAA,EAAA,CAAA,EAAA,cAAA,CAAA,CAAA,CAAA;AACA,QAAA,QAAA,CAAA,IAAA,EAAA,YAAA,CAAA;AACA,QAAA;AACA;AACA,MAAA,QAAA,CAAA,IAAA,EAAA,KAAA,CAAA;AACA,KAAA;AACA,GAAA,CAAA;AACA,EAAA,sBAAA,CAAA,IAAA,CAAA,IAAA,CAAA;AACA,EAAA,OAAA,sBAAA;AACA;;;;"}
@@ -4,7 +4,6 @@ const api = require('@opentelemetry/api');
4
4
  const core$1 = require('@opentelemetry/core');
5
5
  const semanticConventions = require('@opentelemetry/semantic-conventions');
6
6
  const core = require('@sentry/core');
7
- const stream = require('stream');
8
7
 
9
8
  /**
10
9
  * Wraps the original handleRequest function to add Sentry instrumentation.
@@ -56,30 +55,6 @@ function wrapSentryHandleRequest(originalHandle) {
56
55
  /** @deprecated Use `wrapSentryHandleRequest` instead. */
57
56
  const sentryHandleRequest = wrapSentryHandleRequest;
58
57
 
59
- /**
60
- * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.
61
- * This enables distributed tracing by adding trace context to the HTML document head.
62
- *
63
- * @param body - PassThrough stream containing the HTML response body to modify
64
- */
65
- function getMetaTagTransformer(body) {
66
- const headClosingTag = '</head>';
67
- const htmlMetaTagTransformer = new stream.Transform({
68
- transform(chunk, _encoding, callback) {
69
- const html = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);
70
- if (html.includes(headClosingTag)) {
71
- const modifiedHtml = html.replace(headClosingTag, `${core.getTraceMetaTags()}${headClosingTag}`);
72
- callback(null, modifiedHtml);
73
- return;
74
- }
75
- callback(null, chunk);
76
- },
77
- });
78
- htmlMetaTagTransformer.pipe(body);
79
- return htmlMetaTagTransformer;
80
- }
81
-
82
- exports.getMetaTagTransformer = getMetaTagTransformer;
83
58
  exports.sentryHandleRequest = sentryHandleRequest;
84
59
  exports.wrapSentryHandleRequest = wrapSentryHandleRequest;
85
60
  //# sourceMappingURL=wrapSentryHandleRequest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { context } from '@opentelemetry/api';\nimport { getRPCMetadata, RPCType } from '@opentelemetry/core';\nimport { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport {\n flushIfServerless,\n getActiveSpan,\n getRootSpan,\n getTraceMetaTags,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n} from '@sentry/core';\nimport type { AppLoadContext, EntryContext } from 'react-router';\nimport type { PassThrough } from 'stream';\nimport { Transform } from 'stream';\n\ntype OriginalHandleRequest = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\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(originalHandle: OriginalHandleRequest): OriginalHandleRequest {\n return async function sentryInstrumentedHandleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\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 const routeName = `/${parameterizedPath}`;\n\n // The express instrumentation writes on the rpcMetadata and that ends up stomping on the `http.route` attribute.\n const rpcMetadata = getRPCMetadata(context.active());\n\n if (rpcMetadata?.type === RPCType.HTTP) {\n rpcMetadata.route = routeName;\n }\n\n // The span exporter picks up the `http.route` (ATTR_HTTP_ROUTE) attribute to set the transaction name\n rootSpan.setAttributes({\n [ATTR_HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react-router.request-handler',\n });\n }\n\n try {\n return await originalHandle(request, responseStatusCode, responseHeaders, routerContext, loadContext);\n } finally {\n await flushIfServerless();\n }\n };\n}\n\n// todo(v11): remove this\n/** @deprecated Use `wrapSentryHandleRequest` instead. */\nexport const sentryHandleRequest = wrapSentryHandleRequest;\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":["getActiveSpan","getRootSpan","getRPCMetadata","context","RPCType","ATTR_HTTP_ROUTE","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","flushIfServerless","Transform","getTraceMetaTags"],"mappings":";;;;;;;;AAuBA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,uBAAuB,CAAC,cAAc,EAAgD;AACtG,EAAE,OAAO,eAAe,+BAA+B;AACvD,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,WAAW;AACf,IAAI;AACJ,IAAI,MAAM,iBAAA;AACV,MAAM,aAAa,EAAE,oBAAoB,EAAE,OAAO,GAAG,aAAa,CAAC,oBAAoB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI;;AAEvH,IAAI,MAAM,UAAA,GAAaA,kBAAa,EAAE;AACtC,IAAI,MAAM,QAAA,GAAW,UAAA,GAAaC,gBAAW,CAAC,UAAU,CAAA,GAAI,SAAS;;AAErE,IAAI,IAAI,iBAAA,IAAqB,QAAQ,EAAE;AACvC,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;;AAEA;AACA,MAAA,MAAA,WAAA,GAAAC,qBAAA,CAAAC,WAAA,CAAA,MAAA,EAAA,CAAA;;AAEA,MAAA,IAAA,WAAA,EAAA,IAAA,KAAAC,cAAA,CAAA,IAAA,EAAA;AACA,QAAA,WAAA,CAAA,KAAA,GAAA,SAAA;AACA;;AAEA;AACA,MAAA,QAAA,CAAA,aAAA,CAAA;AACA,QAAA,CAAAC,mCAAA,GAAA,SAAA;AACA,QAAA,CAAAC,qCAAA,GAAA,OAAA;AACA,QAAA,CAAAC,qCAAA,GAAA,wCAAA;AACA,OAAA,CAAA;AACA;;AAEA,IAAA,IAAA;AACA,MAAA,OAAA,MAAA,cAAA,CAAA,OAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,aAAA,EAAA,WAAA,CAAA;AACA,KAAA,SAAA;AACA,MAAA,MAAAC,sBAAA,EAAA;AACA;AACA,GAAA;AACA;;AAEA;AACA;AACA,MAAA,mBAAA,GAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,qBAAA,CAAA,IAAA,EAAA;AACA,EAAA,MAAA,cAAA,GAAA,SAAA;AACA,EAAA,MAAA,sBAAA,GAAA,IAAAC,gBAAA,CAAA;AACA,IAAA,SAAA,CAAA,KAAA,EAAA,SAAA,EAAA,QAAA,EAAA;AACA,MAAA,MAAA,IAAA,GAAA,MAAA,CAAA,QAAA,CAAA,KAAA,CAAA,GAAA,KAAA,CAAA,QAAA,EAAA,GAAA,MAAA,CAAA,KAAA,CAAA;AACA,MAAA,IAAA,IAAA,CAAA,QAAA,CAAA,cAAA,CAAA,EAAA;AACA,QAAA,MAAA,YAAA,GAAA,IAAA,CAAA,OAAA,CAAA,cAAA,EAAA,CAAA,EAAAC,qBAAA,EAAA,CAAA,EAAA,cAAA,CAAA,CAAA,CAAA;AACA,QAAA,QAAA,CAAA,IAAA,EAAA,YAAA,CAAA;AACA,QAAA;AACA;AACA,MAAA,QAAA,CAAA,IAAA,EAAA,KAAA,CAAA;AACA,KAAA;AACA,GAAA,CAAA;AACA,EAAA,sBAAA,CAAA,IAAA,CAAA,IAAA,CAAA;AACA,EAAA,OAAA,sBAAA;AACA;;;;;;"}
1
+ {"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { context } from '@opentelemetry/api';\nimport { getRPCMetadata, RPCType } from '@opentelemetry/core';\nimport { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport {\n flushIfServerless,\n getActiveSpan,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n} from '@sentry/core';\nimport type { AppLoadContext, EntryContext } from 'react-router';\n\ntype OriginalHandleRequest = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\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(originalHandle: OriginalHandleRequest): OriginalHandleRequest {\n return async function sentryInstrumentedHandleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\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 const routeName = `/${parameterizedPath}`;\n\n // The express instrumentation writes on the rpcMetadata and that ends up stomping on the `http.route` attribute.\n const rpcMetadata = getRPCMetadata(context.active());\n\n if (rpcMetadata?.type === RPCType.HTTP) {\n rpcMetadata.route = routeName;\n }\n\n // The span exporter picks up the `http.route` (ATTR_HTTP_ROUTE) attribute to set the transaction name\n rootSpan.setAttributes({\n [ATTR_HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react-router.request-handler',\n });\n }\n\n try {\n return await originalHandle(request, responseStatusCode, responseHeaders, routerContext, loadContext);\n } finally {\n await flushIfServerless();\n }\n };\n}\n\n// todo(v11): remove this\n/** @deprecated Use `wrapSentryHandleRequest` instead. */\nexport const sentryHandleRequest = wrapSentryHandleRequest;\n"],"names":["getActiveSpan","getRootSpan","getRPCMetadata","context","RPCType","ATTR_HTTP_ROUTE","SEMANTIC_ATTRIBUTE_SENTRY_SOURCE","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","flushIfServerless"],"mappings":";;;;;;;AAoBA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,uBAAuB,CAAC,cAAc,EAAgD;AACtG,EAAE,OAAO,eAAe,+BAA+B;AACvD,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,WAAW;AACf,IAAI;AACJ,IAAI,MAAM,iBAAA;AACV,MAAM,aAAa,EAAE,oBAAoB,EAAE,OAAO,GAAG,aAAa,CAAC,oBAAoB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI;;AAEvH,IAAI,MAAM,UAAA,GAAaA,kBAAa,EAAE;AACtC,IAAI,MAAM,QAAA,GAAW,UAAA,GAAaC,gBAAW,CAAC,UAAU,CAAA,GAAI,SAAS;;AAErE,IAAI,IAAI,iBAAA,IAAqB,QAAQ,EAAE;AACvC,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;;AAEA;AACA,MAAA,MAAA,WAAA,GAAAC,qBAAA,CAAAC,WAAA,CAAA,MAAA,EAAA,CAAA;;AAEA,MAAA,IAAA,WAAA,EAAA,IAAA,KAAAC,cAAA,CAAA,IAAA,EAAA;AACA,QAAA,WAAA,CAAA,KAAA,GAAA,SAAA;AACA;;AAEA;AACA,MAAA,QAAA,CAAA,aAAA,CAAA;AACA,QAAA,CAAAC,mCAAA,GAAA,SAAA;AACA,QAAA,CAAAC,qCAAA,GAAA,OAAA;AACA,QAAA,CAAAC,qCAAA,GAAA,wCAAA;AACA,OAAA,CAAA;AACA;;AAEA,IAAA,IAAA;AACA,MAAA,OAAA,MAAA,cAAA,CAAA,OAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,aAAA,EAAA,WAAA,CAAA;AACA,KAAA,SAAA;AACA,MAAA,MAAAC,sBAAA,EAAA;AACA;AACA,GAAA;AACA;;AAEA;AACA;AACA,MAAA,mBAAA,GAAA;;;;;"}
@@ -57,7 +57,10 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
57
57
  if (sourceMapsUploadOptions?.enabled ?? (viteConfig.build.sourcemap !== false)) {
58
58
  // inject debugIds
59
59
  try {
60
- await cliInstance.execute(['sourcemaps', 'inject', reactRouterConfig.buildDirectory], debug);
60
+ await cliInstance.execute(
61
+ ['sourcemaps', 'inject', reactRouterConfig.buildDirectory],
62
+ debug ? 'rejectOnError' : false,
63
+ );
61
64
  } catch (error) {
62
65
  // eslint-disable-next-line no-console
63
66
  console.error('[Sentry] Could not inject debug ids', error);
@@ -71,6 +74,7 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
71
74
  paths: [reactRouterConfig.buildDirectory],
72
75
  },
73
76
  ],
77
+ live: 'rejectOnError',
74
78
  });
75
79
  } catch (error) {
76
80
  // eslint-disable-next-line no-console
@@ -82,14 +86,13 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
82
86
  // set a default value no option was set
83
87
  if (typeof sourceMapsUploadOptions?.filesToDeleteAfterUpload === 'undefined') {
84
88
  updatedFilesToDeleteAfterUpload = [`${reactRouterConfig.buildDirectory}/**/*.map`];
85
- if (debug) {
89
+ debug &&
86
90
  // eslint-disable-next-line no-console
87
91
  console.info(
88
92
  `[Sentry] Automatically setting \`sourceMapsUploadOptions.filesToDeleteAfterUpload: ${JSON.stringify(
89
93
  updatedFilesToDeleteAfterUpload,
90
94
  )}\` to delete generated source maps after they were uploaded to Sentry.`,
91
95
  );
92
- }
93
96
  }
94
97
  if (updatedFilesToDeleteAfterUpload) {
95
98
  try {
@@ -106,11 +109,10 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
106
109
  await Promise.all(
107
110
  filePathsToDelete.map(filePathToDelete =>
108
111
  promises.rm(filePathToDelete, { force: true }).catch((e) => {
109
- if (debug) {
110
- // This is allowed to fail - we just don't do anything
112
+ // This is allowed to fail - we just don't do anything
113
+ debug &&
111
114
  // eslint-disable-next-line no-console
112
115
  console.debug(`An error occurred while attempting to delete asset: ${filePathToDelete}`, e);
113
- }
114
116
  }),
115
117
  ),
116
118
  );
@@ -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 { 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 * 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 org,\n project,\n release,\n sourceMapsUploadOptions = { enabled: true },\n debug = false,\n unstable_sentryVitePluginOptions,\n }: SentryReactRouterBuildOptions = {\n ...sentryConfig.unstable_sentryVitePluginOptions,\n ...sentryConfig,\n release: {\n ...sentryConfig.unstable_sentryVitePluginOptions?.release,\n ...sentryConfig.release,\n },\n };\n\n const cliInstance = new SentryCli(null, {\n authToken,\n org,\n project,\n ...unstable_sentryVitePluginOptions,\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 if (sourceMapsUploadOptions?.enabled ?? (true && viteConfig.build.sourcemap !== false)) {\n // inject debugIds\n try {\n await cliInstance.execute(['sourcemaps', 'inject', reactRouterConfig.buildDirectory], debug);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not inject debug ids', error);\n }\n\n // upload sourcemaps\n try {\n await cliInstance.releases.uploadSourceMaps(release?.name || 'undefined', {\n include: [\n {\n paths: [reactRouterConfig.buildDirectory],\n },\n ],\n });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not upload sourcemaps', error);\n }\n }\n // delete sourcemaps after upload\n let updatedFilesToDeleteAfterUpload = sourceMapsUploadOptions?.filesToDeleteAfterUpload;\n // set a default value no option was set\n if (typeof sourceMapsUploadOptions?.filesToDeleteAfterUpload === 'undefined') {\n updatedFilesToDeleteAfterUpload = [`${reactRouterConfig.buildDirectory}/**/*.map`];\n if (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 }\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 if (debug) {\n // This is allowed to fail - we just don't do anything\n // eslint-disable-next-line no-console\n console.debug(`An error occurred while attempting to delete asset: ${filePathToDelete}`, e);\n }\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 SentryCli from '@sentry/cli';\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 * 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 org,\n project,\n release,\n sourceMapsUploadOptions = { enabled: true },\n debug = false,\n unstable_sentryVitePluginOptions,\n }: SentryReactRouterBuildOptions = {\n ...sentryConfig.unstable_sentryVitePluginOptions,\n ...sentryConfig,\n release: {\n ...sentryConfig.unstable_sentryVitePluginOptions?.release,\n ...sentryConfig.release,\n },\n };\n\n const cliInstance = new SentryCli(null, {\n authToken,\n org,\n project,\n ...unstable_sentryVitePluginOptions,\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 if (sourceMapsUploadOptions?.enabled ?? (true && 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 // 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 // delete sourcemaps after upload\n let updatedFilesToDeleteAfterUpload = sourceMapsUploadOptions?.filesToDeleteAfterUpload;\n // set a default value no option was set\n if (typeof sourceMapsUploadOptions?.filesToDeleteAfterUpload === '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,7 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
- const core = require('@sentry/core');
4
-
5
3
  /**
6
4
  * A Sentry plugin for React Router to enable "hidden" source maps if they are unset.
7
5
  */
@@ -47,36 +45,35 @@ function getUpdatedSourceMapSettings(
47
45
  let updatedSourceMapSetting = viteSourceMap;
48
46
 
49
47
  const settingKey = 'vite.build.sourcemap';
48
+ const debug = sentryPluginOptions?.debug;
50
49
 
51
50
  if (viteSourceMap === false) {
52
51
  updatedSourceMapSetting = viteSourceMap;
53
52
 
54
- core.consoleSandbox(() => {
55
- // eslint-disable-next-line no-console
53
+ if (debug) {
54
+ // Longer debug message with more details
55
+ // eslint-disable-next-line no-console
56
56
  console.warn(
57
57
  `[Sentry] Source map generation is currently disabled in your Vite configuration (\`${settingKey}: false \`). This setting is either a default setting or was explicitly set in your configuration. Sentry won't override this setting. Without source maps, code snippets on the Sentry Issues page will remain minified. To show unminified code, enable source maps in \`${settingKey}\` (e.g. by setting them to \`hidden\`).`,
58
58
  );
59
- });
59
+ } else {
60
+ // eslint-disable-next-line no-console
61
+ console.warn('[Sentry] Source map generation is disabled in your Vite configuration.');
62
+ }
60
63
  } else if (viteSourceMap && ['hidden', 'inline', true].includes(viteSourceMap)) {
61
64
  updatedSourceMapSetting = viteSourceMap;
62
65
 
63
- if (sentryPluginOptions?.debug) {
64
- core.consoleSandbox(() => {
65
- // eslint-disable-next-line no-console
66
- console.log(
67
- `[Sentry] We discovered \`${settingKey}\` is set to \`${viteSourceMap.toString()}\`. Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.`,
68
- );
69
- });
70
- }
66
+ debug &&
67
+ // eslint-disable-next-line no-console
68
+ console.log(
69
+ `[Sentry] We discovered \`${settingKey}\` is set to \`${viteSourceMap.toString()}\`. Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.`,
70
+ );
71
71
  } else {
72
72
  updatedSourceMapSetting = 'hidden';
73
-
74
- core.consoleSandbox(() => {
75
- // eslint-disable-next-line no-console
73
+ debug && // eslint-disable-next-line no-console
76
74
  console.log(
77
75
  `[Sentry] Enabled source map generation in the build options with \`${settingKey}: 'hidden'\`. The source maps will be deleted after they were uploaded to Sentry.`,
78
76
  );
79
- });
80
77
  }
81
78
 
82
79
  return updatedSourceMapSetting;
@@ -1 +1 @@
1
- {"version":3,"file":"makeEnableSourceMapsPlugin.js","sources":["../../../src/vite/makeEnableSourceMapsPlugin.ts"],"sourcesContent":["import { consoleSandbox } from '@sentry/core';\nimport type { Plugin, UserConfig } from 'vite';\nimport type { SentryReactRouterBuildOptions } from './types';\n\n/**\n * A Sentry plugin for React Router to enable \"hidden\" source maps if they are unset.\n */\nexport function makeEnableSourceMapsPlugin(options: SentryReactRouterBuildOptions): Plugin {\n return {\n name: 'sentry-react-router-update-source-map-setting',\n apply: 'build',\n enforce: 'post',\n config(viteConfig) {\n return {\n ...viteConfig,\n build: {\n ...viteConfig.build,\n sourcemap: getUpdatedSourceMapSettings(viteConfig, options),\n },\n };\n },\n };\n}\n\n/** There are 3 ways to set up source map generation\n *\n * 1. User explicitly disabled source maps\n * - keep this setting (emit a warning that errors won't be unminified in Sentry)\n * - we won't upload anything\n *\n * 2. Users enabled source map generation (true, 'hidden', 'inline').\n * - keep this setting (don't do anything - like deletion - besides uploading)\n *\n * 3. Users didn't set source maps generation\n * - we enable 'hidden' source maps generation\n * - configure `filesToDeleteAfterUpload` to delete all .map files (we emit a log about this)\n *\n * --> only exported for testing\n */\nexport function getUpdatedSourceMapSettings(\n viteConfig: UserConfig,\n sentryPluginOptions?: SentryReactRouterBuildOptions,\n): boolean | 'inline' | 'hidden' {\n viteConfig.build = viteConfig.build || {};\n\n const viteSourceMap = viteConfig?.build?.sourcemap;\n let updatedSourceMapSetting = viteSourceMap;\n\n const settingKey = 'vite.build.sourcemap';\n\n if (viteSourceMap === false) {\n updatedSourceMapSetting = viteSourceMap;\n\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] Source map generation is currently disabled in your Vite configuration (\\`${settingKey}: false \\`). This setting is either a default setting or was explicitly set in your configuration. Sentry won't override this setting. Without source maps, code snippets on the Sentry Issues page will remain minified. To show unminified code, enable source maps in \\`${settingKey}\\` (e.g. by setting them to \\`hidden\\`).`,\n );\n });\n } else if (viteSourceMap && ['hidden', 'inline', true].includes(viteSourceMap)) {\n updatedSourceMapSetting = viteSourceMap;\n\n if (sentryPluginOptions?.debug) {\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.log(\n `[Sentry] We discovered \\`${settingKey}\\` is set to \\`${viteSourceMap.toString()}\\`. Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.`,\n );\n });\n }\n } else {\n updatedSourceMapSetting = 'hidden';\n\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.log(\n `[Sentry] Enabled source map generation in the build options with \\`${settingKey}: 'hidden'\\`. The source maps will be deleted after they were uploaded to Sentry.`,\n );\n });\n }\n\n return updatedSourceMapSetting;\n}\n"],"names":["consoleSandbox"],"mappings":";;;;AAIA;AACA;AACA;AACO,SAAS,0BAA0B,CAAC,OAAO,EAAyC;AAC3F,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,+CAA+C;AACzD,IAAI,KAAK,EAAE,OAAO;AAClB,IAAI,OAAO,EAAE,MAAM;AACnB,IAAI,MAAM,CAAC,UAAU,EAAE;AACvB,MAAM,OAAO;AACb,QAAQ,GAAG,UAAU;AACrB,QAAQ,KAAK,EAAE;AACf,UAAU,GAAG,UAAU,CAAC,KAAK;AAC7B,UAAU,SAAS,EAAE,2BAA2B,CAAC,UAAU,EAAE,OAAO,CAAC;AACrE,SAAS;AACT,OAAO;AACP,KAAK;AACL,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,2BAA2B;AAC3C,EAAE,UAAU;AACZ,EAAE,mBAAmB;AACrB,EAAiC;AACjC,EAAE,UAAU,CAAC,KAAA,GAAQ,UAAU,CAAC,KAAA,IAAS,EAAE;;AAE3C,EAAE,MAAM,aAAA,GAAgB,UAAU,EAAE,KAAK,EAAE,SAAS;AACpD,EAAE,IAAI,uBAAA,GAA0B,aAAa;;AAE7C,EAAE,MAAM,UAAA,GAAa,sBAAsB;;AAE3C,EAAE,IAAI,aAAA,KAAkB,KAAK,EAAE;AAC/B,IAAI,uBAAA,GAA0B,aAAa;;AAE3C,IAAIA,mBAAc,CAAC,MAAM;AACzB;AACA,MAAM,OAAO,CAAC,IAAI;AAClB,QAAQ,CAAC,mFAAmF,EAAE,UAAU,CAAC,2QAA2Q,EAAE,UAAU,CAAC,wCAAwC,CAAC;AAC1a,OAAO;AACP,KAAK,CAAC;AACN,SAAS,IAAI,aAAA,IAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE;AAClF,IAAI,uBAAA,GAA0B,aAAa;;AAE3C,IAAI,IAAI,mBAAmB,EAAE,KAAK,EAAE;AACpC,MAAMA,mBAAc,CAAC,MAAM;AAC3B;AACA,QAAQ,OAAO,CAAC,GAAG;AACnB,UAAU,CAAC,yBAAyB,EAAE,UAAU,CAAC,eAAe,EAAE,aAAa,CAAC,QAAQ,EAAE,CAAC,4GAA4G,CAAC;AACxM,SAAS;AACT,OAAO,CAAC;AACR;AACA,SAAS;AACT,IAAI,uBAAA,GAA0B,QAAQ;;AAEtC,IAAIA,mBAAc,CAAC,MAAM;AACzB;AACA,MAAM,OAAO,CAAC,GAAG;AACjB,QAAQ,CAAC,mEAAmE,EAAE,UAAU,CAAC,kFAAkF,CAAC;AAC5K,OAAO;AACP,KAAK,CAAC;AACN;;AAEA,EAAE,OAAO,uBAAuB;AAChC;;;;;"}
1
+ {"version":3,"file":"makeEnableSourceMapsPlugin.js","sources":["../../../src/vite/makeEnableSourceMapsPlugin.ts"],"sourcesContent":["import type { Plugin, UserConfig } from 'vite';\nimport type { SentryReactRouterBuildOptions } from './types';\n\n/**\n * A Sentry plugin for React Router to enable \"hidden\" source maps if they are unset.\n */\nexport function makeEnableSourceMapsPlugin(options: SentryReactRouterBuildOptions): Plugin {\n return {\n name: 'sentry-react-router-update-source-map-setting',\n apply: 'build',\n enforce: 'post',\n config(viteConfig) {\n return {\n ...viteConfig,\n build: {\n ...viteConfig.build,\n sourcemap: getUpdatedSourceMapSettings(viteConfig, options),\n },\n };\n },\n };\n}\n\n/** There are 3 ways to set up source map generation\n *\n * 1. User explicitly disabled source maps\n * - keep this setting (emit a warning that errors won't be unminified in Sentry)\n * - we won't upload anything\n *\n * 2. Users enabled source map generation (true, 'hidden', 'inline').\n * - keep this setting (don't do anything - like deletion - besides uploading)\n *\n * 3. Users didn't set source maps generation\n * - we enable 'hidden' source maps generation\n * - configure `filesToDeleteAfterUpload` to delete all .map files (we emit a log about this)\n *\n * --> only exported for testing\n */\nexport function getUpdatedSourceMapSettings(\n viteConfig: UserConfig,\n sentryPluginOptions?: SentryReactRouterBuildOptions,\n): boolean | 'inline' | 'hidden' {\n viteConfig.build = viteConfig.build || {};\n\n const viteSourceMap = viteConfig?.build?.sourcemap;\n let updatedSourceMapSetting = viteSourceMap;\n\n const settingKey = 'vite.build.sourcemap';\n const debug = sentryPluginOptions?.debug;\n\n if (viteSourceMap === false) {\n updatedSourceMapSetting = viteSourceMap;\n\n if (debug) {\n // Longer debug message with more details\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] Source map generation is currently disabled in your Vite configuration (\\`${settingKey}: false \\`). This setting is either a default setting or was explicitly set in your configuration. Sentry won't override this setting. Without source maps, code snippets on the Sentry Issues page will remain minified. To show unminified code, enable source maps in \\`${settingKey}\\` (e.g. by setting them to \\`hidden\\`).`,\n );\n } else {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Source map generation is disabled in your Vite configuration.');\n }\n } else if (viteSourceMap && ['hidden', 'inline', true].includes(viteSourceMap)) {\n updatedSourceMapSetting = viteSourceMap;\n\n debug &&\n // eslint-disable-next-line no-console\n console.log(\n `[Sentry] We discovered \\`${settingKey}\\` is set to \\`${viteSourceMap.toString()}\\`. Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.`,\n );\n } else {\n updatedSourceMapSetting = 'hidden';\n debug && // eslint-disable-next-line no-console\n console.log(\n `[Sentry] Enabled source map generation in the build options with \\`${settingKey}: 'hidden'\\`. The source maps will be deleted after they were uploaded to Sentry.`,\n );\n }\n\n return updatedSourceMapSetting;\n}\n"],"names":[],"mappings":";;AAGA;AACA;AACA;AACO,SAAS,0BAA0B,CAAC,OAAO,EAAyC;AAC3F,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,+CAA+C;AACzD,IAAI,KAAK,EAAE,OAAO;AAClB,IAAI,OAAO,EAAE,MAAM;AACnB,IAAI,MAAM,CAAC,UAAU,EAAE;AACvB,MAAM,OAAO;AACb,QAAQ,GAAG,UAAU;AACrB,QAAQ,KAAK,EAAE;AACf,UAAU,GAAG,UAAU,CAAC,KAAK;AAC7B,UAAU,SAAS,EAAE,2BAA2B,CAAC,UAAU,EAAE,OAAO,CAAC;AACrE,SAAS;AACT,OAAO;AACP,KAAK;AACL,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,2BAA2B;AAC3C,EAAE,UAAU;AACZ,EAAE,mBAAmB;AACrB,EAAiC;AACjC,EAAE,UAAU,CAAC,KAAA,GAAQ,UAAU,CAAC,KAAA,IAAS,EAAE;;AAE3C,EAAE,MAAM,aAAA,GAAgB,UAAU,EAAE,KAAK,EAAE,SAAS;AACpD,EAAE,IAAI,uBAAA,GAA0B,aAAa;;AAE7C,EAAE,MAAM,UAAA,GAAa,sBAAsB;AAC3C,EAAE,MAAM,KAAA,GAAQ,mBAAmB,EAAE,KAAK;;AAE1C,EAAE,IAAI,aAAA,KAAkB,KAAK,EAAE;AAC/B,IAAI,uBAAA,GAA0B,aAAa;;AAE3C,IAAI,IAAI,KAAK,EAAE;AACf;AACA;AACA,MAAM,OAAO,CAAC,IAAI;AAClB,QAAQ,CAAC,mFAAmF,EAAE,UAAU,CAAC,2QAA2Q,EAAE,UAAU,CAAC,wCAAwC,CAAC;AAC1a,OAAO;AACP,WAAW;AACX;AACA,MAAM,OAAO,CAAC,IAAI,CAAC,wEAAwE,CAAC;AAC5F;AACA,SAAS,IAAI,aAAA,IAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE;AAClF,IAAI,uBAAA,GAA0B,aAAa;;AAE3C,IAAI,KAAA;AACJ;AACA,MAAM,OAAO,CAAC,GAAG;AACjB,QAAQ,CAAC,yBAAyB,EAAE,UAAU,CAAC,eAAe,EAAE,aAAa,CAAC,QAAQ,EAAE,CAAC,4GAA4G,CAAC;AACtM,OAAO;AACP,SAAS;AACT,IAAI,uBAAA,GAA0B,QAAQ;AACtC,IAAI,KAAA;AACJ,MAAM,OAAO,CAAC,GAAG;AACjB,QAAQ,CAAC,mEAAmE,EAAE,UAAU,CAAC,kFAAkF,CAAC;AAC5K,OAAO;AACP;;AAEA,EAAE,OAAO,uBAAuB;AAChC;;;;;"}
@@ -0,0 +1,45 @@
1
+ import { getTraceMetaTags } from '@sentry/core';
2
+ export * from '@sentry/browser';
3
+ export { init } from '../client/sdk.js';
4
+ export { reactRouterTracingIntegration } from '../client/tracingIntegration.js';
5
+ export { ErrorBoundary, Profiler, captureReactException, reactErrorHandler, useProfiler, withErrorBoundary, withProfiler } from '@sentry/react';
6
+ export { wrapSentryHandleRequest } from '../server/wrapSentryHandleRequest.js';
7
+
8
+ /**
9
+ * Injects Sentry trace meta tags into the HTML response by transforming the ReadableStream.
10
+ * This enables distributed tracing by adding trace context to the HTML document head.
11
+ * @param body - ReadableStream containing the HTML response body to modify
12
+ * @returns A new ReadableStream with Sentry trace meta tags injected into the head section
13
+ */
14
+ function injectTraceMetaTags(body) {
15
+ const headClosingTag = '</head>';
16
+
17
+ const reader = body.getReader();
18
+ const stream = new ReadableStream({
19
+ async pull(controller) {
20
+ const { done, value } = await reader.read();
21
+
22
+ if (done) {
23
+ controller.close();
24
+ return;
25
+ }
26
+
27
+ const encoder = new TextEncoder();
28
+ const html = value instanceof Uint8Array ? new TextDecoder().decode(value) : String(value);
29
+
30
+ if (html.includes(headClosingTag)) {
31
+ const modifiedHtml = html.replace(headClosingTag, `${getTraceMetaTags()}${headClosingTag}`);
32
+
33
+ controller.enqueue(encoder.encode(modifiedHtml));
34
+ return;
35
+ }
36
+
37
+ controller.enqueue(encoder.encode(html));
38
+ },
39
+ });
40
+
41
+ return stream;
42
+ }
43
+
44
+ export { injectTraceMetaTags };
45
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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":[],"mappings":";;;;;;;AAMA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,mBAAmB,CAAC,IAAI,EAAkC;AAC1E,EAAE,MAAM,cAAA,GAAiB,SAAS;;AAElC,EAAE,MAAM,MAAA,GAAS,IAAI,CAAC,SAAS,EAAE;AACjC,EAAE,MAAM,MAAA,GAAS,IAAI,cAAc,CAAC;AACpC,IAAI,MAAM,IAAI,CAAC,UAAU,EAAE;AAC3B,MAAM,MAAM,EAAE,IAAI,EAAE,KAAA,EAAM,GAAI,MAAM,MAAM,CAAC,IAAI,EAAE;;AAEjD,MAAM,IAAI,IAAI,EAAE;AAChB,QAAQ,UAAU,CAAC,KAAK,EAAE;AAC1B,QAAQ;AACR;;AAEA,MAAM,MAAM,OAAA,GAAU,IAAI,WAAW,EAAE;AACvC,MAAM,MAAM,OAAO,KAAA,YAAiB,UAAA,GAAa,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAA,GAAI,MAAM,CAAC,KAAK,CAAC;;AAEhG,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE;AACzC,QAAQ,MAAM,YAAA,GAAe,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,EAAA,gBAAA,EAAA,CAAA,EAAA,cAAA,CAAA,CAAA,CAAA;;AAEA,QAAA,UAAA,CAAA,OAAA,CAAA,OAAA,CAAA,MAAA,CAAA,YAAA,CAAA,CAAA;AACA,QAAA;AACA;;AAEA,MAAA,UAAA,CAAA,OAAA,CAAA,OAAA,CAAA,MAAA,CAAA,IAAA,CAAA,CAAA;AACA,KAAA;AACA,GAAA,CAAA;;AAEA,EAAA,OAAA,MAAA;AACA;;;;"}
@@ -1,10 +1,11 @@
1
1
  export * from '@sentry/node';
2
2
  export { init } from './server/sdk.js';
3
- export { getMetaTagTransformer, sentryHandleRequest, wrapSentryHandleRequest } from './server/wrapSentryHandleRequest.js';
3
+ export { sentryHandleRequest, wrapSentryHandleRequest } from './server/wrapSentryHandleRequest.js';
4
4
  export { createSentryHandleRequest } from './server/createSentryHandleRequest.js';
5
5
  export { wrapServerAction } from './server/wrapServerAction.js';
6
6
  export { wrapServerLoader } from './server/wrapServerLoader.js';
7
7
  export { createSentryHandleError } from './server/createSentryHandleError.js';
8
+ export { getMetaTagTransformer } from './server/getMetaTagTransformer.js';
8
9
  export { sentryReactRouter } from './vite/plugin.js';
9
10
  export { sentryOnBuildEnd } from './vite/buildEnd/handleOnBuildEnd.js';
10
11
  export { makeConfigInjectorPlugin } from './vite/makeConfigInjectorPlugin.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":";;;;;;;;;;"}
@@ -1 +1 @@
1
- {"type":"module","version":"10.1.0"}
1
+ {"type":"module","version":"10.3.0"}
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { PassThrough } from 'stream';
3
- import { wrapSentryHandleRequest, getMetaTagTransformer } from './wrapSentryHandleRequest.js';
3
+ import { getMetaTagTransformer } from './getMetaTagTransformer.js';
4
+ import { wrapSentryHandleRequest } from './wrapSentryHandleRequest.js';
4
5
 
5
6
  /**
6
7
  * A complete Sentry-instrumented handleRequest implementation that handles both
@@ -1 +1 @@
1
- {"version":3,"file":"createSentryHandleRequest.js","sources":["../../../src/server/createSentryHandleRequest.tsx"],"sourcesContent":["import type { createReadableStreamFromReadable } from '@react-router/node';\nimport type { ReactNode } from 'react';\nimport React from 'react';\nimport type { AppLoadContext, EntryContext, ServerRouter } from 'react-router';\nimport { PassThrough } from 'stream';\nimport { getMetaTagTransformer, wrapSentryHandleRequest } from './wrapSentryHandleRequest';\n\ntype RenderToPipeableStreamOptions = {\n [key: string]: unknown;\n onShellReady?: () => void;\n onAllReady?: () => void;\n onShellError?: (error: unknown) => void;\n onError?: (error: unknown) => void;\n};\n\ntype RenderToPipeableStreamResult = {\n pipe: (destination: NodeJS.WritableStream) => void;\n abort: () => void;\n};\n\ntype RenderToPipeableStreamFunction = (\n node: ReactNode,\n options: RenderToPipeableStreamOptions,\n) => RenderToPipeableStreamResult;\n\nexport interface SentryHandleRequestOptions {\n /**\n * Timeout in milliseconds after which the rendering stream will be aborted\n * @default 10000\n */\n streamTimeout?: number;\n\n /**\n * React's renderToPipeableStream function from 'react-dom/server'\n */\n renderToPipeableStream: RenderToPipeableStreamFunction;\n\n /**\n * The <ServerRouter /> component from '@react-router/server'\n */\n ServerRouter: typeof ServerRouter;\n\n /**\n * createReadableStreamFromReadable from '@react-router/node'\n */\n createReadableStreamFromReadable: typeof createReadableStreamFromReadable;\n\n /**\n * Regular expression to identify bot user agents\n * @default /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i\n */\n botRegex?: RegExp;\n}\n\n/**\n * A complete Sentry-instrumented handleRequest implementation that handles both\n * route parametrization and trace meta tag injection.\n *\n * @param options Configuration options\n * @returns A Sentry-instrumented handleRequest function\n */\nexport function createSentryHandleRequest(\n options: SentryHandleRequestOptions,\n): (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown> {\n const {\n streamTimeout = 10000,\n renderToPipeableStream,\n ServerRouter,\n createReadableStreamFromReadable,\n botRegex = /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i,\n } = options;\n\n const handleRequest = function handleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n _loadContext: AppLoadContext,\n ): Promise<Response> {\n return new Promise((resolve, reject) => {\n let shellRendered = false;\n const userAgent = request.headers.get('user-agent');\n\n // Determine if we should use onAllReady or onShellReady\n const isBot = typeof userAgent === 'string' && botRegex.test(userAgent);\n const isSpaMode = !!(routerContext as { isSpaMode?: boolean }).isSpaMode;\n\n const readyOption = isBot || isSpaMode ? 'onAllReady' : 'onShellReady';\n\n const { pipe, abort } = renderToPipeableStream(<ServerRouter context={routerContext} url={request.url} />, {\n [readyOption]() {\n shellRendered = true;\n const body = new PassThrough();\n\n const stream = createReadableStreamFromReadable(body);\n\n responseHeaders.set('Content-Type', 'text/html');\n\n resolve(\n new Response(stream, {\n headers: responseHeaders,\n status: responseStatusCode,\n }),\n );\n\n // this injects trace data to the HTML head\n pipe(getMetaTagTransformer(body));\n },\n onShellError(error: unknown) {\n reject(error);\n },\n onError(error: unknown) {\n // eslint-disable-next-line no-param-reassign\n responseStatusCode = 500;\n // Log streaming rendering errors from inside the shell. Don't log\n // errors encountered during initial shell rendering since they'll\n // reject and get logged in handleDocumentRequest.\n if (shellRendered) {\n // eslint-disable-next-line no-console\n console.error(error);\n }\n },\n });\n\n // Abort the rendering stream after the `streamTimeout`\n setTimeout(abort, streamTimeout);\n });\n };\n\n // Wrap the handle request function for request parametrization\n return wrapSentryHandleRequest(handleRequest);\n}\n"],"names":[],"mappings":";;;;AAsDA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,yBAAyB;AACzC,EAAE,OAAO;AACT;;AAMA,CAAsB;AACtB,EAAE,MAAM;AACR,IAAI,aAAA,GAAgB,KAAK;AACzB,IAAI,sBAAsB;AAC1B,IAAI,YAAY;AAChB,IAAI,gCAAgC;AACpC,IAAI,QAAA,GAAW,oFAAoF;AACnG,GAAE,GAAI,OAAO;;AAEb,EAAE,MAAM,aAAA,GAAgB,SAAS,aAAa;AAC9C,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,YAAY;AAChB,IAAuB;AACvB,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK;AAC5C,MAAM,IAAI,aAAA,GAAgB,KAAK;AAC/B,MAAM,MAAM,SAAA,GAAY,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;;AAEzD;AACA,MAAM,MAAM,KAAA,GAAQ,OAAO,SAAA,KAAc,QAAA,IAAY,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;AAC7E,MAAM,MAAM,YAAY,CAAC,CAAC,CAAC,aAAA,GAA0C,SAAS;;AAE9E,MAAM,MAAM,cAAc,KAAA,IAAS,SAAA,GAAY,YAAA,GAAe,cAAc;;AAE5E,MAAM,MAAM,EAAE,IAAI,EAAE,OAAM,GAAI,sBAAsB,CAAC,KAAA,CAAA,aAAA,CAAC,YAAA,EAAA,EAAa,OAAO,EAAC,aAAc,EAAE,GAAG,EAAC,OAAQ,CAAC,GAAG,EAAA,EAAI,EAAE;AACjH,QAAQ,CAAC,WAAW,CAAC,GAAG;AACxB,UAAU,aAAA,GAAgB,IAAI;AAC9B,UAAU,MAAM,IAAA,GAAO,IAAI,WAAW,EAAE;;AAExC,UAAU,MAAM,MAAA,GAAS,gCAAgC,CAAC,IAAI,CAAC;;AAE/D,UAAU,eAAe,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC;;AAE1D,UAAU,OAAO;AACjB,YAAY,IAAI,QAAQ,CAAC,MAAM,EAAE;AACjC,cAAc,OAAO,EAAE,eAAe;AACtC,cAAc,MAAM,EAAE,kBAAkB;AACxC,aAAa,CAAC;AACd,WAAW;;AAEX;AACA,UAAU,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;AAC3C,SAAS;AACT,QAAQ,YAAY,CAAC,KAAK,EAAW;AACrC,UAAU,MAAM,CAAC,KAAK,CAAC;AACvB,SAAS;AACT,QAAQ,OAAO,CAAC,KAAK,EAAW;AAChC;AACA,UAAU,kBAAA,GAAqB,GAAG;AAClC;AACA;AACA;AACA,UAAU,IAAI,aAAa,EAAE;AAC7B;AACA,YAAY,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;AAChC;AACA,SAAS;AACT,OAAO,CAAC;;AAER;AACA,MAAM,UAAU,CAAC,KAAK,EAAE,aAAa,CAAC;AACtC,KAAK,CAAC;AACN,GAAG;;AAEH;AACA,EAAE,OAAO,uBAAuB,CAAC,aAAa,CAAC;AAC/C;;;;"}
1
+ {"version":3,"file":"createSentryHandleRequest.js","sources":["../../../src/server/createSentryHandleRequest.tsx"],"sourcesContent":["import type { createReadableStreamFromReadable } from '@react-router/node';\nimport type { ReactNode } from 'react';\nimport React from 'react';\nimport type { AppLoadContext, EntryContext, ServerRouter } from 'react-router';\nimport { PassThrough } from 'stream';\nimport { getMetaTagTransformer } from './getMetaTagTransformer';\nimport { wrapSentryHandleRequest } from './wrapSentryHandleRequest';\n\ntype RenderToPipeableStreamOptions = {\n [key: string]: unknown;\n onShellReady?: () => void;\n onAllReady?: () => void;\n onShellError?: (error: unknown) => void;\n onError?: (error: unknown) => void;\n};\n\ntype RenderToPipeableStreamResult = {\n pipe: (destination: NodeJS.WritableStream) => void;\n abort: () => void;\n};\n\ntype RenderToPipeableStreamFunction = (\n node: ReactNode,\n options: RenderToPipeableStreamOptions,\n) => RenderToPipeableStreamResult;\n\nexport interface SentryHandleRequestOptions {\n /**\n * Timeout in milliseconds after which the rendering stream will be aborted\n * @default 10000\n */\n streamTimeout?: number;\n\n /**\n * React's renderToPipeableStream function from 'react-dom/server'\n */\n renderToPipeableStream: RenderToPipeableStreamFunction;\n\n /**\n * The <ServerRouter /> component from '@react-router/server'\n */\n ServerRouter: typeof ServerRouter;\n\n /**\n * createReadableStreamFromReadable from '@react-router/node'\n */\n createReadableStreamFromReadable: typeof createReadableStreamFromReadable;\n\n /**\n * Regular expression to identify bot user agents\n * @default /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i\n */\n botRegex?: RegExp;\n}\n\n/**\n * A complete Sentry-instrumented handleRequest implementation that handles both\n * route parametrization and trace meta tag injection.\n *\n * @param options Configuration options\n * @returns A Sentry-instrumented handleRequest function\n */\nexport function createSentryHandleRequest(\n options: SentryHandleRequestOptions,\n): (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\n) => Promise<unknown> {\n const {\n streamTimeout = 10000,\n renderToPipeableStream,\n ServerRouter,\n createReadableStreamFromReadable,\n botRegex = /bot|crawler|spider|googlebot|chrome-lighthouse|baidu|bing|google|yahoo|lighthouse/i,\n } = options;\n\n const handleRequest = function handleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n _loadContext: AppLoadContext,\n ): Promise<Response> {\n return new Promise((resolve, reject) => {\n let shellRendered = false;\n const userAgent = request.headers.get('user-agent');\n\n // Determine if we should use onAllReady or onShellReady\n const isBot = typeof userAgent === 'string' && botRegex.test(userAgent);\n const isSpaMode = !!(routerContext as { isSpaMode?: boolean }).isSpaMode;\n\n const readyOption = isBot || isSpaMode ? 'onAllReady' : 'onShellReady';\n\n const { pipe, abort } = renderToPipeableStream(<ServerRouter context={routerContext} url={request.url} />, {\n [readyOption]() {\n shellRendered = true;\n const body = new PassThrough();\n\n const stream = createReadableStreamFromReadable(body);\n\n responseHeaders.set('Content-Type', 'text/html');\n\n resolve(\n new Response(stream, {\n headers: responseHeaders,\n status: responseStatusCode,\n }),\n );\n\n // this injects trace data to the HTML head\n pipe(getMetaTagTransformer(body));\n },\n onShellError(error: unknown) {\n reject(error);\n },\n onError(error: unknown) {\n // eslint-disable-next-line no-param-reassign\n responseStatusCode = 500;\n // Log streaming rendering errors from inside the shell. Don't log\n // errors encountered during initial shell rendering since they'll\n // reject and get logged in handleDocumentRequest.\n if (shellRendered) {\n // eslint-disable-next-line no-console\n console.error(error);\n }\n },\n });\n\n // Abort the rendering stream after the `streamTimeout`\n setTimeout(abort, streamTimeout);\n });\n };\n\n // Wrap the handle request function for request parametrization\n return wrapSentryHandleRequest(handleRequest);\n}\n"],"names":[],"mappings":";;;;;AAuDA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,yBAAyB;AACzC,EAAE,OAAO;AACT;;AAMA,CAAsB;AACtB,EAAE,MAAM;AACR,IAAI,aAAA,GAAgB,KAAK;AACzB,IAAI,sBAAsB;AAC1B,IAAI,YAAY;AAChB,IAAI,gCAAgC;AACpC,IAAI,QAAA,GAAW,oFAAoF;AACnG,GAAE,GAAI,OAAO;;AAEb,EAAE,MAAM,aAAA,GAAgB,SAAS,aAAa;AAC9C,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,YAAY;AAChB,IAAuB;AACvB,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK;AAC5C,MAAM,IAAI,aAAA,GAAgB,KAAK;AAC/B,MAAM,MAAM,SAAA,GAAY,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;;AAEzD;AACA,MAAM,MAAM,KAAA,GAAQ,OAAO,SAAA,KAAc,QAAA,IAAY,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;AAC7E,MAAM,MAAM,YAAY,CAAC,CAAC,CAAC,aAAA,GAA0C,SAAS;;AAE9E,MAAM,MAAM,cAAc,KAAA,IAAS,SAAA,GAAY,YAAA,GAAe,cAAc;;AAE5E,MAAM,MAAM,EAAE,IAAI,EAAE,OAAM,GAAI,sBAAsB,CAAC,KAAA,CAAA,aAAA,CAAC,YAAA,EAAA,EAAa,OAAO,EAAC,aAAc,EAAE,GAAG,EAAC,OAAQ,CAAC,GAAG,EAAA,EAAI,EAAE;AACjH,QAAQ,CAAC,WAAW,CAAC,GAAG;AACxB,UAAU,aAAA,GAAgB,IAAI;AAC9B,UAAU,MAAM,IAAA,GAAO,IAAI,WAAW,EAAE;;AAExC,UAAU,MAAM,MAAA,GAAS,gCAAgC,CAAC,IAAI,CAAC;;AAE/D,UAAU,eAAe,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC;;AAE1D,UAAU,OAAO;AACjB,YAAY,IAAI,QAAQ,CAAC,MAAM,EAAE;AACjC,cAAc,OAAO,EAAE,eAAe;AACtC,cAAc,MAAM,EAAE,kBAAkB;AACxC,aAAa,CAAC;AACd,WAAW;;AAEX;AACA,UAAU,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;AAC3C,SAAS;AACT,QAAQ,YAAY,CAAC,KAAK,EAAW;AACrC,UAAU,MAAM,CAAC,KAAK,CAAC;AACvB,SAAS;AACT,QAAQ,OAAO,CAAC,KAAK,EAAW;AAChC;AACA,UAAU,kBAAA,GAAqB,GAAG;AAClC;AACA;AACA;AACA,UAAU,IAAI,aAAa,EAAE;AAC7B;AACA,YAAY,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;AAChC;AACA,SAAS;AACT,OAAO,CAAC;;AAER;AACA,MAAM,UAAU,CAAC,KAAK,EAAE,aAAa,CAAC;AACtC,KAAK,CAAC;AACN,GAAG;;AAEH;AACA,EAAE,OAAO,uBAAuB,CAAC,aAAa,CAAC;AAC/C;;;;"}
@@ -0,0 +1,28 @@
1
+ import { Transform } from 'node:stream';
2
+ import { getTraceMetaTags } from '@sentry/core';
3
+
4
+ /**
5
+ * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.
6
+ * This enables distributed tracing by adding trace context to the HTML document head.
7
+ *
8
+ * @param body - PassThrough stream containing the HTML response body to modify
9
+ */
10
+ function getMetaTagTransformer(body) {
11
+ const headClosingTag = '</head>';
12
+ const htmlMetaTagTransformer = new Transform({
13
+ transform(chunk, _encoding, callback) {
14
+ const html = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);
15
+ if (html.includes(headClosingTag)) {
16
+ const modifiedHtml = html.replace(headClosingTag, `${getTraceMetaTags()}${headClosingTag}`);
17
+ callback(null, modifiedHtml);
18
+ return;
19
+ }
20
+ callback(null, chunk);
21
+ },
22
+ });
23
+ htmlMetaTagTransformer.pipe(body);
24
+ return htmlMetaTagTransformer;
25
+ }
26
+
27
+ export { getMetaTagTransformer };
28
+ //# sourceMappingURL=getMetaTagTransformer.js.map
@@ -0,0 +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":[],"mappings":";;;AAIA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,qBAAqB,CAAC,IAAI,EAA0B;AACpE,EAAE,MAAM,cAAA,GAAiB,SAAS;AAClC,EAAE,MAAM,sBAAA,GAAyB,IAAI,SAAS,CAAC;AAC/C,IAAI,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE;AAC1C,MAAM,MAAM,IAAA,GAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAA,GAAI,KAAK,CAAC,QAAQ,EAAC,GAAI,MAAM,CAAC,KAAK,CAAC;AAC5E,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE;AACzC,QAAQ,MAAM,YAAA,GAAe,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,EAAA,gBAAA,EAAA,CAAA,EAAA,cAAA,CAAA,CAAA,CAAA;AACA,QAAA,QAAA,CAAA,IAAA,EAAA,YAAA,CAAA;AACA,QAAA;AACA;AACA,MAAA,QAAA,CAAA,IAAA,EAAA,KAAA,CAAA;AACA,KAAA;AACA,GAAA,CAAA;AACA,EAAA,sBAAA,CAAA,IAAA,CAAA,IAAA,CAAA;AACA,EAAA,OAAA,sBAAA;AACA;;;;"}
@@ -1,8 +1,7 @@
1
1
  import { context } from '@opentelemetry/api';
2
2
  import { getRPCMetadata, RPCType } from '@opentelemetry/core';
3
3
  import { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';
4
- import { getActiveSpan, getRootSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, flushIfServerless, getTraceMetaTags } from '@sentry/core';
5
- import { Transform } from 'stream';
4
+ import { getActiveSpan, getRootSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, flushIfServerless } from '@sentry/core';
6
5
 
7
6
  /**
8
7
  * Wraps the original handleRequest function to add Sentry instrumentation.
@@ -54,28 +53,5 @@ function wrapSentryHandleRequest(originalHandle) {
54
53
  /** @deprecated Use `wrapSentryHandleRequest` instead. */
55
54
  const sentryHandleRequest = wrapSentryHandleRequest;
56
55
 
57
- /**
58
- * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.
59
- * This enables distributed tracing by adding trace context to the HTML document head.
60
- *
61
- * @param body - PassThrough stream containing the HTML response body to modify
62
- */
63
- function getMetaTagTransformer(body) {
64
- const headClosingTag = '</head>';
65
- const htmlMetaTagTransformer = new Transform({
66
- transform(chunk, _encoding, callback) {
67
- const html = Buffer.isBuffer(chunk) ? chunk.toString() : String(chunk);
68
- if (html.includes(headClosingTag)) {
69
- const modifiedHtml = html.replace(headClosingTag, `${getTraceMetaTags()}${headClosingTag}`);
70
- callback(null, modifiedHtml);
71
- return;
72
- }
73
- callback(null, chunk);
74
- },
75
- });
76
- htmlMetaTagTransformer.pipe(body);
77
- return htmlMetaTagTransformer;
78
- }
79
-
80
- export { getMetaTagTransformer, sentryHandleRequest, wrapSentryHandleRequest };
56
+ export { sentryHandleRequest, wrapSentryHandleRequest };
81
57
  //# sourceMappingURL=wrapSentryHandleRequest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { context } from '@opentelemetry/api';\nimport { getRPCMetadata, RPCType } from '@opentelemetry/core';\nimport { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport {\n flushIfServerless,\n getActiveSpan,\n getRootSpan,\n getTraceMetaTags,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n} from '@sentry/core';\nimport type { AppLoadContext, EntryContext } from 'react-router';\nimport type { PassThrough } from 'stream';\nimport { Transform } from 'stream';\n\ntype OriginalHandleRequest = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\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(originalHandle: OriginalHandleRequest): OriginalHandleRequest {\n return async function sentryInstrumentedHandleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\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 const routeName = `/${parameterizedPath}`;\n\n // The express instrumentation writes on the rpcMetadata and that ends up stomping on the `http.route` attribute.\n const rpcMetadata = getRPCMetadata(context.active());\n\n if (rpcMetadata?.type === RPCType.HTTP) {\n rpcMetadata.route = routeName;\n }\n\n // The span exporter picks up the `http.route` (ATTR_HTTP_ROUTE) attribute to set the transaction name\n rootSpan.setAttributes({\n [ATTR_HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react-router.request-handler',\n });\n }\n\n try {\n return await originalHandle(request, responseStatusCode, responseHeaders, routerContext, loadContext);\n } finally {\n await flushIfServerless();\n }\n };\n}\n\n// todo(v11): remove this\n/** @deprecated Use `wrapSentryHandleRequest` instead. */\nexport const sentryHandleRequest = wrapSentryHandleRequest;\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":[],"mappings":";;;;;;AAuBA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,uBAAuB,CAAC,cAAc,EAAgD;AACtG,EAAE,OAAO,eAAe,+BAA+B;AACvD,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,WAAW;AACf,IAAI;AACJ,IAAI,MAAM,iBAAA;AACV,MAAM,aAAa,EAAE,oBAAoB,EAAE,OAAO,GAAG,aAAa,CAAC,oBAAoB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI;;AAEvH,IAAI,MAAM,UAAA,GAAa,aAAa,EAAE;AACtC,IAAI,MAAM,QAAA,GAAW,UAAA,GAAa,WAAW,CAAC,UAAU,CAAA,GAAI,SAAS;;AAErE,IAAI,IAAI,iBAAA,IAAqB,QAAQ,EAAE;AACvC,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;;AAEA;AACA,MAAA,MAAA,WAAA,GAAA,cAAA,CAAA,OAAA,CAAA,MAAA,EAAA,CAAA;;AAEA,MAAA,IAAA,WAAA,EAAA,IAAA,KAAA,OAAA,CAAA,IAAA,EAAA;AACA,QAAA,WAAA,CAAA,KAAA,GAAA,SAAA;AACA;;AAEA;AACA,MAAA,QAAA,CAAA,aAAA,CAAA;AACA,QAAA,CAAA,eAAA,GAAA,SAAA;AACA,QAAA,CAAA,gCAAA,GAAA,OAAA;AACA,QAAA,CAAA,gCAAA,GAAA,wCAAA;AACA,OAAA,CAAA;AACA;;AAEA,IAAA,IAAA;AACA,MAAA,OAAA,MAAA,cAAA,CAAA,OAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,aAAA,EAAA,WAAA,CAAA;AACA,KAAA,SAAA;AACA,MAAA,MAAA,iBAAA,EAAA;AACA;AACA,GAAA;AACA;;AAEA;AACA;AACA,MAAA,mBAAA,GAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,qBAAA,CAAA,IAAA,EAAA;AACA,EAAA,MAAA,cAAA,GAAA,SAAA;AACA,EAAA,MAAA,sBAAA,GAAA,IAAA,SAAA,CAAA;AACA,IAAA,SAAA,CAAA,KAAA,EAAA,SAAA,EAAA,QAAA,EAAA;AACA,MAAA,MAAA,IAAA,GAAA,MAAA,CAAA,QAAA,CAAA,KAAA,CAAA,GAAA,KAAA,CAAA,QAAA,EAAA,GAAA,MAAA,CAAA,KAAA,CAAA;AACA,MAAA,IAAA,IAAA,CAAA,QAAA,CAAA,cAAA,CAAA,EAAA;AACA,QAAA,MAAA,YAAA,GAAA,IAAA,CAAA,OAAA,CAAA,cAAA,EAAA,CAAA,EAAA,gBAAA,EAAA,CAAA,EAAA,cAAA,CAAA,CAAA,CAAA;AACA,QAAA,QAAA,CAAA,IAAA,EAAA,YAAA,CAAA;AACA,QAAA;AACA;AACA,MAAA,QAAA,CAAA,IAAA,EAAA,KAAA,CAAA;AACA,KAAA;AACA,GAAA,CAAA;AACA,EAAA,sBAAA,CAAA,IAAA,CAAA,IAAA,CAAA;AACA,EAAA,OAAA,sBAAA;AACA;;;;"}
1
+ {"version":3,"file":"wrapSentryHandleRequest.js","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"sourcesContent":["import { context } from '@opentelemetry/api';\nimport { getRPCMetadata, RPCType } from '@opentelemetry/core';\nimport { ATTR_HTTP_ROUTE } from '@opentelemetry/semantic-conventions';\nimport {\n flushIfServerless,\n getActiveSpan,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n} from '@sentry/core';\nimport type { AppLoadContext, EntryContext } from 'react-router';\n\ntype OriginalHandleRequest = (\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\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(originalHandle: OriginalHandleRequest): OriginalHandleRequest {\n return async function sentryInstrumentedHandleRequest(\n request: Request,\n responseStatusCode: number,\n responseHeaders: Headers,\n routerContext: EntryContext,\n loadContext: AppLoadContext,\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 const routeName = `/${parameterizedPath}`;\n\n // The express instrumentation writes on the rpcMetadata and that ends up stomping on the `http.route` attribute.\n const rpcMetadata = getRPCMetadata(context.active());\n\n if (rpcMetadata?.type === RPCType.HTTP) {\n rpcMetadata.route = routeName;\n }\n\n // The span exporter picks up the `http.route` (ATTR_HTTP_ROUTE) attribute to set the transaction name\n rootSpan.setAttributes({\n [ATTR_HTTP_ROUTE]: routeName,\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.react-router.request-handler',\n });\n }\n\n try {\n return await originalHandle(request, responseStatusCode, responseHeaders, routerContext, loadContext);\n } finally {\n await flushIfServerless();\n }\n };\n}\n\n// todo(v11): remove this\n/** @deprecated Use `wrapSentryHandleRequest` instead. */\nexport const sentryHandleRequest = wrapSentryHandleRequest;\n"],"names":[],"mappings":";;;;;AAoBA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,uBAAuB,CAAC,cAAc,EAAgD;AACtG,EAAE,OAAO,eAAe,+BAA+B;AACvD,IAAI,OAAO;AACX,IAAI,kBAAkB;AACtB,IAAI,eAAe;AACnB,IAAI,aAAa;AACjB,IAAI,WAAW;AACf,IAAI;AACJ,IAAI,MAAM,iBAAA;AACV,MAAM,aAAa,EAAE,oBAAoB,EAAE,OAAO,GAAG,aAAa,CAAC,oBAAoB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI;;AAEvH,IAAI,MAAM,UAAA,GAAa,aAAa,EAAE;AACtC,IAAI,MAAM,QAAA,GAAW,UAAA,GAAa,WAAW,CAAC,UAAU,CAAA,GAAI,SAAS;;AAErE,IAAI,IAAI,iBAAA,IAAqB,QAAQ,EAAE;AACvC,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAA;;AAEA;AACA,MAAA,MAAA,WAAA,GAAA,cAAA,CAAA,OAAA,CAAA,MAAA,EAAA,CAAA;;AAEA,MAAA,IAAA,WAAA,EAAA,IAAA,KAAA,OAAA,CAAA,IAAA,EAAA;AACA,QAAA,WAAA,CAAA,KAAA,GAAA,SAAA;AACA;;AAEA;AACA,MAAA,QAAA,CAAA,aAAA,CAAA;AACA,QAAA,CAAA,eAAA,GAAA,SAAA;AACA,QAAA,CAAA,gCAAA,GAAA,OAAA;AACA,QAAA,CAAA,gCAAA,GAAA,wCAAA;AACA,OAAA,CAAA;AACA;;AAEA,IAAA,IAAA;AACA,MAAA,OAAA,MAAA,cAAA,CAAA,OAAA,EAAA,kBAAA,EAAA,eAAA,EAAA,aAAA,EAAA,WAAA,CAAA;AACA,KAAA,SAAA;AACA,MAAA,MAAA,iBAAA,EAAA;AACA;AACA,GAAA;AACA;;AAEA;AACA;AACA,MAAA,mBAAA,GAAA;;;;"}
@@ -55,7 +55,10 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
55
55
  if (sourceMapsUploadOptions?.enabled ?? (viteConfig.build.sourcemap !== false)) {
56
56
  // inject debugIds
57
57
  try {
58
- await cliInstance.execute(['sourcemaps', 'inject', reactRouterConfig.buildDirectory], debug);
58
+ await cliInstance.execute(
59
+ ['sourcemaps', 'inject', reactRouterConfig.buildDirectory],
60
+ debug ? 'rejectOnError' : false,
61
+ );
59
62
  } catch (error) {
60
63
  // eslint-disable-next-line no-console
61
64
  console.error('[Sentry] Could not inject debug ids', error);
@@ -69,6 +72,7 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
69
72
  paths: [reactRouterConfig.buildDirectory],
70
73
  },
71
74
  ],
75
+ live: 'rejectOnError',
72
76
  });
73
77
  } catch (error) {
74
78
  // eslint-disable-next-line no-console
@@ -80,14 +84,13 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
80
84
  // set a default value no option was set
81
85
  if (typeof sourceMapsUploadOptions?.filesToDeleteAfterUpload === 'undefined') {
82
86
  updatedFilesToDeleteAfterUpload = [`${reactRouterConfig.buildDirectory}/**/*.map`];
83
- if (debug) {
87
+ debug &&
84
88
  // eslint-disable-next-line no-console
85
89
  console.info(
86
90
  `[Sentry] Automatically setting \`sourceMapsUploadOptions.filesToDeleteAfterUpload: ${JSON.stringify(
87
91
  updatedFilesToDeleteAfterUpload,
88
92
  )}\` to delete generated source maps after they were uploaded to Sentry.`,
89
93
  );
90
- }
91
94
  }
92
95
  if (updatedFilesToDeleteAfterUpload) {
93
96
  try {
@@ -104,11 +107,10 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
104
107
  await Promise.all(
105
108
  filePathsToDelete.map(filePathToDelete =>
106
109
  rm(filePathToDelete, { force: true }).catch((e) => {
107
- if (debug) {
108
- // This is allowed to fail - we just don't do anything
110
+ // This is allowed to fail - we just don't do anything
111
+ debug &&
109
112
  // eslint-disable-next-line no-console
110
113
  console.debug(`An error occurred while attempting to delete asset: ${filePathToDelete}`, e);
111
- }
112
114
  }),
113
115
  ),
114
116
  );
@@ -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 { 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 * 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 org,\n project,\n release,\n sourceMapsUploadOptions = { enabled: true },\n debug = false,\n unstable_sentryVitePluginOptions,\n }: SentryReactRouterBuildOptions = {\n ...sentryConfig.unstable_sentryVitePluginOptions,\n ...sentryConfig,\n release: {\n ...sentryConfig.unstable_sentryVitePluginOptions?.release,\n ...sentryConfig.release,\n },\n };\n\n const cliInstance = new SentryCli(null, {\n authToken,\n org,\n project,\n ...unstable_sentryVitePluginOptions,\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 if (sourceMapsUploadOptions?.enabled ?? (true && viteConfig.build.sourcemap !== false)) {\n // inject debugIds\n try {\n await cliInstance.execute(['sourcemaps', 'inject', reactRouterConfig.buildDirectory], debug);\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not inject debug ids', error);\n }\n\n // upload sourcemaps\n try {\n await cliInstance.releases.uploadSourceMaps(release?.name || 'undefined', {\n include: [\n {\n paths: [reactRouterConfig.buildDirectory],\n },\n ],\n });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('[Sentry] Could not upload sourcemaps', error);\n }\n }\n // delete sourcemaps after upload\n let updatedFilesToDeleteAfterUpload = sourceMapsUploadOptions?.filesToDeleteAfterUpload;\n // set a default value no option was set\n if (typeof sourceMapsUploadOptions?.filesToDeleteAfterUpload === 'undefined') {\n updatedFilesToDeleteAfterUpload = [`${reactRouterConfig.buildDirectory}/**/*.map`];\n if (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 }\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 if (debug) {\n // This is allowed to fail - we just don't do anything\n // eslint-disable-next-line no-console\n console.debug(`An error occurred while attempting to delete asset: ${filePathToDelete}`, e);\n }\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":[],"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 SentryCli from '@sentry/cli';\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 * 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 org,\n project,\n release,\n sourceMapsUploadOptions = { enabled: true },\n debug = false,\n unstable_sentryVitePluginOptions,\n }: SentryReactRouterBuildOptions = {\n ...sentryConfig.unstable_sentryVitePluginOptions,\n ...sentryConfig,\n release: {\n ...sentryConfig.unstable_sentryVitePluginOptions?.release,\n ...sentryConfig.release,\n },\n };\n\n const cliInstance = new SentryCli(null, {\n authToken,\n org,\n project,\n ...unstable_sentryVitePluginOptions,\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 if (sourceMapsUploadOptions?.enabled ?? (true && 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 // 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 // delete sourcemaps after upload\n let updatedFilesToDeleteAfterUpload = sourceMapsUploadOptions?.filesToDeleteAfterUpload;\n // set a default value no option was set\n if (typeof sourceMapsUploadOptions?.filesToDeleteAfterUpload === '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":[],"mappings":"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"}
@@ -1,5 +1,3 @@
1
- import { consoleSandbox } from '@sentry/core';
2
-
3
1
  /**
4
2
  * A Sentry plugin for React Router to enable "hidden" source maps if they are unset.
5
3
  */
@@ -45,36 +43,35 @@ function getUpdatedSourceMapSettings(
45
43
  let updatedSourceMapSetting = viteSourceMap;
46
44
 
47
45
  const settingKey = 'vite.build.sourcemap';
46
+ const debug = sentryPluginOptions?.debug;
48
47
 
49
48
  if (viteSourceMap === false) {
50
49
  updatedSourceMapSetting = viteSourceMap;
51
50
 
52
- consoleSandbox(() => {
53
- // eslint-disable-next-line no-console
51
+ if (debug) {
52
+ // Longer debug message with more details
53
+ // eslint-disable-next-line no-console
54
54
  console.warn(
55
55
  `[Sentry] Source map generation is currently disabled in your Vite configuration (\`${settingKey}: false \`). This setting is either a default setting or was explicitly set in your configuration. Sentry won't override this setting. Without source maps, code snippets on the Sentry Issues page will remain minified. To show unminified code, enable source maps in \`${settingKey}\` (e.g. by setting them to \`hidden\`).`,
56
56
  );
57
- });
57
+ } else {
58
+ // eslint-disable-next-line no-console
59
+ console.warn('[Sentry] Source map generation is disabled in your Vite configuration.');
60
+ }
58
61
  } else if (viteSourceMap && ['hidden', 'inline', true].includes(viteSourceMap)) {
59
62
  updatedSourceMapSetting = viteSourceMap;
60
63
 
61
- if (sentryPluginOptions?.debug) {
62
- consoleSandbox(() => {
63
- // eslint-disable-next-line no-console
64
- console.log(
65
- `[Sentry] We discovered \`${settingKey}\` is set to \`${viteSourceMap.toString()}\`. Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.`,
66
- );
67
- });
68
- }
64
+ debug &&
65
+ // eslint-disable-next-line no-console
66
+ console.log(
67
+ `[Sentry] We discovered \`${settingKey}\` is set to \`${viteSourceMap.toString()}\`. Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.`,
68
+ );
69
69
  } else {
70
70
  updatedSourceMapSetting = 'hidden';
71
-
72
- consoleSandbox(() => {
73
- // eslint-disable-next-line no-console
71
+ debug && // eslint-disable-next-line no-console
74
72
  console.log(
75
73
  `[Sentry] Enabled source map generation in the build options with \`${settingKey}: 'hidden'\`. The source maps will be deleted after they were uploaded to Sentry.`,
76
74
  );
77
- });
78
75
  }
79
76
 
80
77
  return updatedSourceMapSetting;
@@ -1 +1 @@
1
- {"version":3,"file":"makeEnableSourceMapsPlugin.js","sources":["../../../src/vite/makeEnableSourceMapsPlugin.ts"],"sourcesContent":["import { consoleSandbox } from '@sentry/core';\nimport type { Plugin, UserConfig } from 'vite';\nimport type { SentryReactRouterBuildOptions } from './types';\n\n/**\n * A Sentry plugin for React Router to enable \"hidden\" source maps if they are unset.\n */\nexport function makeEnableSourceMapsPlugin(options: SentryReactRouterBuildOptions): Plugin {\n return {\n name: 'sentry-react-router-update-source-map-setting',\n apply: 'build',\n enforce: 'post',\n config(viteConfig) {\n return {\n ...viteConfig,\n build: {\n ...viteConfig.build,\n sourcemap: getUpdatedSourceMapSettings(viteConfig, options),\n },\n };\n },\n };\n}\n\n/** There are 3 ways to set up source map generation\n *\n * 1. User explicitly disabled source maps\n * - keep this setting (emit a warning that errors won't be unminified in Sentry)\n * - we won't upload anything\n *\n * 2. Users enabled source map generation (true, 'hidden', 'inline').\n * - keep this setting (don't do anything - like deletion - besides uploading)\n *\n * 3. Users didn't set source maps generation\n * - we enable 'hidden' source maps generation\n * - configure `filesToDeleteAfterUpload` to delete all .map files (we emit a log about this)\n *\n * --> only exported for testing\n */\nexport function getUpdatedSourceMapSettings(\n viteConfig: UserConfig,\n sentryPluginOptions?: SentryReactRouterBuildOptions,\n): boolean | 'inline' | 'hidden' {\n viteConfig.build = viteConfig.build || {};\n\n const viteSourceMap = viteConfig?.build?.sourcemap;\n let updatedSourceMapSetting = viteSourceMap;\n\n const settingKey = 'vite.build.sourcemap';\n\n if (viteSourceMap === false) {\n updatedSourceMapSetting = viteSourceMap;\n\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] Source map generation is currently disabled in your Vite configuration (\\`${settingKey}: false \\`). This setting is either a default setting or was explicitly set in your configuration. Sentry won't override this setting. Without source maps, code snippets on the Sentry Issues page will remain minified. To show unminified code, enable source maps in \\`${settingKey}\\` (e.g. by setting them to \\`hidden\\`).`,\n );\n });\n } else if (viteSourceMap && ['hidden', 'inline', true].includes(viteSourceMap)) {\n updatedSourceMapSetting = viteSourceMap;\n\n if (sentryPluginOptions?.debug) {\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.log(\n `[Sentry] We discovered \\`${settingKey}\\` is set to \\`${viteSourceMap.toString()}\\`. Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.`,\n );\n });\n }\n } else {\n updatedSourceMapSetting = 'hidden';\n\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.log(\n `[Sentry] Enabled source map generation in the build options with \\`${settingKey}: 'hidden'\\`. The source maps will be deleted after they were uploaded to Sentry.`,\n );\n });\n }\n\n return updatedSourceMapSetting;\n}\n"],"names":[],"mappings":";;AAIA;AACA;AACA;AACO,SAAS,0BAA0B,CAAC,OAAO,EAAyC;AAC3F,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,+CAA+C;AACzD,IAAI,KAAK,EAAE,OAAO;AAClB,IAAI,OAAO,EAAE,MAAM;AACnB,IAAI,MAAM,CAAC,UAAU,EAAE;AACvB,MAAM,OAAO;AACb,QAAQ,GAAG,UAAU;AACrB,QAAQ,KAAK,EAAE;AACf,UAAU,GAAG,UAAU,CAAC,KAAK;AAC7B,UAAU,SAAS,EAAE,2BAA2B,CAAC,UAAU,EAAE,OAAO,CAAC;AACrE,SAAS;AACT,OAAO;AACP,KAAK;AACL,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,2BAA2B;AAC3C,EAAE,UAAU;AACZ,EAAE,mBAAmB;AACrB,EAAiC;AACjC,EAAE,UAAU,CAAC,KAAA,GAAQ,UAAU,CAAC,KAAA,IAAS,EAAE;;AAE3C,EAAE,MAAM,aAAA,GAAgB,UAAU,EAAE,KAAK,EAAE,SAAS;AACpD,EAAE,IAAI,uBAAA,GAA0B,aAAa;;AAE7C,EAAE,MAAM,UAAA,GAAa,sBAAsB;;AAE3C,EAAE,IAAI,aAAA,KAAkB,KAAK,EAAE;AAC/B,IAAI,uBAAA,GAA0B,aAAa;;AAE3C,IAAI,cAAc,CAAC,MAAM;AACzB;AACA,MAAM,OAAO,CAAC,IAAI;AAClB,QAAQ,CAAC,mFAAmF,EAAE,UAAU,CAAC,2QAA2Q,EAAE,UAAU,CAAC,wCAAwC,CAAC;AAC1a,OAAO;AACP,KAAK,CAAC;AACN,SAAS,IAAI,aAAA,IAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE;AAClF,IAAI,uBAAA,GAA0B,aAAa;;AAE3C,IAAI,IAAI,mBAAmB,EAAE,KAAK,EAAE;AACpC,MAAM,cAAc,CAAC,MAAM;AAC3B;AACA,QAAQ,OAAO,CAAC,GAAG;AACnB,UAAU,CAAC,yBAAyB,EAAE,UAAU,CAAC,eAAe,EAAE,aAAa,CAAC,QAAQ,EAAE,CAAC,4GAA4G,CAAC;AACxM,SAAS;AACT,OAAO,CAAC;AACR;AACA,SAAS;AACT,IAAI,uBAAA,GAA0B,QAAQ;;AAEtC,IAAI,cAAc,CAAC,MAAM;AACzB;AACA,MAAM,OAAO,CAAC,GAAG;AACjB,QAAQ,CAAC,mEAAmE,EAAE,UAAU,CAAC,kFAAkF,CAAC;AAC5K,OAAO;AACP,KAAK,CAAC;AACN;;AAEA,EAAE,OAAO,uBAAuB;AAChC;;;;"}
1
+ {"version":3,"file":"makeEnableSourceMapsPlugin.js","sources":["../../../src/vite/makeEnableSourceMapsPlugin.ts"],"sourcesContent":["import type { Plugin, UserConfig } from 'vite';\nimport type { SentryReactRouterBuildOptions } from './types';\n\n/**\n * A Sentry plugin for React Router to enable \"hidden\" source maps if they are unset.\n */\nexport function makeEnableSourceMapsPlugin(options: SentryReactRouterBuildOptions): Plugin {\n return {\n name: 'sentry-react-router-update-source-map-setting',\n apply: 'build',\n enforce: 'post',\n config(viteConfig) {\n return {\n ...viteConfig,\n build: {\n ...viteConfig.build,\n sourcemap: getUpdatedSourceMapSettings(viteConfig, options),\n },\n };\n },\n };\n}\n\n/** There are 3 ways to set up source map generation\n *\n * 1. User explicitly disabled source maps\n * - keep this setting (emit a warning that errors won't be unminified in Sentry)\n * - we won't upload anything\n *\n * 2. Users enabled source map generation (true, 'hidden', 'inline').\n * - keep this setting (don't do anything - like deletion - besides uploading)\n *\n * 3. Users didn't set source maps generation\n * - we enable 'hidden' source maps generation\n * - configure `filesToDeleteAfterUpload` to delete all .map files (we emit a log about this)\n *\n * --> only exported for testing\n */\nexport function getUpdatedSourceMapSettings(\n viteConfig: UserConfig,\n sentryPluginOptions?: SentryReactRouterBuildOptions,\n): boolean | 'inline' | 'hidden' {\n viteConfig.build = viteConfig.build || {};\n\n const viteSourceMap = viteConfig?.build?.sourcemap;\n let updatedSourceMapSetting = viteSourceMap;\n\n const settingKey = 'vite.build.sourcemap';\n const debug = sentryPluginOptions?.debug;\n\n if (viteSourceMap === false) {\n updatedSourceMapSetting = viteSourceMap;\n\n if (debug) {\n // Longer debug message with more details\n // eslint-disable-next-line no-console\n console.warn(\n `[Sentry] Source map generation is currently disabled in your Vite configuration (\\`${settingKey}: false \\`). This setting is either a default setting or was explicitly set in your configuration. Sentry won't override this setting. Without source maps, code snippets on the Sentry Issues page will remain minified. To show unminified code, enable source maps in \\`${settingKey}\\` (e.g. by setting them to \\`hidden\\`).`,\n );\n } else {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Source map generation is disabled in your Vite configuration.');\n }\n } else if (viteSourceMap && ['hidden', 'inline', true].includes(viteSourceMap)) {\n updatedSourceMapSetting = viteSourceMap;\n\n debug &&\n // eslint-disable-next-line no-console\n console.log(\n `[Sentry] We discovered \\`${settingKey}\\` is set to \\`${viteSourceMap.toString()}\\`. Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.`,\n );\n } else {\n updatedSourceMapSetting = 'hidden';\n debug && // eslint-disable-next-line no-console\n console.log(\n `[Sentry] Enabled source map generation in the build options with \\`${settingKey}: 'hidden'\\`. The source maps will be deleted after they were uploaded to Sentry.`,\n );\n }\n\n return updatedSourceMapSetting;\n}\n"],"names":[],"mappings":"AAGA;AACA;AACA;AACO,SAAS,0BAA0B,CAAC,OAAO,EAAyC;AAC3F,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,+CAA+C;AACzD,IAAI,KAAK,EAAE,OAAO;AAClB,IAAI,OAAO,EAAE,MAAM;AACnB,IAAI,MAAM,CAAC,UAAU,EAAE;AACvB,MAAM,OAAO;AACb,QAAQ,GAAG,UAAU;AACrB,QAAQ,KAAK,EAAE;AACf,UAAU,GAAG,UAAU,CAAC,KAAK;AAC7B,UAAU,SAAS,EAAE,2BAA2B,CAAC,UAAU,EAAE,OAAO,CAAC;AACrE,SAAS;AACT,OAAO;AACP,KAAK;AACL,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,2BAA2B;AAC3C,EAAE,UAAU;AACZ,EAAE,mBAAmB;AACrB,EAAiC;AACjC,EAAE,UAAU,CAAC,KAAA,GAAQ,UAAU,CAAC,KAAA,IAAS,EAAE;;AAE3C,EAAE,MAAM,aAAA,GAAgB,UAAU,EAAE,KAAK,EAAE,SAAS;AACpD,EAAE,IAAI,uBAAA,GAA0B,aAAa;;AAE7C,EAAE,MAAM,UAAA,GAAa,sBAAsB;AAC3C,EAAE,MAAM,KAAA,GAAQ,mBAAmB,EAAE,KAAK;;AAE1C,EAAE,IAAI,aAAA,KAAkB,KAAK,EAAE;AAC/B,IAAI,uBAAA,GAA0B,aAAa;;AAE3C,IAAI,IAAI,KAAK,EAAE;AACf;AACA;AACA,MAAM,OAAO,CAAC,IAAI;AAClB,QAAQ,CAAC,mFAAmF,EAAE,UAAU,CAAC,2QAA2Q,EAAE,UAAU,CAAC,wCAAwC,CAAC;AAC1a,OAAO;AACP,WAAW;AACX;AACA,MAAM,OAAO,CAAC,IAAI,CAAC,wEAAwE,CAAC;AAC5F;AACA,SAAS,IAAI,aAAA,IAAiB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE;AAClF,IAAI,uBAAA,GAA0B,aAAa;;AAE3C,IAAI,KAAA;AACJ;AACA,MAAM,OAAO,CAAC,GAAG;AACjB,QAAQ,CAAC,yBAAyB,EAAE,UAAU,CAAC,eAAe,EAAE,aAAa,CAAC,QAAQ,EAAE,CAAC,4GAA4G,CAAC;AACtM,OAAO;AACP,SAAS;AACT,IAAI,uBAAA,GAA0B,QAAQ;AACtC,IAAI,KAAA;AACJ,MAAM,OAAO,CAAC,GAAG;AACjB,QAAQ,CAAC,mEAAmE,EAAE,UAAU,CAAC,kFAAkF,CAAC;AAC5K,OAAO;AACP;;AAEA,EAAE,OAAO,uBAAuB;AAChC;;;;"}
@@ -0,0 +1,10 @@
1
+ export * from '../client';
2
+ export { wrapSentryHandleRequest } from '../server/wrapSentryHandleRequest';
3
+ /**
4
+ * Injects Sentry trace meta tags into the HTML response by transforming the ReadableStream.
5
+ * This enables distributed tracing by adding trace context to the HTML document head.
6
+ * @param body - ReadableStream containing the HTML response body to modify
7
+ * @returns A new ReadableStream with Sentry trace meta tags injected into the head section
8
+ */
9
+ export declare function injectTraceMetaTags(body: ReadableStream): ReadableStream;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cloudflare/index.ts"],"names":[],"mappings":"AAEA,cAAc,WAAW,CAAC;AAE1B,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAE5E;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,GAAG,cAAc,CA4BxE"}
@@ -1 +1 @@
1
- {"version":3,"file":"createSentryHandleRequest.d.ts","sourceRoot":"","sources":["../../../src/server/createSentryHandleRequest.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAI/E,KAAK,6BAA6B,GAAG;IACnC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC,CAAC;AAEF,KAAK,4BAA4B,GAAG;IAClC,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,cAAc,KAAK,IAAI,CAAC;IACnD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,KAAK,8BAA8B,GAAG,CACpC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,6BAA6B,KACnC,4BAA4B,CAAC;AAElC,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,sBAAsB,EAAE,8BAA8B,CAAC;IAEvD;;OAEG;IACH,YAAY,EAAE,OAAO,YAAY,CAAC;IAElC;;OAEG;IACH,gCAAgC,EAAE,OAAO,gCAAgC,CAAC;IAE1E;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,CACD,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,MAAM,EAC1B,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,YAAY,EAC3B,WAAW,EAAE,cAAc,KACxB,OAAO,CAAC,OAAO,CAAC,CAoEpB"}
1
+ {"version":3,"file":"createSentryHandleRequest.d.ts","sourceRoot":"","sources":["../../../src/server/createSentryHandleRequest.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,gCAAgC,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAK/E,KAAK,6BAA6B,GAAG;IACnC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC,CAAC;AAEF,KAAK,4BAA4B,GAAG;IAClC,IAAI,EAAE,CAAC,WAAW,EAAE,MAAM,CAAC,cAAc,KAAK,IAAI,CAAC;IACnD,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,KAAK,8BAA8B,GAAG,CACpC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,6BAA6B,KACnC,4BAA4B,CAAC;AAElC,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,sBAAsB,EAAE,8BAA8B,CAAC;IAEvD;;OAEG;IACH,YAAY,EAAE,OAAO,YAAY,CAAC;IAElC;;OAEG;IACH,gCAAgC,EAAE,OAAO,gCAAgC,CAAC;IAE1E;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,CACD,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,MAAM,EAC1B,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,YAAY,EAC3B,WAAW,EAAE,cAAc,KACxB,OAAO,CAAC,OAAO,CAAC,CAoEpB"}
@@ -0,0 +1,11 @@
1
+ /// <reference types="node" />
2
+ import type { PassThrough } from 'node:stream';
3
+ import { Transform } from 'node:stream';
4
+ /**
5
+ * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.
6
+ * This enables distributed tracing by adding trace context to the HTML document head.
7
+ *
8
+ * @param body - PassThrough stream containing the HTML response body to modify
9
+ */
10
+ export declare function getMetaTagTransformer(body: PassThrough): Transform;
11
+ //# sourceMappingURL=getMetaTagTransformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getMetaTagTransformer.d.ts","sourceRoot":"","sources":["../../../src/server/getMetaTagTransformer.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAelE"}
@@ -1,8 +1,9 @@
1
1
  export * from '@sentry/node';
2
2
  export { init } from './sdk';
3
- export { wrapSentryHandleRequest, sentryHandleRequest, getMetaTagTransformer } from './wrapSentryHandleRequest';
3
+ export { wrapSentryHandleRequest, sentryHandleRequest } from './wrapSentryHandleRequest';
4
4
  export { createSentryHandleRequest, type SentryHandleRequestOptions } from './createSentryHandleRequest';
5
5
  export { wrapServerAction } from './wrapServerAction';
6
6
  export { wrapServerLoader } from './wrapServerLoader';
7
7
  export { createSentryHandleError, type SentryHandleErrorOptions } from './createSentryHandleError';
8
+ export { getMetaTagTransformer } from './getMetaTagTransformer';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAE7B,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAE7B,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAChH,OAAO,EAAE,yBAAyB,EAAE,KAAK,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzG,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,KAAK,wBAAwB,EAAE,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAE7B,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAE7B,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACzF,OAAO,EAAE,yBAAyB,EAAE,KAAK,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzG,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,KAAK,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACnG,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -1,7 +1,4 @@
1
- /// <reference types="node" />
2
1
  import type { AppLoadContext, EntryContext } from 'react-router';
3
- import type { PassThrough } from 'stream';
4
- import { Transform } from 'stream';
5
2
  type OriginalHandleRequest = (request: Request, responseStatusCode: number, responseHeaders: Headers, routerContext: EntryContext, loadContext: AppLoadContext) => Promise<unknown>;
6
3
  /**
7
4
  * Wraps the original handleRequest function to add Sentry instrumentation.
@@ -12,12 +9,5 @@ type OriginalHandleRequest = (request: Request, responseStatusCode: number, resp
12
9
  export declare function wrapSentryHandleRequest(originalHandle: OriginalHandleRequest): OriginalHandleRequest;
13
10
  /** @deprecated Use `wrapSentryHandleRequest` instead. */
14
11
  export declare const sentryHandleRequest: typeof wrapSentryHandleRequest;
15
- /**
16
- * Injects Sentry trace meta tags into the HTML response by piping through a transform stream.
17
- * This enables distributed tracing by adding trace context to the HTML document head.
18
- *
19
- * @param body - PassThrough stream containing the HTML response body to modify
20
- */
21
- export declare function getMetaTagTransformer(body: PassThrough): Transform;
22
12
  export {};
23
13
  //# sourceMappingURL=wrapSentryHandleRequest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wrapSentryHandleRequest.d.ts","sourceRoot":"","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"names":[],"mappings":";AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC,KAAK,qBAAqB,GAAG,CAC3B,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,MAAM,EAC1B,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,YAAY,EAC3B,WAAW,EAAE,cAAc,KACxB,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,qBAAqB,GAAG,qBAAqB,CAsCpG;AAGD,yDAAyD;AACzD,eAAO,MAAM,mBAAmB,gCAA0B,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAelE"}
1
+ {"version":3,"file":"wrapSentryHandleRequest.d.ts","sourceRoot":"","sources":["../../../src/server/wrapSentryHandleRequest.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjE,KAAK,qBAAqB,GAAG,CAC3B,OAAO,EAAE,OAAO,EAChB,kBAAkB,EAAE,MAAM,EAC1B,eAAe,EAAE,OAAO,EACxB,aAAa,EAAE,YAAY,EAC3B,WAAW,EAAE,cAAc,KACxB,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtB;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,cAAc,EAAE,qBAAqB,GAAG,qBAAqB,CAsCpG;AAGD,yDAAyD;AACzD,eAAO,MAAM,mBAAmB,gCAA0B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"handleOnBuildEnd.d.ts","sourceRoot":"","sources":["../../../../src/vite/buildEnd/handleOnBuildEnd.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAKvD,KAAK,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;AAWpD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,YAqG9B,CAAC"}
1
+ {"version":3,"file":"handleOnBuildEnd.d.ts","sourceRoot":"","sources":["../../../../src/vite/buildEnd/handleOnBuildEnd.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAKvD,KAAK,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;AAWpD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,EAAE,YAuG9B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"makeEnableSourceMapsPlugin.d.ts","sourceRoot":"","sources":["../../../src/vite/makeEnableSourceMapsPlugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAC/C,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAC;AAE7D;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,6BAA6B,GAAG,MAAM,CAezF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,UAAU,EACtB,mBAAmB,CAAC,EAAE,6BAA6B,GAClD,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAwC/B"}
1
+ {"version":3,"file":"makeEnableSourceMapsPlugin.d.ts","sourceRoot":"","sources":["../../../src/vite/makeEnableSourceMapsPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAC/C,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,SAAS,CAAC;AAE7D;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,6BAA6B,GAAG,MAAM,CAezF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,UAAU,EACtB,mBAAmB,CAAC,EAAE,6BAA6B,GAClD,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAuC/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/react-router",
3
- "version": "10.1.0",
3
+ "version": "10.3.0",
4
4
  "description": "Official Sentry SDK for React Router (Framework)",
5
5
  "repository": "git://github.com/getsentry/sentry-javascript.git",
6
6
  "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/react-router",
@@ -27,7 +27,18 @@
27
27
  "node": {
28
28
  "import": "./build/esm/index.server.js",
29
29
  "require": "./build/cjs/index.server.js"
30
+ },
31
+ "worker": {
32
+ "import": "./build/esm/cloudflare/index.js",
33
+ "require": "./build/cjs/cloudflare/index.js",
34
+ "default": "./build/esm/cloudflare/index.js"
30
35
  }
36
+ },
37
+ "./cloudflare": {
38
+ "import": "./build/esm/cloudflare/index.js",
39
+ "require": "./build/cjs/cloudflare/index.js",
40
+ "types": "./build/types/cloudflare/index.d.ts",
41
+ "default": "./build/esm/cloudflare/index.js"
31
42
  }
32
43
  },
33
44
  "publishConfig": {
@@ -38,11 +49,11 @@
38
49
  "@opentelemetry/core": "^2.0.0",
39
50
  "@opentelemetry/instrumentation": "^0.203.0",
40
51
  "@opentelemetry/semantic-conventions": "^1.34.0",
41
- "@sentry/browser": "10.1.0",
42
- "@sentry/cli": "^2.46.0",
43
- "@sentry/core": "10.1.0",
44
- "@sentry/node": "10.1.0",
45
- "@sentry/react": "10.1.0",
52
+ "@sentry/browser": "10.3.0",
53
+ "@sentry/cli": "^2.50.2",
54
+ "@sentry/core": "10.3.0",
55
+ "@sentry/node": "10.3.0",
56
+ "@sentry/react": "10.3.0",
46
57
  "@sentry/vite-plugin": "^4.0.0",
47
58
  "glob": "11.0.1"
48
59
  },