@sentry/react-router 10.0.0 → 10.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/cloudflare/index.js +67 -0
- package/build/cjs/cloudflare/index.js.map +1 -0
- package/build/cjs/index.server.js +2 -1
- package/build/cjs/index.server.js.map +1 -1
- package/build/cjs/server/createSentryHandleRequest.js +2 -1
- package/build/cjs/server/createSentryHandleRequest.js.map +1 -1
- package/build/cjs/server/getMetaTagTransformer.js +30 -0
- package/build/cjs/server/getMetaTagTransformer.js.map +1 -0
- package/build/cjs/server/wrapSentryHandleRequest.js +0 -25
- package/build/cjs/server/wrapSentryHandleRequest.js.map +1 -1
- package/build/cjs/vite/buildEnd/handleOnBuildEnd.js +3 -5
- package/build/cjs/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
- package/build/cjs/vite/makeEnableSourceMapsPlugin.js +14 -17
- package/build/cjs/vite/makeEnableSourceMapsPlugin.js.map +1 -1
- package/build/esm/cloudflare/index.js +45 -0
- package/build/esm/cloudflare/index.js.map +1 -0
- package/build/esm/index.server.js +2 -1
- package/build/esm/index.server.js.map +1 -1
- package/build/esm/package.json +1 -1
- package/build/esm/server/createSentryHandleRequest.js +2 -1
- package/build/esm/server/createSentryHandleRequest.js.map +1 -1
- package/build/esm/server/getMetaTagTransformer.js +28 -0
- package/build/esm/server/getMetaTagTransformer.js.map +1 -0
- package/build/esm/server/wrapSentryHandleRequest.js +2 -26
- package/build/esm/server/wrapSentryHandleRequest.js.map +1 -1
- package/build/esm/vite/buildEnd/handleOnBuildEnd.js +3 -5
- package/build/esm/vite/buildEnd/handleOnBuildEnd.js.map +1 -1
- package/build/esm/vite/makeEnableSourceMapsPlugin.js +14 -17
- package/build/esm/vite/makeEnableSourceMapsPlugin.js.map +1 -1
- package/build/types/cloudflare/index.d.ts +10 -0
- package/build/types/cloudflare/index.d.ts.map +1 -0
- package/build/types/server/createSentryHandleRequest.d.ts.map +1 -1
- package/build/types/server/getMetaTagTransformer.d.ts +11 -0
- package/build/types/server/getMetaTagTransformer.d.ts.map +1 -0
- package/build/types/server/index.d.ts +2 -1
- package/build/types/server/index.d.ts.map +1 -1
- package/build/types/server/wrapSentryHandleRequest.d.ts +0 -10
- package/build/types/server/wrapSentryHandleRequest.d.ts.map +1 -1
- package/build/types/vite/buildEnd/handleOnBuildEnd.d.ts.map +1 -1
- package/build/types/vite/makeEnableSourceMapsPlugin.d.ts.map +1 -1
- 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(
|
|
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
|
|
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
|
|
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;;;;;"}
|
|
@@ -82,14 +82,13 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
|
|
|
82
82
|
// set a default value no option was set
|
|
83
83
|
if (typeof sourceMapsUploadOptions?.filesToDeleteAfterUpload === 'undefined') {
|
|
84
84
|
updatedFilesToDeleteAfterUpload = [`${reactRouterConfig.buildDirectory}/**/*.map`];
|
|
85
|
-
|
|
85
|
+
debug &&
|
|
86
86
|
// eslint-disable-next-line no-console
|
|
87
87
|
console.info(
|
|
88
88
|
`[Sentry] Automatically setting \`sourceMapsUploadOptions.filesToDeleteAfterUpload: ${JSON.stringify(
|
|
89
89
|
updatedFilesToDeleteAfterUpload,
|
|
90
90
|
)}\` to delete generated source maps after they were uploaded to Sentry.`,
|
|
91
91
|
);
|
|
92
|
-
}
|
|
93
92
|
}
|
|
94
93
|
if (updatedFilesToDeleteAfterUpload) {
|
|
95
94
|
try {
|
|
@@ -106,11 +105,10 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
|
|
|
106
105
|
await Promise.all(
|
|
107
106
|
filePathsToDelete.map(filePathToDelete =>
|
|
108
107
|
promises.rm(filePathToDelete, { force: true }).catch((e) => {
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
// This is allowed to fail - we just don't do anything
|
|
109
|
+
debug &&
|
|
111
110
|
// eslint-disable-next-line no-console
|
|
112
111
|
console.debug(`An error occurred while attempting to delete asset: ${filePathToDelete}`, e);
|
|
113
|
-
}
|
|
114
112
|
}),
|
|
115
113
|
),
|
|
116
114
|
);
|
|
@@ -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
|
|
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 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
|
-
|
|
55
|
-
//
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
|
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 {
|
|
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":";;;;;;;;;;"}
|
package/build/esm/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"10.
|
|
1
|
+
{"type":"module","version":"10.2.0"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { PassThrough } from 'stream';
|
|
3
|
-
import {
|
|
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
|
|
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
|
|
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
|
|
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;;;;"}
|
|
@@ -80,14 +80,13 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
|
|
|
80
80
|
// set a default value no option was set
|
|
81
81
|
if (typeof sourceMapsUploadOptions?.filesToDeleteAfterUpload === 'undefined') {
|
|
82
82
|
updatedFilesToDeleteAfterUpload = [`${reactRouterConfig.buildDirectory}/**/*.map`];
|
|
83
|
-
|
|
83
|
+
debug &&
|
|
84
84
|
// eslint-disable-next-line no-console
|
|
85
85
|
console.info(
|
|
86
86
|
`[Sentry] Automatically setting \`sourceMapsUploadOptions.filesToDeleteAfterUpload: ${JSON.stringify(
|
|
87
87
|
updatedFilesToDeleteAfterUpload,
|
|
88
88
|
)}\` to delete generated source maps after they were uploaded to Sentry.`,
|
|
89
89
|
);
|
|
90
|
-
}
|
|
91
90
|
}
|
|
92
91
|
if (updatedFilesToDeleteAfterUpload) {
|
|
93
92
|
try {
|
|
@@ -104,11 +103,10 @@ const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
|
|
|
104
103
|
await Promise.all(
|
|
105
104
|
filePathsToDelete.map(filePathToDelete =>
|
|
106
105
|
rm(filePathToDelete, { force: true }).catch((e) => {
|
|
107
|
-
|
|
108
|
-
|
|
106
|
+
// This is allowed to fail - we just don't do anything
|
|
107
|
+
debug &&
|
|
109
108
|
// eslint-disable-next-line no-console
|
|
110
109
|
console.debug(`An error occurred while attempting to delete asset: ${filePathToDelete}`, e);
|
|
111
|
-
}
|
|
112
110
|
}),
|
|
113
111
|
),
|
|
114
112
|
);
|
|
@@ -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
|
|
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 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
|
-
|
|
53
|
-
//
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
|
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;
|
|
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
|
|
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,
|
|
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":"
|
|
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,
|
|
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,YAmG9B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"makeEnableSourceMapsPlugin.d.ts","sourceRoot":"","sources":["../../../src/vite/makeEnableSourceMapsPlugin.ts"],"names":[],"mappings":"
|
|
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.
|
|
3
|
+
"version": "10.2.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.
|
|
42
|
-
"@sentry/cli": "^2.
|
|
43
|
-
"@sentry/core": "10.
|
|
44
|
-
"@sentry/node": "10.
|
|
45
|
-
"@sentry/react": "10.
|
|
52
|
+
"@sentry/browser": "10.2.0",
|
|
53
|
+
"@sentry/cli": "^2.50.2",
|
|
54
|
+
"@sentry/core": "10.2.0",
|
|
55
|
+
"@sentry/node": "10.2.0",
|
|
56
|
+
"@sentry/react": "10.2.0",
|
|
46
57
|
"@sentry/vite-plugin": "^4.0.0",
|
|
47
58
|
"glob": "11.0.1"
|
|
48
59
|
},
|