@sentry/react-router 9.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.
- package/LICENSE +16 -0
- package/README.md +182 -0
- package/build/cjs/client/sdk.js +24 -0
- package/build/cjs/client/sdk.js.map +1 -0
- package/build/cjs/index.client.js +19 -0
- package/build/cjs/index.client.js.map +1 -0
- package/build/cjs/index.server.js +23 -0
- package/build/cjs/index.server.js.map +1 -0
- package/build/cjs/server/sdk.js +24 -0
- package/build/cjs/server/sdk.js.map +1 -0
- package/build/cjs/vite/buildEnd/handleOnBuildEnd.js +114 -0
- package/build/cjs/vite/buildEnd/handleOnBuildEnd.js.map +1 -0
- package/build/cjs/vite/makeCustomSentryVitePlugins.js +40 -0
- package/build/cjs/vite/makeCustomSentryVitePlugins.js.map +1 -0
- package/build/cjs/vite/makeEnableSourceMapsPlugin.js +87 -0
- package/build/cjs/vite/makeEnableSourceMapsPlugin.js.map +1 -0
- package/build/cjs/vite/plugin.js +28 -0
- package/build/cjs/vite/plugin.js.map +1 -0
- package/build/esm/client/sdk.js +22 -0
- package/build/esm/client/sdk.js.map +1 -0
- package/build/esm/index.client.js +3 -0
- package/build/esm/index.client.js.map +1 -0
- package/build/esm/index.server.js +5 -0
- package/build/esm/index.server.js.map +1 -0
- package/build/esm/package.json +1 -0
- package/build/esm/server/sdk.js +22 -0
- package/build/esm/server/sdk.js.map +1 -0
- package/build/esm/vite/buildEnd/handleOnBuildEnd.js +112 -0
- package/build/esm/vite/buildEnd/handleOnBuildEnd.js.map +1 -0
- package/build/esm/vite/makeCustomSentryVitePlugins.js +38 -0
- package/build/esm/vite/makeCustomSentryVitePlugins.js.map +1 -0
- package/build/esm/vite/makeEnableSourceMapsPlugin.js +84 -0
- package/build/esm/vite/makeEnableSourceMapsPlugin.js.map +1 -0
- package/build/esm/vite/plugin.js +26 -0
- package/build/esm/vite/plugin.js.map +1 -0
- package/build/types/client/index.d.ts +3 -0
- package/build/types/client/index.d.ts.map +1 -0
- package/build/types/client/sdk.d.ts +7 -0
- package/build/types/client/sdk.d.ts.map +1 -0
- package/build/types/common/debug-build.d.ts +7 -0
- package/build/types/common/debug-build.d.ts.map +1 -0
- package/build/types/index.client.d.ts +2 -0
- package/build/types/index.client.d.ts.map +1 -0
- package/build/types/index.server.d.ts +3 -0
- package/build/types/index.server.d.ts.map +1 -0
- package/build/types/index.types.d.ts +13 -0
- package/build/types/index.types.d.ts.map +1 -0
- package/build/types/server/index.d.ts +3 -0
- package/build/types/server/index.d.ts.map +1 -0
- package/build/types/server/sdk.d.ts +6 -0
- package/build/types/server/sdk.d.ts.map +1 -0
- package/build/types/vite/buildEnd/handleOnBuildEnd.d.ts +10 -0
- package/build/types/vite/buildEnd/handleOnBuildEnd.d.ts.map +1 -0
- package/build/types/vite/index.d.ts +4 -0
- package/build/types/vite/index.d.ts.map +1 -0
- package/build/types/vite/makeCustomSentryVitePlugins.d.ts +7 -0
- package/build/types/vite/makeCustomSentryVitePlugins.d.ts.map +1 -0
- package/build/types/vite/makeEnableSourceMapsPlugin.d.ts +23 -0
- package/build/types/vite/makeEnableSourceMapsPlugin.d.ts.map +1 -0
- package/build/types/vite/plugin.d.ts +12 -0
- package/build/types/vite/plugin.d.ts.map +1 -0
- package/build/types/vite/types.d.ts +141 -0
- package/build/types/vite/types.d.ts.map +1 -0
- package/package.json +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Functional Software, Inc. dba Sentry
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
6
|
+
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
|
7
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
8
|
+
persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
|
11
|
+
Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
14
|
+
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
15
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
16
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://sentry.io/?utm_source=github&utm_medium=logo" target="_blank">
|
|
3
|
+
<img src="https://sentry-brand.storage.googleapis.com/sentry-wordmark-dark-280x84.png" alt="Sentry" width="280" height="84">
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
# Official Sentry SDK for React Router Framework (EXPERIMENTAL)
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@sentry/react-router)
|
|
10
|
+
[](https://www.npmjs.com/package/@sentry/react-router)
|
|
11
|
+
[](https://www.npmjs.com/package/@sentry/react-router)
|
|
12
|
+
|
|
13
|
+
> [!WARNING]
|
|
14
|
+
> This SDK is considered ⚠️ **experimental and in an alpha state**. It may experience breaking changes. Please reach out
|
|
15
|
+
> on [GitHub](https://github.com/getsentry/sentry-javascript/issues/) if you have any feedback or concerns. This
|
|
16
|
+
> SDK is for [React Router (framework)](https://reactrouter.com/start/framework/installation). If you're using [React Router (library)](https://reactrouter.com/start/library/installation) see our
|
|
17
|
+
> [React SDK here](https://docs.sentry.io/platforms/javascript/guides/react/features/react-router/v7/).
|
|
18
|
+
|
|
19
|
+
## Links
|
|
20
|
+
|
|
21
|
+
- [Official SDK Docs](https://docs.sentry.io/platforms/javascript/guides/react-router/)
|
|
22
|
+
|
|
23
|
+
## General
|
|
24
|
+
|
|
25
|
+
This package is a wrapper around `@sentry/node` for the server and `@sentry/browser` for the client side.
|
|
26
|
+
|
|
27
|
+
## Manual Setup
|
|
28
|
+
|
|
29
|
+
### Expose Hooks
|
|
30
|
+
|
|
31
|
+
React Router exposes two hooks in your `app` folder (`entry.client.tsx` and `entry.server.tsx`).
|
|
32
|
+
If you do not see these two files, expose them with the following command:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx react-router reveal
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Client-Side Setup
|
|
39
|
+
|
|
40
|
+
Initialize the SDK in your `entry.client.tsx` file:
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
import * as Sentry from '@sentry/react-router';
|
|
44
|
+
import { startTransition, StrictMode } from 'react';
|
|
45
|
+
import { hydrateRoot } from 'react-dom/client';
|
|
46
|
+
import { HydratedRouter } from 'react-router/dom';
|
|
47
|
+
|
|
48
|
+
Sentry.init({
|
|
49
|
+
dsn: '___PUBLIC_DSN___',
|
|
50
|
+
integrations: [Sentry.browserTracingIntegration()],
|
|
51
|
+
|
|
52
|
+
tracesSampleRate: 1.0, // Capture 100% of the transactions
|
|
53
|
+
|
|
54
|
+
// Set `tracePropagationTargets` to declare which URL(s) should have trace propagation enabled
|
|
55
|
+
tracePropagationTargets: [/^\//, /^https:\/\/yourserver\.io\/api/],
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
startTransition(() => {
|
|
59
|
+
hydrateRoot(
|
|
60
|
+
document,
|
|
61
|
+
<StrictMode>
|
|
62
|
+
<HydratedRouter />
|
|
63
|
+
</StrictMode>,
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Now, update your `app/root.tsx` file to report any unhandled errors from your global error boundary:
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import * as Sentry from '@sentry/react-router';
|
|
72
|
+
|
|
73
|
+
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
|
|
74
|
+
let message = 'Oops!';
|
|
75
|
+
let details = 'An unexpected error occurred.';
|
|
76
|
+
let stack: string | undefined;
|
|
77
|
+
|
|
78
|
+
if (isRouteErrorResponse(error)) {
|
|
79
|
+
message = error.status === 404 ? '404' : 'Error';
|
|
80
|
+
details = error.status === 404 ? 'The requested page could not be found.' : error.statusText || details;
|
|
81
|
+
} else if (error && error instanceof Error) {
|
|
82
|
+
// you only want to capture non 404-errors that reach the boundary
|
|
83
|
+
Sentry.captureException(error);
|
|
84
|
+
if (import.meta.env.DEV) {
|
|
85
|
+
details = error.message;
|
|
86
|
+
stack = error.stack;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<main>
|
|
92
|
+
<h1>{message}</h1>
|
|
93
|
+
<p>{details}</p>
|
|
94
|
+
{stack && (
|
|
95
|
+
<pre>
|
|
96
|
+
<code>{stack}</code>
|
|
97
|
+
</pre>
|
|
98
|
+
)}
|
|
99
|
+
</main>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
// ...
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Server-Side Setup
|
|
106
|
+
|
|
107
|
+
Create an `instrument.server.mjs` file in the root of your app:
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
import * as Sentry from '@sentry/react-router';
|
|
111
|
+
|
|
112
|
+
Sentry.init({
|
|
113
|
+
dsn: '___PUBLIC_DSN___',
|
|
114
|
+
tracesSampleRate: 1.0, // Capture 100% of the transactions
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
In your `entry.server.tsx` file, export the `handleError` function:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
import * as Sentry from '@sentry/react-router';
|
|
122
|
+
import { type HandleErrorFunction } from 'react-router';
|
|
123
|
+
|
|
124
|
+
export const handleError: HandleErrorFunction = (error, { request }) => {
|
|
125
|
+
// React Router may abort some interrupted requests, report those
|
|
126
|
+
if (!request.signal.aborted) {
|
|
127
|
+
Sentry.captureException(error);
|
|
128
|
+
|
|
129
|
+
// make sure to still log the error so you can see it
|
|
130
|
+
console.error(error);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
// ... rest of your server entry
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Update Scripts
|
|
137
|
+
|
|
138
|
+
Since React Router is running in ESM mode, you need to use the `--import` command line options to load our server-side instrumentation module before the application starts.
|
|
139
|
+
Update the `start` and `dev` script to include the instrumentation file:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
"scripts": {
|
|
143
|
+
"dev": "NODE_OPTIONS='--import ./instrument.server.mjs' react-router dev",
|
|
144
|
+
"start": "NODE_OPTIONS='--import ./instrument.server.mjs' react-router-serve ./build/server/index.js",
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Build-time Config
|
|
149
|
+
|
|
150
|
+
Update your vite.config.ts file to include the `sentryReactRouter` plugin and also add your config options to the vite config (this is required for uploading sourcemaps at the end of the build):
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import { reactRouter } from '@react-router/dev/vite';
|
|
154
|
+
import { sentryReactRouter } from '@sentry/react-router';
|
|
155
|
+
import { defineConfig } from 'vite';
|
|
156
|
+
|
|
157
|
+
const sentryConfig = {
|
|
158
|
+
authToken: '...',
|
|
159
|
+
org: '...',
|
|
160
|
+
project: '...',
|
|
161
|
+
// rest of your config
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export default defineConfig(config => {
|
|
165
|
+
return {
|
|
166
|
+
plugins: [reactRouter(), sentryReactRouter(sentryConfig, config)],
|
|
167
|
+
sentryConfig,
|
|
168
|
+
};
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Next, in your `react-router.config.ts` file, include the `sentryOnBuildEnd` hook:
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
import type { Config } from '@react-router/dev/config';
|
|
176
|
+
import { sentryOnBuildEnd } from '@sentry/react-router';
|
|
177
|
+
|
|
178
|
+
export default {
|
|
179
|
+
ssr: true,
|
|
180
|
+
buildEnd: sentryOnBuildEnd,
|
|
181
|
+
} satisfies Config;
|
|
182
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const browser = require('@sentry/browser');
|
|
4
|
+
const core = require('@sentry/core');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Initializes the client side of the React Router SDK.
|
|
8
|
+
*/
|
|
9
|
+
function init(options) {
|
|
10
|
+
const opts = {
|
|
11
|
+
...options,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
core.applySdkMetadata(opts, 'react-router', ['react-router', 'browser']);
|
|
15
|
+
|
|
16
|
+
const client = browser.init(opts);
|
|
17
|
+
|
|
18
|
+
core.setTag('runtime', 'browser');
|
|
19
|
+
|
|
20
|
+
return client;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
exports.init = init;
|
|
24
|
+
//# sourceMappingURL=sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.js","sources":["../../../src/client/sdk.ts"],"sourcesContent":["import type { BrowserOptions } from '@sentry/browser';\nimport { init as browserInit } from '@sentry/browser';\nimport type { Client } from '@sentry/core';\nimport { applySdkMetadata, setTag } from '@sentry/core';\n\n/**\n * Initializes the client side of the React Router SDK.\n */\nexport function init(options: BrowserOptions): Client | undefined {\n const opts = {\n ...options,\n };\n\n applySdkMetadata(opts, 'react-router', ['react-router', 'browser']);\n\n const client = browserInit(opts);\n\n setTag('runtime', 'browser');\n\n return client;\n}\n"],"names":["applySdkMetadata","browserInit","setTag"],"mappings":";;;;;AAKA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAsC;AAClE,EAAE,MAAM,OAAO;AACf,IAAI,GAAG,OAAO;AACd,GAAG;;AAEH,EAAEA,qBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;;AAErE,EAAE,MAAM,MAAO,GAAEC,YAAW,CAAC,IAAI,CAAC;;AAElC,EAAEC,WAAM,CAAC,SAAS,EAAE,SAAS,CAAC;;AAE9B,EAAE,OAAO,MAAM;AACf;;;;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const browser = require('@sentry/browser');
|
|
4
|
+
const sdk = require('./client/sdk.js');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
exports.init = sdk.init;
|
|
9
|
+
Object.prototype.hasOwnProperty.call(browser, '__proto__') &&
|
|
10
|
+
!Object.prototype.hasOwnProperty.call(exports, '__proto__') &&
|
|
11
|
+
Object.defineProperty(exports, '__proto__', {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
value: browser['__proto__']
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
Object.keys(browser).forEach(k => {
|
|
17
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = browser[k];
|
|
18
|
+
});
|
|
19
|
+
//# sourceMappingURL=index.client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const node = require('@sentry/node');
|
|
4
|
+
const sdk = require('./server/sdk.js');
|
|
5
|
+
const plugin = require('./vite/plugin.js');
|
|
6
|
+
const handleOnBuildEnd = require('./vite/buildEnd/handleOnBuildEnd.js');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
exports.init = sdk.init;
|
|
11
|
+
exports.sentryReactRouter = plugin.sentryReactRouter;
|
|
12
|
+
exports.sentryOnBuildEnd = handleOnBuildEnd.sentryOnBuildEnd;
|
|
13
|
+
Object.prototype.hasOwnProperty.call(node, '__proto__') &&
|
|
14
|
+
!Object.prototype.hasOwnProperty.call(exports, '__proto__') &&
|
|
15
|
+
Object.defineProperty(exports, '__proto__', {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
value: node['__proto__']
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
Object.keys(node).forEach(k => {
|
|
21
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) exports[k] = node[k];
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=index.server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const core = require('@sentry/core');
|
|
4
|
+
const node = require('@sentry/node');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Initializes the server side of the React Router SDK
|
|
8
|
+
*/
|
|
9
|
+
function init(options) {
|
|
10
|
+
const opts = {
|
|
11
|
+
...options,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
core.applySdkMetadata(opts, 'react-router', ['react-router', 'node']);
|
|
15
|
+
|
|
16
|
+
const client = node.init(opts);
|
|
17
|
+
|
|
18
|
+
core.setTag('runtime', 'node');
|
|
19
|
+
|
|
20
|
+
return client;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
exports.init = init;
|
|
24
|
+
//# sourceMappingURL=sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.js","sources":["../../../src/server/sdk.ts"],"sourcesContent":["import { applySdkMetadata, setTag } from '@sentry/core';\nimport type { NodeClient, NodeOptions } from '@sentry/node';\nimport { init as initNodeSdk } from '@sentry/node';\n\n/**\n * Initializes the server side of the React Router SDK\n */\nexport function init(options: NodeOptions): NodeClient | undefined {\n const opts = {\n ...options,\n };\n\n applySdkMetadata(opts, 'react-router', ['react-router', 'node']);\n\n const client = initNodeSdk(opts);\n\n setTag('runtime', 'node');\n\n return client;\n}\n"],"names":["applySdkMetadata","initNodeSdk","setTag"],"mappings":";;;;;AAIA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAuC;AACnE,EAAE,MAAM,OAAO;AACf,IAAI,GAAG,OAAO;AACd,GAAG;;AAEH,EAAEA,qBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;;AAElE,EAAE,MAAM,MAAO,GAAEC,SAAW,CAAC,IAAI,CAAC;;AAElC,EAAEC,WAAM,CAAC,SAAS,EAAE,MAAM,CAAC;;AAE3B,EAAE,OAAO,MAAM;AACf;;;;"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const promises = require('node:fs/promises');
|
|
4
|
+
const SentryCli = require('@sentry/cli');
|
|
5
|
+
const glob = require('glob');
|
|
6
|
+
|
|
7
|
+
function getSentryConfig(viteConfig) {
|
|
8
|
+
if (!viteConfig || typeof viteConfig !== 'object' || !('sentryConfig' in viteConfig)) {
|
|
9
|
+
// eslint-disable-next-line no-console
|
|
10
|
+
console.error('[Sentry] sentryConfig not found - it needs to be passed to vite.config.ts');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return (viteConfig ).sentryConfig;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A build end hook that handles Sentry release creation and source map uploads.
|
|
18
|
+
* It creates a new Sentry release if configured, uploads source maps to Sentry,
|
|
19
|
+
* and optionally deletes the source map files after upload.
|
|
20
|
+
*/
|
|
21
|
+
const sentryOnBuildEnd = async ({ reactRouterConfig, viteConfig }) => {
|
|
22
|
+
const {
|
|
23
|
+
authToken,
|
|
24
|
+
org,
|
|
25
|
+
project,
|
|
26
|
+
release,
|
|
27
|
+
sourceMapsUploadOptions = { enabled: true },
|
|
28
|
+
debug = false,
|
|
29
|
+
} = getSentryConfig(viteConfig);
|
|
30
|
+
|
|
31
|
+
const cliInstance = new SentryCli.default(null, {
|
|
32
|
+
authToken,
|
|
33
|
+
org,
|
|
34
|
+
project,
|
|
35
|
+
});
|
|
36
|
+
// check if release should be created
|
|
37
|
+
if (release?.name) {
|
|
38
|
+
try {
|
|
39
|
+
await cliInstance.releases.new(release.name);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
// eslint-disable-next-line no-console
|
|
42
|
+
console.error('[Sentry] Could not create release', error);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (sourceMapsUploadOptions?.enabled ?? (viteConfig.build.sourcemap !== false)) {
|
|
47
|
+
// inject debugIds
|
|
48
|
+
try {
|
|
49
|
+
await cliInstance.execute(['sourcemaps', 'inject', reactRouterConfig.buildDirectory], debug);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
// eslint-disable-next-line no-console
|
|
52
|
+
console.error('[Sentry] Could not inject debug ids', error);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// upload sourcemaps
|
|
56
|
+
try {
|
|
57
|
+
await cliInstance.releases.uploadSourceMaps(release?.name || 'undefined', {
|
|
58
|
+
include: [
|
|
59
|
+
{
|
|
60
|
+
paths: [reactRouterConfig.buildDirectory],
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
});
|
|
64
|
+
} catch (error) {
|
|
65
|
+
// eslint-disable-next-line no-console
|
|
66
|
+
console.error('[Sentry] Could not upload sourcemaps', error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// delete sourcemaps after upload
|
|
70
|
+
let updatedFilesToDeleteAfterUpload = sourceMapsUploadOptions?.filesToDeleteAfterUpload;
|
|
71
|
+
// set a default value no option was set
|
|
72
|
+
if (typeof sourceMapsUploadOptions?.filesToDeleteAfterUpload === 'undefined') {
|
|
73
|
+
updatedFilesToDeleteAfterUpload = [`${reactRouterConfig.buildDirectory}/**/*.map`];
|
|
74
|
+
if (debug) {
|
|
75
|
+
// eslint-disable-next-line no-console
|
|
76
|
+
console.info(
|
|
77
|
+
`[Sentry] Automatically setting \`sourceMapsUploadOptions.filesToDeleteAfterUpload: ${JSON.stringify(
|
|
78
|
+
updatedFilesToDeleteAfterUpload,
|
|
79
|
+
)}\` to delete generated source maps after they were uploaded to Sentry.`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (updatedFilesToDeleteAfterUpload) {
|
|
84
|
+
try {
|
|
85
|
+
const filePathsToDelete = await glob.glob(updatedFilesToDeleteAfterUpload, {
|
|
86
|
+
absolute: true,
|
|
87
|
+
nodir: true,
|
|
88
|
+
});
|
|
89
|
+
if (debug) {
|
|
90
|
+
filePathsToDelete.forEach(filePathToDelete => {
|
|
91
|
+
// eslint-disable-next-line no-console
|
|
92
|
+
console.info(`Deleting asset after upload: ${filePathToDelete}`);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
await Promise.all(
|
|
96
|
+
filePathsToDelete.map(filePathToDelete =>
|
|
97
|
+
promises.rm(filePathToDelete, { force: true }).catch((e) => {
|
|
98
|
+
if (debug) {
|
|
99
|
+
// This is allowed to fail - we just don't do anything
|
|
100
|
+
// eslint-disable-next-line no-console
|
|
101
|
+
console.debug(`An error occurred while attempting to delete asset: ${filePathToDelete}`, e);
|
|
102
|
+
}
|
|
103
|
+
}),
|
|
104
|
+
),
|
|
105
|
+
);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
// eslint-disable-next-line no-console
|
|
108
|
+
console.error('Error deleting files after sourcemap upload:', error);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
exports.sentryOnBuildEnd = sentryOnBuildEnd;
|
|
114
|
+
//# sourceMappingURL=handleOnBuildEnd.js.map
|
|
@@ -0,0 +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/dist/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 {\n authToken,\n org,\n project,\n release,\n sourceMapsUploadOptions = { enabled: true },\n debug = false,\n } = getSentryConfig(viteConfig);\n\n const cliInstance = new SentryCli(null, {\n authToken,\n org,\n project,\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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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const vitePlugin = require('@sentry/vite-plugin');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Create a custom subset of sentry's vite plugins
|
|
7
|
+
*/
|
|
8
|
+
async function makeCustomSentryVitePlugins(options) {
|
|
9
|
+
const { debug, unstable_sentryVitePluginOptions, bundleSizeOptimizations, authToken, org, project, telemetry } =
|
|
10
|
+
options;
|
|
11
|
+
|
|
12
|
+
const sentryVitePlugins = vitePlugin.sentryVitePlugin({
|
|
13
|
+
authToken: authToken ?? process.env.SENTRY_AUTH_TOKEN,
|
|
14
|
+
bundleSizeOptimizations,
|
|
15
|
+
debug: debug ?? false,
|
|
16
|
+
org: org ?? process.env.SENTRY_ORG,
|
|
17
|
+
project: project ?? process.env.SENTRY_PROJECT,
|
|
18
|
+
telemetry: telemetry ?? true,
|
|
19
|
+
_metaOptions: {
|
|
20
|
+
telemetry: {
|
|
21
|
+
metaFramework: 'react-router',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
// will be handled in buildEnd hook
|
|
25
|
+
sourcemaps: {
|
|
26
|
+
disable: true,
|
|
27
|
+
},
|
|
28
|
+
...unstable_sentryVitePluginOptions,
|
|
29
|
+
}) ;
|
|
30
|
+
|
|
31
|
+
// only use a subset of the plugins as all upload and file deletion tasks will be handled in the buildEnd hook
|
|
32
|
+
return [
|
|
33
|
+
...sentryVitePlugins.filter(plugin => {
|
|
34
|
+
return ['sentry-telemetry-plugin', 'sentry-vite-release-injection-plugin'].includes(plugin.name);
|
|
35
|
+
}),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
exports.makeCustomSentryVitePlugins = makeCustomSentryVitePlugins;
|
|
40
|
+
//# sourceMappingURL=makeCustomSentryVitePlugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"makeCustomSentryVitePlugins.js","sources":["../../../src/vite/makeCustomSentryVitePlugins.ts"],"sourcesContent":["import { sentryVitePlugin } from '@sentry/vite-plugin';\nimport { type Plugin } from 'vite';\nimport type { SentryReactRouterBuildOptions } from './types';\n\n/**\n * Create a custom subset of sentry's vite plugins\n */\nexport async function makeCustomSentryVitePlugins(options: SentryReactRouterBuildOptions): Promise<Plugin[]> {\n const { debug, unstable_sentryVitePluginOptions, bundleSizeOptimizations, authToken, org, project, telemetry } =\n options;\n\n const sentryVitePlugins = sentryVitePlugin({\n authToken: authToken ?? process.env.SENTRY_AUTH_TOKEN,\n bundleSizeOptimizations,\n debug: debug ?? false,\n org: org ?? process.env.SENTRY_ORG,\n project: project ?? process.env.SENTRY_PROJECT,\n telemetry: telemetry ?? true,\n _metaOptions: {\n telemetry: {\n metaFramework: 'react-router',\n },\n },\n // will be handled in buildEnd hook\n sourcemaps: {\n disable: true,\n },\n ...unstable_sentryVitePluginOptions,\n }) as Plugin[];\n\n // only use a subset of the plugins as all upload and file deletion tasks will be handled in the buildEnd hook\n return [\n ...sentryVitePlugins.filter(plugin => {\n return ['sentry-telemetry-plugin', 'sentry-vite-release-injection-plugin'].includes(plugin.name);\n }),\n ];\n}\n"],"names":["sentryVitePlugin"],"mappings":";;;;AAIA;AACA;AACA;AACO,eAAe,2BAA2B,CAAC,OAAO,EAAoD;AAC7G,EAAE,MAAM,EAAE,KAAK,EAAE,gCAAgC,EAAE,uBAAuB,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,WAAY;AACjH,IAAI,OAAO;;AAEX,EAAE,MAAM,iBAAA,GAAoBA,2BAAgB,CAAC;AAC7C,IAAI,SAAS,EAAE,SAAU,IAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB;AACzD,IAAI,uBAAuB;AAC3B,IAAI,KAAK,EAAE,KAAM,IAAG,KAAK;AACzB,IAAI,GAAG,EAAE,GAAI,IAAG,OAAO,CAAC,GAAG,CAAC,UAAU;AACtC,IAAI,OAAO,EAAE,OAAQ,IAAG,OAAO,CAAC,GAAG,CAAC,cAAc;AAClD,IAAI,SAAS,EAAE,SAAU,IAAG,IAAI;AAChC,IAAI,YAAY,EAAE;AAClB,MAAM,SAAS,EAAE;AACjB,QAAQ,aAAa,EAAE,cAAc;AACrC,OAAO;AACP,KAAK;AACL;AACA,IAAI,UAAU,EAAE;AAChB,MAAM,OAAO,EAAE,IAAI;AACnB,KAAK;AACL,IAAI,GAAG,gCAAgC;AACvC,GAAG,CAAE;;AAEL;AACA,EAAE,OAAO;AACT,IAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,UAAU;AAC1C,MAAM,OAAO,CAAC,yBAAyB,EAAE,sCAAsC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;AACtG,KAAK,CAAC;AACN,GAAG;AACH;;;;"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const core = require('@sentry/core');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A Sentry plugin for React Router to enable "hidden" source maps if they are unset.
|
|
7
|
+
*/
|
|
8
|
+
function makeEnableSourceMapsPlugin(options) {
|
|
9
|
+
return {
|
|
10
|
+
name: 'sentry-react-router-update-source-map-setting',
|
|
11
|
+
apply: 'build',
|
|
12
|
+
enforce: 'post',
|
|
13
|
+
config(viteConfig) {
|
|
14
|
+
return {
|
|
15
|
+
...viteConfig,
|
|
16
|
+
build: {
|
|
17
|
+
...viteConfig.build,
|
|
18
|
+
sourcemap: getUpdatedSourceMapSettings(viteConfig, options),
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** There are 3 ways to set up source map generation
|
|
26
|
+
*
|
|
27
|
+
* 1. User explicitly disabled source maps
|
|
28
|
+
* - keep this setting (emit a warning that errors won't be unminified in Sentry)
|
|
29
|
+
* - we won't upload anything
|
|
30
|
+
*
|
|
31
|
+
* 2. Users enabled source map generation (true, 'hidden', 'inline').
|
|
32
|
+
* - keep this setting (don't do anything - like deletion - besides uploading)
|
|
33
|
+
*
|
|
34
|
+
* 3. Users didn't set source maps generation
|
|
35
|
+
* - we enable 'hidden' source maps generation
|
|
36
|
+
* - configure `filesToDeleteAfterUpload` to delete all .map files (we emit a log about this)
|
|
37
|
+
*
|
|
38
|
+
* --> only exported for testing
|
|
39
|
+
*/
|
|
40
|
+
function getUpdatedSourceMapSettings(
|
|
41
|
+
viteConfig,
|
|
42
|
+
sentryPluginOptions,
|
|
43
|
+
) {
|
|
44
|
+
viteConfig.build = viteConfig.build || {};
|
|
45
|
+
|
|
46
|
+
const viteSourceMap = viteConfig?.build?.sourcemap;
|
|
47
|
+
let updatedSourceMapSetting = viteSourceMap;
|
|
48
|
+
|
|
49
|
+
const settingKey = 'vite.build.sourcemap';
|
|
50
|
+
|
|
51
|
+
if (viteSourceMap === false) {
|
|
52
|
+
updatedSourceMapSetting = viteSourceMap;
|
|
53
|
+
|
|
54
|
+
core.consoleSandbox(() => {
|
|
55
|
+
// eslint-disable-next-line no-console
|
|
56
|
+
console.warn(
|
|
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
|
+
);
|
|
59
|
+
});
|
|
60
|
+
} else if (viteSourceMap && ['hidden', 'inline', true].includes(viteSourceMap)) {
|
|
61
|
+
updatedSourceMapSetting = viteSourceMap;
|
|
62
|
+
|
|
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
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
updatedSourceMapSetting = 'hidden';
|
|
73
|
+
|
|
74
|
+
core.consoleSandbox(() => {
|
|
75
|
+
// eslint-disable-next-line no-console
|
|
76
|
+
console.log(
|
|
77
|
+
`[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
|
+
);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return updatedSourceMapSetting;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
exports.getUpdatedSourceMapSettings = getUpdatedSourceMapSettings;
|
|
86
|
+
exports.makeEnableSourceMapsPlugin = makeEnableSourceMapsPlugin;
|
|
87
|
+
//# sourceMappingURL=makeEnableSourceMapsPlugin.js.map
|
|
@@ -0,0 +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,KAAM,GAAE,UAAU,CAAC,KAAA,IAAS,EAAE;;AAE3C,EAAE,MAAM,aAAc,GAAE,UAAU,EAAE,KAAK,EAAE,SAAS;AACpD,EAAE,IAAI,uBAAwB,GAAE,aAAa;;AAE7C,EAAE,MAAM,UAAW,GAAE,sBAAsB;;AAE3C,EAAE,IAAI,aAAc,KAAI,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,aAAc,IAAG,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;;;;;"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const makeCustomSentryVitePlugins = require('./makeCustomSentryVitePlugins.js');
|
|
4
|
+
const makeEnableSourceMapsPlugin = require('./makeEnableSourceMapsPlugin.js');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A Vite plugin for Sentry that handles source map uploads and bundle size optimizations.
|
|
8
|
+
*
|
|
9
|
+
* @param options - Configuration options for the Sentry Vite plugin
|
|
10
|
+
* @param viteConfig - The Vite user config object
|
|
11
|
+
* @returns An array of Vite plugins
|
|
12
|
+
*/
|
|
13
|
+
async function sentryReactRouter(
|
|
14
|
+
options = {},
|
|
15
|
+
config,
|
|
16
|
+
) {
|
|
17
|
+
const plugins = [];
|
|
18
|
+
|
|
19
|
+
if (process.env.NODE_ENV !== 'development' && config.command === 'build' && config.mode !== 'development') {
|
|
20
|
+
plugins.push(makeEnableSourceMapsPlugin.makeEnableSourceMapsPlugin(options));
|
|
21
|
+
plugins.push(...(await makeCustomSentryVitePlugins.makeCustomSentryVitePlugins(options)));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return plugins;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exports.sentryReactRouter = sentryReactRouter;
|
|
28
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["../../../src/vite/plugin.ts"],"sourcesContent":["import type { ConfigEnv } from 'vite';\nimport { type Plugin } from 'vite';\nimport { makeCustomSentryVitePlugins } from './makeCustomSentryVitePlugins';\nimport { makeEnableSourceMapsPlugin } from './makeEnableSourceMapsPlugin';\nimport type { SentryReactRouterBuildOptions } from './types';\n\n/**\n * A Vite plugin for Sentry that handles source map uploads and bundle size optimizations.\n *\n * @param options - Configuration options for the Sentry Vite plugin\n * @param viteConfig - The Vite user config object\n * @returns An array of Vite plugins\n */\nexport async function sentryReactRouter(\n options: SentryReactRouterBuildOptions = {},\n config: ConfigEnv,\n): Promise<Plugin[]> {\n const plugins: Plugin[] = [];\n\n if (process.env.NODE_ENV !== 'development' && config.command === 'build' && config.mode !== 'development') {\n plugins.push(makeEnableSourceMapsPlugin(options));\n plugins.push(...(await makeCustomSentryVitePlugins(options)));\n }\n\n return plugins;\n}\n"],"names":["makeEnableSourceMapsPlugin","makeCustomSentryVitePlugins"],"mappings":";;;;;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,eAAe,iBAAiB;AACvC,EAAE,OAAO,GAAkC,EAAE;AAC7C,EAAE,MAAM;AACR,EAAqB;AACrB,EAAE,MAAM,OAAO,GAAa,EAAE;;AAE9B,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,QAAA,KAAa,aAAc,IAAG,MAAM,CAAC,OAAA,KAAY,OAAQ,IAAG,MAAM,CAAC,IAAA,KAAS,aAAa,EAAE;AAC7G,IAAI,OAAO,CAAC,IAAI,CAACA,qDAA0B,CAAC,OAAO,CAAC,CAAC;AACrD,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,MAAMC,uDAA2B,CAAC,OAAO,CAAC,CAAC,CAAC;AACjE;;AAEA,EAAE,OAAO,OAAO;AAChB;;;;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { init as init$1 } from '@sentry/browser';
|
|
2
|
+
import { applySdkMetadata, setTag } from '@sentry/core';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Initializes the client side of the React Router SDK.
|
|
6
|
+
*/
|
|
7
|
+
function init(options) {
|
|
8
|
+
const opts = {
|
|
9
|
+
...options,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
applySdkMetadata(opts, 'react-router', ['react-router', 'browser']);
|
|
13
|
+
|
|
14
|
+
const client = init$1(opts);
|
|
15
|
+
|
|
16
|
+
setTag('runtime', 'browser');
|
|
17
|
+
|
|
18
|
+
return client;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { init };
|
|
22
|
+
//# sourceMappingURL=sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.js","sources":["../../../src/client/sdk.ts"],"sourcesContent":["import type { BrowserOptions } from '@sentry/browser';\nimport { init as browserInit } from '@sentry/browser';\nimport type { Client } from '@sentry/core';\nimport { applySdkMetadata, setTag } from '@sentry/core';\n\n/**\n * Initializes the client side of the React Router SDK.\n */\nexport function init(options: BrowserOptions): Client | undefined {\n const opts = {\n ...options,\n };\n\n applySdkMetadata(opts, 'react-router', ['react-router', 'browser']);\n\n const client = browserInit(opts);\n\n setTag('runtime', 'browser');\n\n return client;\n}\n"],"names":["browserInit"],"mappings":";;;AAKA;AACA;AACA;AACO,SAAS,IAAI,CAAC,OAAO,EAAsC;AAClE,EAAE,MAAM,OAAO;AACf,IAAI,GAAG,OAAO;AACd,GAAG;;AAEH,EAAE,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;;AAErE,EAAE,MAAM,MAAO,GAAEA,MAAW,CAAC,IAAI,CAAC;;AAElC,EAAE,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC;;AAE9B,EAAE,OAAO,MAAM;AACf;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.client.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|