diff --git a/dev-packages/e2e-tests/verdaccio-config/config.yaml b/dev-packages/e2e-tests/verdaccio-config/config.yaml
index ee65c5218d4a..cbb73201eebf 100644
--- a/dev-packages/e2e-tests/verdaccio-config/config.yaml
+++ b/dev-packages/e2e-tests/verdaccio-config/config.yaml
@@ -122,6 +122,12 @@ packages:
unpublish: $all
# proxy: npmjs # Don't proxy for E2E tests!
+ '@sentry/react-router':
+ access: $all
+ publish: $all
+ unpublish: $all
+ # proxy: npmjs # Don't proxy for E2E tests!
+
'@sentry/remix':
access: $all
publish: $all
diff --git a/package.json b/package.json
index 4eaa5eac73ca..a57893dde86c 100644
--- a/package.json
+++ b/package.json
@@ -73,6 +73,7 @@
"packages/opentelemetry",
"packages/profiling-node",
"packages/react",
+ "packages/react-router",
"packages/remix",
"packages/replay-internal",
"packages/replay-canvas",
diff --git a/packages/react-router/.eslintrc.js b/packages/react-router/.eslintrc.js
new file mode 100644
index 000000000000..a22f9710cf6b
--- /dev/null
+++ b/packages/react-router/.eslintrc.js
@@ -0,0 +1,15 @@
+module.exports = {
+ env: {
+ browser: true,
+ node: true,
+ },
+ overrides: [
+ {
+ files: ['vite.config.ts'],
+ parserOptions: {
+ project: ['tsconfig.test.json'],
+ },
+ },
+ ],
+ extends: ['../../.eslintrc.js'],
+};
diff --git a/packages/react-router/LICENSE b/packages/react-router/LICENSE
new file mode 100644
index 000000000000..5251db3eaaca
--- /dev/null
+++ b/packages/react-router/LICENSE
@@ -0,0 +1,16 @@
+MIT License
+
+Copyright (c) 2025 Functional Software, Inc. dba Sentry
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/packages/react-router/README.md b/packages/react-router/README.md
new file mode 100644
index 000000000000..368f3ee4b717
--- /dev/null
+++ b/packages/react-router/README.md
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+# Official Sentry SDK for React Router (Framework) (EXPERIMENTAL)
+
+[](https://www.npmjs.com/package/@sentry/react-router)
+[](https://www.npmjs.com/package/@sentry/react-router)
+[](https://www.npmjs.com/package/@sentry/react-router)
+
+> [!WARNING]
+> This SDK is considered ⚠️ **experimental and in an alpha state**. It may experience breaking changes. Please reach out
+> on [GitHub](https://github.com/getsentry/sentry-javascript/issues/) if you have any feedback or concerns. This
+> 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
+> [React SDK here](https://docs.sentry.io/platforms/javascript/guides/react/features/react-router/v7/).
+
+## Links
+
+- [Official SDK Docs](https://docs.sentry.io/platforms/javascript/guides/react-router/)
+
+## General
+
+This package is a wrapper around `@sentry/node` for the server and `@sentry/browser` for the client side.
+
+## Manual Setup
+
+### Expose Hooks
+
+React Router exposes two hooks in your `app` folder (`entry.client.tsx` and `entry.server.tsx`).
+If you do not see these two files, expose them with the following command:
+
+```bash
+npx react-router reveal
+```
+
+### Client-Side Setup
+
+Initialize the SDK in your `entry.client.tsx` file:
+
+```tsx
+import * as Sentry from '@sentry/react-router';
+import { startTransition, StrictMode } from 'react';
+import { hydrateRoot } from 'react-dom/client';
+import { HydratedRouter } from 'react-router/dom';
+
+Sentry.init({
+ dsn: '___PUBLIC_DSN___',
+ integrations: [Sentry.browserTracingIntegration()],
+
+ tracesSampleRate: 1.0, // Capture 100% of the transactions
+
+ // Set `tracePropagationTargets` to declare which URL(s) should have trace propagation enabled
+ tracePropagationTargets: [/^\//, /^https:\/\/yourserver\.io\/api/],
+});
+
+startTransition(() => {
+ hydrateRoot(
+ document,
+
+
+ ,
+ );
+});
+```
+
+Now, update your `app/root.tsx` file to report any unhandled errors from your global error boundary:
+
+```tsx
+import * as Sentry from '@sentry/react-router';
+
+export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
+ let message = 'Oops!';
+ let details = 'An unexpected error occurred.';
+ let stack: string | undefined;
+
+ if (isRouteErrorResponse(error)) {
+ message = error.status === 404 ? '404' : 'Error';
+ details = error.status === 404 ? 'The requested page could not be found.' : error.statusText || details;
+ } else if (error && error instanceof Error) {
+ // you only want to capture non 404-errors that reach the boundary
+ Sentry.captureException(error);
+ if (import.meta.env.DEV) {
+ details = error.message;
+ stack = error.stack;
+ }
+ }
+
+ return (
+
+ {message}
+ {details}
+ {stack && (
+
+ {stack}
+
+ )}
+
+ );
+}
+// ...
+```
+
+### Server-Side Setup
+
+Create an `instrument.server.mjs` file in the root of your app:
+
+```js
+import * as Sentry from '@sentry/node';
+
+Sentry.init({
+ dsn: '___PUBLIC_DSN___',
+ tracesSampleRate: 1.0, // Capture 100% of the transactions
+});
+```
+
+In your `entry.server.tsx` file, export the `handleError` function:
+
+```tsx
+import * as Sentry from '@sentry/node';
+import { type HandleErrorFunction } from 'react-router';
+
+export const handleError: HandleErrorFunction = (error, { request }) => {
+ // React Router may abort some interrupted requests, report those
+ if (!request.signal.aborted) {
+ Sentry.captureException(error);
+
+ // make sure to still log the error so you can see it
+ console.error(error);
+ }
+};
+// ... rest of your server entry
+```
+
+### Update Scripts
+
+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.
+Update the `start` and `dev` script to include the instrumentation file:
+
+```json
+"scripts": {
+ "dev": "NODE_OPTIONS='--import ./instrument.server.mjs' react-router dev",
+ "start": "NODE_OPTIONS='--import ./instrument.server.mjs' react-router-serve ./build/server/index.js",
+}
+```
diff --git a/packages/react-router/package.json b/packages/react-router/package.json
new file mode 100644
index 000000000000..8db3107ecffb
--- /dev/null
+++ b/packages/react-router/package.json
@@ -0,0 +1,73 @@
+{
+ "name": "@sentry/react-router",
+ "version": "9.0.0-alpha.2",
+ "description": "Official Sentry SDK for React Router (Framework)",
+ "repository": "git://github.com/getsentry/sentry-javascript.git",
+ "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/react-router",
+ "author": "Sentry",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ },
+ "files": [
+ "/build"
+ ],
+ "main": "build/cjs/index.server.js",
+ "module": "build/esm/index.server.js",
+ "browser": "build/esm/index.client.js",
+ "types": "build/types/index.types.d.ts",
+ "exports": {
+ "./package.json": "./package.json",
+ ".": {
+ "types": "./build/types/index.types.d.ts",
+ "browser": {
+ "import": "./build/esm/index.client.js",
+ "require": "./build/cjs/index.client.js"
+ },
+ "node": {
+ "import": "./build/esm/index.server.js",
+ "require": "./build/cjs/index.server.js"
+ }
+ }
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "dependencies": {
+ "@sentry/core": "9.0.0-alpha.2",
+ "@sentry/browser": "9.0.0-alpha.2",
+ "@sentry/node": "9.0.0-alpha.2"
+ },
+ "devDependencies": {
+ "@react-router/node": "^7.1.5",
+ "react-router": "^7.1.5"
+ },
+ "peerDependencies": {
+ "@react-router/node": "7.x",
+ "react-router": "7.x",
+ "react": ">=18"
+ },
+ "scripts": {
+ "build": "run-p build:transpile build:types",
+ "build:dev": "yarn build",
+ "build:transpile": "rollup -c rollup.npm.config.mjs",
+ "build:types": "run-s build:types:core",
+ "build:types:core": "tsc -p tsconfig.types.json",
+ "build:watch": "run-p build:transpile:watch build:types:watch",
+ "build:dev:watch": "yarn build:watch",
+ "build:transpile:watch": "rollup -c rollup.npm.config.mjs --watch",
+ "build:types:watch": "tsc -p tsconfig.types.json --watch",
+ "build:tarball": "npm pack",
+ "circularDepCheck": "madge --circular src/index.client.ts && madge --circular src/index.server.ts && madge --circular src/index.types.ts",
+ "clean": "rimraf build coverage sentry-react-router-*.tgz",
+ "fix": "eslint . --format stylish --fix",
+ "lint": "eslint . --format stylish",
+ "test": "yarn test:unit",
+ "test:unit": "vitest run",
+ "test:watch": "vitest --watch",
+ "yalc:publish": "yalc publish --push --sig"
+ },
+ "volta": {
+ "extends": "../../package.json"
+ }
+}
diff --git a/packages/react-router/rollup.npm.config.mjs b/packages/react-router/rollup.npm.config.mjs
new file mode 100644
index 000000000000..65e6b0a0dd9a
--- /dev/null
+++ b/packages/react-router/rollup.npm.config.mjs
@@ -0,0 +1,22 @@
+import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollup-utils';
+
+export default [
+ ...makeNPMConfigVariants(
+ makeBaseNPMConfig({
+ entrypoints: ['src/index.server.ts', 'src/index.client.ts'],
+ packageSpecificConfig: {
+ external: ['react-router', 'react-router-dom', 'react', 'react/jsx-runtime'],
+ output: {
+ // make it so Rollup calms down about the fact that we're combining default and named exports
+ exports: 'named',
+ },
+ },
+ sucrase: {
+ // React 19 emits a warning if we don't use the newer jsx transform: https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html
+ // but this breaks react 17, so we keep it at `classic` for now
+ jsxRuntime: 'classic',
+ production: true, // This is needed so that sucrase uses the production jsx runtime (ie `import { jsx } from 'react/jsx-runtime'` instead of `import { jsxDEV as _jsxDEV } from 'react/jsx-dev-runtime'`)
+ },
+ }),
+ ),
+];
diff --git a/packages/react-router/src/client/index.ts b/packages/react-router/src/client/index.ts
new file mode 100644
index 000000000000..8e25b84c4a0c
--- /dev/null
+++ b/packages/react-router/src/client/index.ts
@@ -0,0 +1,3 @@
+export * from '@sentry/browser';
+
+export { init } from './sdk';
diff --git a/packages/react-router/src/client/sdk.ts b/packages/react-router/src/client/sdk.ts
new file mode 100644
index 000000000000..688a8ba460f1
--- /dev/null
+++ b/packages/react-router/src/client/sdk.ts
@@ -0,0 +1,21 @@
+import type { BrowserOptions } from '@sentry/browser';
+import { init as browserInit } from '@sentry/browser';
+import type { Client } from '@sentry/core';
+import { applySdkMetadata, setTag } from '@sentry/core';
+
+/**
+ * Initializes the client side of the React Router SDK.
+ */
+export function init(options: BrowserOptions): Client | undefined {
+ const opts = {
+ ...options,
+ };
+
+ applySdkMetadata(opts, 'react-router', ['react-router', 'browser']);
+
+ const client = browserInit(opts);
+
+ setTag('runtime', 'browser');
+
+ return client;
+}
diff --git a/packages/react-router/src/common/debug-build.ts b/packages/react-router/src/common/debug-build.ts
new file mode 100644
index 000000000000..60aa50940582
--- /dev/null
+++ b/packages/react-router/src/common/debug-build.ts
@@ -0,0 +1,8 @@
+declare const __DEBUG_BUILD__: boolean;
+
+/**
+ * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.
+ *
+ * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking.
+ */
+export const DEBUG_BUILD = __DEBUG_BUILD__;
diff --git a/packages/react-router/src/index.client.ts b/packages/react-router/src/index.client.ts
new file mode 100644
index 000000000000..4f1cce44fa36
--- /dev/null
+++ b/packages/react-router/src/index.client.ts
@@ -0,0 +1 @@
+export * from './client';
diff --git a/packages/react-router/src/index.server.ts b/packages/react-router/src/index.server.ts
new file mode 100644
index 000000000000..0ce5251aa327
--- /dev/null
+++ b/packages/react-router/src/index.server.ts
@@ -0,0 +1 @@
+export * from './server';
diff --git a/packages/react-router/src/index.types.ts b/packages/react-router/src/index.types.ts
new file mode 100644
index 000000000000..8d246451eb7d
--- /dev/null
+++ b/packages/react-router/src/index.types.ts
@@ -0,0 +1,16 @@
+// re-define colliding type exports below
+
+export * from './client';
+export * from './server';
+
+import type { Integration, Options, StackParser } from '@sentry/core';
+import type * as clientSdk from './client';
+import type * as serverSdk from './server';
+
+/** Initializes Sentry React Router SDK */
+export declare function init(options: Options | clientSdk.BrowserOptions | serverSdk.NodeOptions): void;
+
+export declare const contextLinesIntegration: typeof clientSdk.contextLinesIntegration;
+export declare const linkedErrorsIntegration: typeof clientSdk.linkedErrorsIntegration;
+export declare const defaultStackParser: StackParser;
+export declare const getDefaultIntegrations: (options: Options) => Integration[];
diff --git a/packages/react-router/src/server/index.ts b/packages/react-router/src/server/index.ts
new file mode 100644
index 000000000000..6ac8d97b4241
--- /dev/null
+++ b/packages/react-router/src/server/index.ts
@@ -0,0 +1,3 @@
+export * from '@sentry/node';
+
+export { init } from './sdk';
diff --git a/packages/react-router/src/server/sdk.ts b/packages/react-router/src/server/sdk.ts
new file mode 100644
index 000000000000..bae99dee4983
--- /dev/null
+++ b/packages/react-router/src/server/sdk.ts
@@ -0,0 +1,20 @@
+import { applySdkMetadata, setTag } from '@sentry/core';
+import type { NodeClient, NodeOptions } from '@sentry/node';
+import { init as initNodeSdk } from '@sentry/node';
+
+/**
+ * Initializes the server side of the React Router SDK
+ */
+export function init(options: NodeOptions): NodeClient | undefined {
+ const opts = {
+ ...options,
+ };
+
+ applySdkMetadata(opts, 'react-router', ['react-router', 'node']);
+
+ const client = initNodeSdk(opts);
+
+ setTag('runtime', 'node');
+
+ return client;
+}
diff --git a/packages/react-router/test/client/sdk.test.ts b/packages/react-router/test/client/sdk.test.ts
new file mode 100644
index 000000000000..e63fe0cf51cf
--- /dev/null
+++ b/packages/react-router/test/client/sdk.test.ts
@@ -0,0 +1,47 @@
+import { afterEach, describe, expect, it, vi } from 'vitest';
+
+import * as SentryBrowser from '@sentry/browser';
+import { SDK_VERSION, getCurrentScope, getGlobalScope, getIsolationScope } from '@sentry/browser';
+
+import { init as reactRouterInit } from '../../src/client';
+
+const browserInit = vi.spyOn(SentryBrowser, 'init');
+
+describe('React Router client SDK', () => {
+ describe('init', () => {
+ afterEach(() => {
+ vi.clearAllMocks();
+
+ getGlobalScope().clear();
+ getIsolationScope().clear();
+ getCurrentScope().clear();
+ getCurrentScope().setClient(undefined);
+ });
+
+ it('adds React Router metadata to the SDK options', () => {
+ expect(browserInit).not.toHaveBeenCalled();
+
+ reactRouterInit({});
+
+ const expectedMetadata = {
+ _metadata: {
+ sdk: {
+ name: 'sentry.javascript.react-router',
+ version: SDK_VERSION,
+ packages: [
+ { name: 'npm:@sentry/react-router', version: SDK_VERSION },
+ { name: 'npm:@sentry/browser', version: SDK_VERSION },
+ ],
+ },
+ },
+ };
+
+ expect(browserInit).toHaveBeenCalledTimes(1);
+ expect(browserInit).toHaveBeenCalledWith(expect.objectContaining(expectedMetadata));
+ });
+
+ it('returns client from init', () => {
+ expect(reactRouterInit({})).not.toBeUndefined();
+ });
+ });
+});
diff --git a/packages/react-router/test/server/sdk.test.ts b/packages/react-router/test/server/sdk.test.ts
new file mode 100644
index 000000000000..06ff871d07f9
--- /dev/null
+++ b/packages/react-router/test/server/sdk.test.ts
@@ -0,0 +1,48 @@
+import { afterEach, describe, expect, it, vi } from 'vitest';
+
+import * as SentryNode from '@sentry/node';
+
+import { SDK_VERSION } from '@sentry/node';
+
+import { init as reactRouterInit } from '../../src/server/sdk';
+
+const nodeInit = vi.spyOn(SentryNode, 'init');
+
+describe('React Router server SDK', () => {
+ describe('init', () => {
+ afterEach(() => {
+ vi.clearAllMocks();
+
+ SentryNode.getGlobalScope().clear();
+ SentryNode.getIsolationScope().clear();
+ SentryNode.getCurrentScope().clear();
+ SentryNode.getCurrentScope().setClient(undefined);
+ });
+
+ it('adds React Router metadata to the SDK options', () => {
+ expect(nodeInit).not.toHaveBeenCalled();
+
+ reactRouterInit({});
+
+ expect(nodeInit).toHaveBeenCalledTimes(1);
+ expect(nodeInit).toHaveBeenCalledWith(
+ expect.objectContaining({
+ _metadata: {
+ sdk: {
+ name: 'sentry.javascript.react-router',
+ version: SDK_VERSION,
+ packages: [
+ { name: 'npm:@sentry/react-router', version: SDK_VERSION },
+ { name: 'npm:@sentry/node', version: SDK_VERSION },
+ ],
+ },
+ },
+ }),
+ );
+ });
+
+ it('returns client from init', () => {
+ expect(reactRouterInit({})).not.toBeUndefined();
+ });
+ });
+});
diff --git a/packages/react-router/test/tsconfig.json b/packages/react-router/test/tsconfig.json
new file mode 100644
index 000000000000..120c3aff3716
--- /dev/null
+++ b/packages/react-router/test/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "../tsconfig.test.json",
+}
diff --git a/packages/react-router/tsconfig.json b/packages/react-router/tsconfig.json
new file mode 100644
index 000000000000..b0eb9ecb6476
--- /dev/null
+++ b/packages/react-router/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../tsconfig.json",
+
+ "include": ["src/**/*"],
+
+ "compilerOptions": {}
+}
diff --git a/packages/react-router/tsconfig.test.json b/packages/react-router/tsconfig.test.json
new file mode 100644
index 000000000000..b3625cd0bd3f
--- /dev/null
+++ b/packages/react-router/tsconfig.test.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.json",
+
+ "include": ["test/**/*", "vite.config.ts"],
+
+ "compilerOptions": {
+ "types": ["node", "vitest/globals"],
+ }
+}
diff --git a/packages/react-router/tsconfig.types.json b/packages/react-router/tsconfig.types.json
new file mode 100644
index 000000000000..65455f66bd75
--- /dev/null
+++ b/packages/react-router/tsconfig.types.json
@@ -0,0 +1,10 @@
+{
+ "extends": "./tsconfig.json",
+
+ "compilerOptions": {
+ "declaration": true,
+ "declarationMap": true,
+ "emitDeclarationOnly": true,
+ "outDir": "build/types"
+ }
+}
diff --git a/packages/react-router/vite.config.ts b/packages/react-router/vite.config.ts
new file mode 100644
index 000000000000..1094fe0d79da
--- /dev/null
+++ b/packages/react-router/vite.config.ts
@@ -0,0 +1,9 @@
+import baseConfig from '../../vite/vite.config';
+
+export default {
+ ...baseConfig,
+ test: {
+ ...baseConfig.test,
+ environment: 'jsdom',
+ },
+};
diff --git a/scripts/ci-unit-tests.ts b/scripts/ci-unit-tests.ts
index 13cbc6957d5c..cd53df2dfd68 100644
--- a/scripts/ci-unit-tests.ts
+++ b/scripts/ci-unit-tests.ts
@@ -4,6 +4,7 @@ import * as path from 'path';
const UNIT_TEST_ENV = process.env.UNIT_TEST_ENV as 'node' | 'browser' | undefined;
const RUN_AFFECTED = process.argv.includes('--affected');
+const NODE_VERSION = process.env.NODE_VERSION as '18' | '20' | '22';
// These packages are tested separately in CI, so no need to run them here
const DEFAULT_SKIP_PACKAGES = ['@sentry/bun', '@sentry/deno'];
@@ -25,6 +26,9 @@ const BROWSER_TEST_PACKAGES = [
'@sentry/wasm',
];
+// Packages that cannot run in Node 18
+const SKIP_NODE_18_PACKAGES = ['@sentry/react-router'];
+
function getAllPackages(): string[] {
const { workspaces }: { workspaces: string[] } = JSON.parse(
fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8'),
@@ -55,6 +59,10 @@ function runTests(): void {
});
} else if (UNIT_TEST_ENV === 'node') {
BROWSER_TEST_PACKAGES.forEach(pkg => ignores.add(pkg));
+
+ if (NODE_VERSION === '18') {
+ SKIP_NODE_18_PACKAGES.forEach(pkg => ignores.add(pkg));
+ }
}
if (RUN_AFFECTED) {
diff --git a/yarn.lock b/yarn.lock
index 21615559f6dc..f1e8c2068fdb 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4759,6 +4759,11 @@
semver "^7.3.5"
tar "^6.1.11"
+"@mjackson/node-fetch-server@^0.2.0":
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/@mjackson/node-fetch-server/-/node-fetch-server-0.2.0.tgz#577c0c25d8aae9f69a97738b7b0d03d1471cdc49"
+ integrity sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng==
+
"@nestjs/common@10.4.6":
version "10.4.6"
resolved "https://registry.yarnpkg.com/@nestjs/common/-/common-10.4.6.tgz#952e8fd0ceafeffcc4eaf47effd67fb395844ae0"
@@ -6162,6 +6167,16 @@
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
+"@react-router/node@^7.1.5":
+ version "7.1.5"
+ resolved "https://registry.yarnpkg.com/@react-router/node/-/node-7.1.5.tgz#fe4bdb708bb574cbf21b359d1263f6accde737bd"
+ integrity sha512-Ga8xFHxO2yt5TpGwV5xYx4LC3eUDmhT6jYfTbMFb6F7hBA9sLdHxNfYZCe2WEfVZ4/BM7I8989Qzq6BWilV2LA==
+ dependencies:
+ "@mjackson/node-fetch-server" "^0.2.0"
+ source-map-support "^0.5.21"
+ stream-slice "^0.1.2"
+ undici "^6.19.2"
+
"@redis/bloom@1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@redis/bloom/-/bloom-1.2.0.tgz#d3fd6d3c0af3ef92f26767b56414a370c7b63b71"
@@ -12604,6 +12619,11 @@ cookie@^0.6.0:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
+cookie@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.0.2.tgz#27360701532116bd3f1f9416929d176afe1e4610"
+ integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==
+
cookie@~0.7.2:
version "0.7.2"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7"
@@ -25243,6 +25263,16 @@ react-router@6.28.1:
dependencies:
"@remix-run/router" "1.21.0"
+react-router@^7.1.5:
+ version "7.1.5"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-7.1.5.tgz#c9e19d329d9ce2215fdae844ab6b023b911094db"
+ integrity sha512-8BUF+hZEU4/z/JD201yK6S+UYhsf58bzYIDq2NS1iGpwxSXDu7F+DeGSkIXMFBuHZB21FSiCzEcUb18cQNdRkA==
+ dependencies:
+ "@types/cookie" "^0.6.0"
+ cookie "^1.0.1"
+ set-cookie-parser "^2.6.0"
+ turbo-stream "2.4.0"
+
react@^18.0.0:
version "18.0.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.0.0.tgz#b468736d1f4a5891f38585ba8e8fb29f91c3cb96"
@@ -28908,6 +28938,11 @@ undici@^6.11.1:
resolved "https://registry.yarnpkg.com/undici/-/undici-6.21.0.tgz#4b3d3afaef984e07b48e7620c34ed8a285ed4cd4"
integrity sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==
+undici@^6.19.2:
+ version "6.21.1"
+ resolved "https://registry.yarnpkg.com/undici/-/undici-6.21.1.tgz#336025a14162e6837e44ad7b819b35b6c6af0e05"
+ integrity sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==
+
unenv@^1.10.0, unenv@^1.9.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/unenv/-/unenv-1.10.0.tgz#c3394a6c6e4cfe68d699f87af456fe3f0db39571"