From 78be8c0b8d4dc6fed039c69744bf820341ada77a Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Wed, 16 Jul 2025 08:35:08 +0200 Subject: [PATCH 01/18] feat: simple sentry implementation --- .env.template | 3 ++ package-lock.json | 93 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 ++- src/App.tsx | 2 +- src/AppRouter.tsx | 12 +----- src/mount.ts | 8 ++++ 6 files changed, 110 insertions(+), 13 deletions(-) diff --git a/.env.template b/.env.template index 7c300da0..af3c57b3 100644 --- a/.env.template +++ b/.env.template @@ -1,3 +1,6 @@ +# Sentry DSN +VITE_SENTRY_DSN= + # OpenID Connect Configuration for Onboarding API OIDC_ISSUER= OIDC_CLIENT_ID= diff --git a/package-lock.json b/package-lock.json index f20fecc0..731bc7cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@fastify/static": "^8.1.1", "@fastify/vite": "^8.1.3", "@hookform/resolvers": "^5.0.0", + "@sentry/react": "^9.39.0", "@ui5/webcomponents": "^2.7.2", "@ui5/webcomponents-fiori": "^2.7.2", "@ui5/webcomponents-icons": "^2.7.2", @@ -3047,6 +3048,98 @@ "integrity": "sha512-0LVCUYqoTQGcKmgPShbxQLBoF8469ZojUrYtVm1k3op/1pgLA/FMN//bvgGEm7HTBJBu3gW2Ad2f4ASqEzLolA==", "license": "Apache-2.0" }, + "node_modules/@sentry-internal/browser-utils": { + "version": "9.39.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.39.0.tgz", + "integrity": "sha512-f1qUAftQ/aMTJHJDCG9jDJIwLEkSVZ6xWGn2xQMj7PfD1uuYlTy3KHn+wPy1VlPJTZQ44WclTPnY2U/OBIPmsg==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.39.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "9.39.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.39.0.tgz", + "integrity": "sha512-IvD2LDKFderPn6pXN6N8cFJWWIXUADys9WRtfh1CK8DIuU1fXYi61tO23Z+sCsvXReQgr/mdJg5dHa0qY/vDww==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.39.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "9.39.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.39.0.tgz", + "integrity": "sha512-6mweqQtfcVG2+FEPjmgjrpCThgs9bR2cmQM2Ew/SlINj8ETq5P/7Z3rdIp+Zs7LArXFIJUA7KX9ZW+noVPI8Gg==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "9.39.0", + "@sentry/core": "9.39.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "9.39.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.39.0.tgz", + "integrity": "sha512-rTw0WZuAwzo36/hXRSuftu7e3qtwXc+bSs1q7M+w7Tb98aoOyXs3GlnYmgP6q3t2v/h7zoIiQcfjnPqo6+DVtQ==", + "license": "MIT", + "dependencies": { + "@sentry-internal/replay": "9.39.0", + "@sentry/core": "9.39.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/browser": { + "version": "9.39.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.39.0.tgz", + "integrity": "sha512-RZ4Zp22ohFLwkR3y6pmSWDrPVP7ErX0ClNOh2Kal3TNWlOGb4WPBPaWj2tiOvc4n/l6EDYaFvQ0Hh8RhesB98A==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "9.39.0", + "@sentry-internal/feedback": "9.39.0", + "@sentry-internal/replay": "9.39.0", + "@sentry-internal/replay-canvas": "9.39.0", + "@sentry/core": "9.39.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/core": { + "version": "9.39.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.39.0.tgz", + "integrity": "sha512-9Z32C64rUGEI0ROxXXOtpJDaldPYtkzOQyGzToVgq5LefXkdgQInd8BhCt6PIBALfj7n25lLOYllTrHlboFJug==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/react": { + "version": "9.39.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.39.0.tgz", + "integrity": "sha512-oSc0ReVM9ZCJqDs7IDS//hVg+29SynmnufBUpDKETXiq2+1B6UXcVM2Vq2pIJHD03v1UMalTp2HIb6S3NROUUQ==", + "license": "MIT", + "dependencies": { + "@sentry/browser": "9.39.0", + "@sentry/core": "9.39.0", + "hoist-non-react-statics": "^3.3.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, "node_modules/@standard-schema/utils": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", diff --git a/package.json b/package.json index 9462b941..47266c6e 100644 --- a/package.json +++ b/package.json @@ -24,12 +24,13 @@ "@fastify/cookie": "^11.0.2", "@fastify/env": "^5.0.2", "@fastify/http-proxy": "^11.1.2", - "@fastify/sensible": "^6.0.3", "@fastify/secure-session": "^8.2.0", + "@fastify/sensible": "^6.0.3", "@fastify/session": "^11.1.0", "@fastify/static": "^8.1.1", "@fastify/vite": "^8.1.3", "@hookform/resolvers": "^5.0.0", + "@sentry/react": "^9.39.0", "@ui5/webcomponents": "^2.7.2", "@ui5/webcomponents-fiori": "^2.7.2", "@ui5/webcomponents-icons": "^2.7.2", @@ -84,4 +85,4 @@ "vite": "^6.3.4", "vitest": "^3.1.4" } -} \ No newline at end of file +} diff --git a/src/App.tsx b/src/App.tsx index 8bdcca23..1340ad4d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,7 +14,7 @@ function App() { if (frontendConfig && frontendConfig.landscape) { document.title = `[${frontendConfig.landscape}] MCP`; } - }, []); + }, [frontendConfig]); if (auth.isLoading) { return ; diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx index 37ab5dad..9eae5788 100644 --- a/src/AppRouter.tsx +++ b/src/AppRouter.tsx @@ -1,9 +1,4 @@ -import { - HashRouter as Router, - Navigate, - Route, - Routes, -} from 'react-router-dom'; +import { HashRouter as Router, Navigate, Route, Routes } from 'react-router-dom'; import ControlPlaneView from './views/ControlPlanes/ControlPlaneView.tsx'; import ProjectListView from './views/ProjectList'; import ControlPlaneListView from './views/ControlPlanes/ControlPlaneListView.tsx'; @@ -18,10 +13,7 @@ function AppRouter() { }> } /> - } - /> + } /> } diff --git a/src/mount.ts b/src/mount.ts index 394f3425..46352b8a 100644 --- a/src/mount.ts +++ b/src/mount.ts @@ -1,5 +1,13 @@ import { createRoot } from 'react-dom/client'; import { createApp } from './main.tsx'; +import * as Sentry from '@sentry/react'; + +Sentry.init({ + dsn: import.meta.env.VITE_SENTRY_DSN, + // Setting this option to true will send default PII data to Sentry. + // For example, automatic IP address collection on events + sendDefaultPii: true, +}); const root = createRoot(document.getElementById('root')!); root.render(createApp()); From fc68756b69e6a666ff2cfdb81d62601c2950dd78 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Wed, 16 Jul 2025 13:41:30 +0200 Subject: [PATCH 02/18] feat: integrate Sentry for error tracking and performance monitoring - Added @sentry/vite-plugin to package.json for Vite integration. - Wrapped the main App component with Sentry's withProfiler for performance monitoring. - Updated AppRouter to use SentryRoutes for enhanced routing error tracking. - Initialized Sentry in mount.ts with environment and PII settings. - Added breadcrumbs for user authentication events in AuthContextOnboarding. - Logged breadcrumb for visiting the Login page in LoginView. - Configured Vite to include Sentry plugin and enabled sourcemaps for better debugging. --- .env.template | 8 +- .gitignore | 3 + package-lock.json | 537 ++++++++++++++++-- package.json | 1 + src/App.tsx | 7 +- src/AppRouter.tsx | 5 +- src/mount.ts | 39 +- .../onboarding/auth/AuthContextOnboarding.tsx | 6 + src/views/Login.tsx | 7 + vite.config.js | 18 +- 10 files changed, 569 insertions(+), 62 deletions(-) diff --git a/.env.template b/.env.template index af3c57b3..e119b69c 100644 --- a/.env.template +++ b/.env.template @@ -1,5 +1,4 @@ -# Sentry DSN -VITE_SENTRY_DSN= +VITE_ENVIRONMENT= # OpenID Connect Configuration for Onboarding API OIDC_ISSUER= @@ -10,11 +9,9 @@ OIDC_REDIRECT_URI=http://localhost:5173 POST_LOGIN_REDIRECT=http://localhost:5173 - # Location of the API Backend API_BACKEND_URL= - # Cookie Secret # Replace this value with a strong, randomly generated string (at least 32 characters). # Example for generation in Node.js: require('crypto').randomBytes(32).toString('hex') @@ -23,3 +20,6 @@ SESSION_SECRET= FEEDBACK_SLACK_URL= FEEDBACK_URL_LINK= + +# Sentry DSN +VITE_SENTRY_DSN= diff --git a/.gitignore b/.gitignore index dd3db9dd..ed12b496 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ notes.md tmp/ public/frontend-config.json + +# Sentry Config File +.env.sentry-build-plugin diff --git a/package-lock.json b/package-lock.json index 731bc7cb..2c60bf63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@fastify/vite": "^8.1.3", "@hookform/resolvers": "^5.0.0", "@sentry/react": "^9.39.0", + "@sentry/vite-plugin": "^3.6.0", "@ui5/webcomponents": "^2.7.2", "@ui5/webcomponents-fiori": "^2.7.2", "@ui5/webcomponents-icons": "^2.7.2", @@ -83,7 +84,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -178,7 +178,6 @@ "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -188,7 +187,6 @@ "version": "7.27.4", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", - "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", @@ -219,7 +217,6 @@ "version": "7.27.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.27.5", @@ -236,7 +233,6 @@ "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.27.2", @@ -253,7 +249,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.27.1", @@ -267,7 +262,6 @@ "version": "7.27.3", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.27.1", @@ -295,7 +289,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -314,7 +307,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -324,7 +316,6 @@ "version": "7.27.6", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", - "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", @@ -338,7 +329,6 @@ "version": "7.27.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.27.3" @@ -411,7 +401,6 @@ "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -426,7 +415,6 @@ "version": "7.27.4", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", - "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", @@ -445,7 +433,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -455,7 +442,6 @@ "version": "7.27.6", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -2603,7 +2589,6 @@ "version": "0.3.8", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -2618,7 +2603,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -2628,7 +2612,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -2638,14 +2621,12 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -3098,6 +3079,15 @@ "node": ">=18" } }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.6.0.tgz", + "integrity": "sha512-QjqqaNghVSPercSU1sA8WcZtka/cHCShU6z38Fi41P/n9HpfxLFv6aBV03kqH5m1uLOPCl+u3AUm3HGMgGYQjg==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/@sentry/browser": { "version": "9.39.0", "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.39.0.tgz", @@ -3114,6 +3104,327 @@ "node": ">=18" } }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.6.0.tgz", + "integrity": "sha512-26+cLguEtBBtsYi3NIwU6X/UvOPJM9tGm9ciDWYgMFvFIk8hhi0iuffAC6WsDWRebVYXTlA7RS/VGJG/T+1Zcw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "3.6.0", + "@sentry/cli": "^2.46.0", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^9.3.2", + "magic-string": "0.30.8", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/@sentry/cli": { + "version": "2.47.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.47.1.tgz", + "integrity": "sha512-t45lfyyMYs6L1oFUmtYuLDJFf0o6a0IGbPJvzOZcP3lmidouEG5nloBF6FG39AkL29pwrS2WN41j2gyDjrQ71g==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.47.1", + "@sentry/cli-linux-arm": "2.47.1", + "@sentry/cli-linux-arm64": "2.47.1", + "@sentry/cli-linux-i686": "2.47.1", + "@sentry/cli-linux-x64": "2.47.1", + "@sentry/cli-win32-arm64": "2.47.1", + "@sentry/cli-win32-i686": "2.47.1", + "@sentry/cli-win32-x64": "2.47.1" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.47.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.47.1.tgz", + "integrity": "sha512-Vq+8Hs1AR5MFYCI8vkz+rdRJmcNgUf8b8dW8aSLYCHy7wS/X61OB00LupLaaaoN5c/xemb0rZCg4M0ftUqB5Kw==", + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.47.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.47.1.tgz", + "integrity": "sha512-Wkcvr0LYP1XMSoaczQnUtOSZPfyBzdGk7wQyloYWyMv9oZWJYkt1wYI0/FaNM+MIX15RqEAx0nI5CjotLMlj8w==", + "cpu": [ + "arm" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.47.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.47.1.tgz", + "integrity": "sha512-Kuda8/BFMVyqYayQjP0NQnxnAz5Xpfo2crG1/RRXF9lYQ9O/5YRb3dvlMPX6WasplCzajaSuLrYt/LXcs4McwA==", + "cpu": [ + "arm64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.47.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.47.1.tgz", + "integrity": "sha512-WB3FbRjeJmKHhGc5CftaFFJfFc7c+Mu/XKwbI8Es/9f65bVWdB6BA2tH7aHyoAQngA++1ZVXUJwUpxYPNxQEag==", + "cpu": [ + "x86", + "ia32" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.47.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.47.1.tgz", + "integrity": "sha512-C+3GJLDpZQMO45toUKiF4bPZpxQiU5/10LtZg2vhpUyyzFGNseVQO/Bsnu9hG/LVjYGLkTgEaorl1liRQsfKVg==", + "cpu": [ + "x64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-arm64": { + "version": "2.47.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.47.1.tgz", + "integrity": "sha512-K3yb1yLvA6Lh0UaXjsU6lP/2uOMkZ47cVq0dFxL/hEr4fBHRkXuvg3oOJNDkJ2xXt2W2s7AIa83T2EisZ0a/NQ==", + "cpu": [ + "arm64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.47.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.47.1.tgz", + "integrity": "sha512-wk+6IIT+VT28c9uPe9PDzxdh+OiTEDb/0PIdFv1khSfAmEuVSNWzuDWsra7MnA7OPfgzzNDPkP4HRW1CKb3Xiw==", + "cpu": [ + "x86", + "ia32" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.47.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.47.1.tgz", + "integrity": "sha512-blseDhuUJDsb+3Ku9dvR4b0JO4nunRokF/9jzW+qHqTha7UHE2kQYXkCfsoDg65juvJFeKeQASYV7VphEJgIGQ==", + "cpu": [ + "x64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@sentry/cli/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@sentry/cli/node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/@sentry/core": { "version": "9.39.0", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.39.0.tgz", @@ -3140,6 +3451,19 @@ "react": "^16.14.0 || 17.x || 18.x || 19.x" } }, + "node_modules/@sentry/vite-plugin": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-3.6.0.tgz", + "integrity": "sha512-gayOzM64kRujYGEPNB9xvQWKVXmJAo0WW9R25XwYXvTkjKpwT/ue3id5Dw4L6GUpj3AfF/qE+ghhY4r3mHkoiw==", + "license": "MIT", + "dependencies": { + "@sentry/bundler-plugin-core": "3.6.0", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/@standard-schema/utils": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", @@ -4420,7 +4744,6 @@ "version": "8.14.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -4569,6 +4892,28 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -5053,6 +5398,18 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -5180,7 +5537,6 @@ "version": "4.24.5", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5367,7 +5723,6 @@ "version": "1.0.30001718", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5534,6 +5889,51 @@ "node": ">= 0.8.0" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chokidar/node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ci-info": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", @@ -5820,7 +6220,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, "license": "MIT" }, "node_modules/cookie": { @@ -6192,7 +6591,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -6431,7 +6829,6 @@ "version": "1.5.155", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz", "integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==", - "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { @@ -6766,7 +7163,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -8051,9 +8447,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -8212,6 +8606,12 @@ "node": ">=14.14" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -8271,7 +8671,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -9264,6 +9663,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", @@ -9904,7 +10315,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -9993,7 +10403,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" @@ -10213,9 +10622,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -10366,7 +10773,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^3.0.2" @@ -10556,7 +10962,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/mute-stream": { @@ -10653,7 +11058,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" @@ -10681,7 +11085,6 @@ "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, "license": "MIT" }, "node_modules/normalize-path": { @@ -10995,9 +11398,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -11141,9 +11542,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -11575,6 +11974,15 @@ ], "license": "MIT" }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", @@ -11919,6 +12327,18 @@ "node": ">= 6" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -12840,7 +13260,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -13874,7 +14293,6 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, "license": "MIT" }, "node_modules/tree-kill": { @@ -14238,6 +14656,18 @@ "node": ">= 0.8" } }, + "node_modules/unplugin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", + "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==", + "license": "MIT", + "dependencies": { + "acorn": "^8.8.1", + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.5.0" + } + }, "node_modules/unrs-resolver": { "version": "1.7.13", "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.7.13.tgz", @@ -14285,7 +14715,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -14647,9 +15076,23 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, "license": "BSD-2-Clause" }, + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", + "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "license": "MIT" + }, "node_modules/whatwg-mimetype": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", @@ -14663,7 +15106,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, "license": "MIT", "dependencies": { "tr46": "~0.0.3", @@ -14885,7 +15327,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, "license": "ISC" }, "node_modules/yaml": { diff --git a/package.json b/package.json index 47266c6e..5dc956e4 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@fastify/vite": "^8.1.3", "@hookform/resolvers": "^5.0.0", "@sentry/react": "^9.39.0", + "@sentry/vite-plugin": "^3.6.0", "@ui5/webcomponents": "^2.7.2", "@ui5/webcomponents-fiori": "^2.7.2", "@ui5/webcomponents-icons": "^2.7.2", diff --git a/src/App.tsx b/src/App.tsx index 1340ad4d..1d2a4920 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,6 +5,7 @@ import { useEffect } from 'react'; import { useFrontendConfig } from './context/FrontendConfigContext.tsx'; import LoginView from './views/Login.tsx'; import { BusyIndicator } from '@ui5/webcomponents-react'; +import * as Sentry from '@sentry/react'; function App() { const auth = useAuthOnboarding(); @@ -24,7 +25,11 @@ function App() { return ; } + Sentry.setUser({ + email: auth.user?.email, + }); + return ; } -export default App; +export default Sentry.withProfiler(App); diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx index 9eae5788..bfa936c3 100644 --- a/src/AppRouter.tsx +++ b/src/AppRouter.tsx @@ -4,13 +4,14 @@ import ProjectListView from './views/ProjectList'; import ControlPlaneListView from './views/ControlPlanes/ControlPlaneListView.tsx'; import GlobalProviderOutlet from './components/Core/ApiConfigWrapper.tsx'; import { ShellBarComponent } from './components/Core/ShellBar.tsx'; +import { SentryRoutes } from './mount.ts'; function AppRouter() { return ( <> - + }> } /> } /> @@ -20,7 +21,7 @@ function AppRouter() { /> } /> - + ); diff --git a/src/mount.ts b/src/mount.ts index 46352b8a..801278f2 100644 --- a/src/mount.ts +++ b/src/mount.ts @@ -1,13 +1,40 @@ import { createRoot } from 'react-dom/client'; import { createApp } from './main.tsx'; import * as Sentry from '@sentry/react'; +import React from 'react'; +import { + Routes, + Route, + BrowserRouter, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, +} from 'react-router-dom'; -Sentry.init({ - dsn: import.meta.env.VITE_SENTRY_DSN, - // Setting this option to true will send default PII data to Sentry. - // For example, automatic IP address collection on events - sendDefaultPii: true, -}); +let sentryRoutes = Routes; +if (import.meta.env.VITE_SENTRY_DSN.length > 0) { + Sentry.init({ + dsn: import.meta.env.VITE_SENTRY_DSN, + // Setting this option to true will send default PII data to Sentry. + // For example, automatic IP address collection on events + sendDefaultPii: true, + environment: import.meta.env.VITE_ENVIRONMENT, + integrations: [ + Sentry.reactRouterV7BrowserTracingIntegration({ + useEffect: React.useEffect, + useLocation, + useNavigationType, + createRoutesFromChildren, + matchRoutes, + }), + ], + }); + + sentryRoutes = Sentry.withSentryReactRouterV7Routing(Routes); +} + +export const SentryRoutes = sentryRoutes; const root = createRoot(document.getElementById('root')!); root.render(createApp()); diff --git a/src/spaces/onboarding/auth/AuthContextOnboarding.tsx b/src/spaces/onboarding/auth/AuthContextOnboarding.tsx index 3764ff37..bd5b7f71 100644 --- a/src/spaces/onboarding/auth/AuthContextOnboarding.tsx +++ b/src/spaces/onboarding/auth/AuthContextOnboarding.tsx @@ -57,6 +57,12 @@ export function AuthProviderOnboarding({ children }: { children: ReactNode }) { validationResult.data; setUser(apiUser); setIsAuthenticated(apiIsAuthenticated); + + Sentry.addBreadcrumb({ + category: 'auth', + message: 'Authenticated user ' + apiUser?.email, + level: 'info', + }); } catch (err) { setError(err instanceof Error ? err : new Error('Authentication error.')); setUser(null); diff --git a/src/views/Login.tsx b/src/views/Login.tsx index 9e825d46..8802a983 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -5,12 +5,19 @@ import './login.css'; import { ThemingParameters } from '@ui5/webcomponents-react-base'; import { useLink } from '../lib/shared/useLink.ts'; import { useTranslation } from 'react-i18next'; +import * as Sentry from '@sentry/react'; export default function LoginView() { const auth = useAuthOnboarding(); const { documentationHomepage } = useLink(); const { t } = useTranslation(); + Sentry.addBreadcrumb({ + category: 'auth', + message: 'Visit Login Page', + level: 'info', + }); + return ( Date: Wed, 16 Jul 2025 13:57:33 +0200 Subject: [PATCH 03/18] feat: integrate Sentry to BFF - Added Sentry for error tracking in server.js and configured it with DSN from environment variables. - Set up Sentry error handler for Fastify. - Enhanced authentication logging in auth-utils.js by adding breadcrumbs for successful user authentication. - Added Sentry breadcrumbs in http-proxy.js to track token refresh attempts and usage of crate. - Updated package.json to include Sentry dependencies. --- package-lock.json | 875 ++++++++++++++++++++++++++++++++++- package.json | 1 + server.js | 10 + server/encrypted-session.js | 4 +- server/plugins/auth-utils.js | 7 + server/plugins/http-proxy.js | 11 + 6 files changed, 900 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2c60bf63..0c281caa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@fastify/static": "^8.1.1", "@fastify/vite": "^8.1.3", "@hookform/resolvers": "^5.0.0", + "@sentry/node": "^9.39.0", "@sentry/react": "^9.39.0", "@sentry/vite-plugin": "^3.6.0", "@ui5/webcomponents": "^2.7.2", @@ -2730,6 +2731,567 @@ "node": ">= 8" } }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.2.tgz", + "integrity": "sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz", + "integrity": "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.2.tgz", + "integrity": "sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.57.2", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib": { + "version": "0.46.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.46.1.tgz", + "integrity": "sha512-AyXVnlCf/xV3K/rNumzKxZqsULyITJH6OVLiW6730JPRqWA7Zc9bvYoVNpN6iOpTU8CasH34SU/ksVJmObFibQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-connect": { + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.43.1.tgz", + "integrity": "sha512-ht7YGWQuV5BopMcw5Q2hXn3I8eG8TH0J/kc/GMcW4CuNTgiP6wCu44BOnucJWL3CmFWaRHI//vWyAhaC8BwePw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/connect": "3.4.38" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.16.1.tgz", + "integrity": "sha512-K/qU4CjnzOpNkkKO4DfCLSQshejRNAJtd4esgigo/50nxCB6XCyi1dhAblUHM9jG5dRm8eu0FB+t87nIo99LYQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-express": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.47.1.tgz", + "integrity": "sha512-QNXPTWteDclR2B4pDFpz0TNghgB33UMjUt14B+BZPmtH1MwUFAfLHBaP5If0Z5NZC+jaH8oF2glgYjrmhZWmSw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fs": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.19.1.tgz", + "integrity": "sha512-6g0FhB3B9UobAR60BGTcXg4IHZ6aaYJzp0Ki5FhnxyAPt8Ns+9SSvgcrnsN2eGmk3RWG5vYycUGOEApycQL24A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool": { + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.43.1.tgz", + "integrity": "sha512-M6qGYsp1cURtvVLGDrPPZemMFEbuMmCXgQYTReC/IbimV5sGrLBjB+/hANUpRZjX67nGLdKSVLZuQQAiNz+sww==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.47.1.tgz", + "integrity": "sha512-EGQRWMGqwiuVma8ZLAZnExQ7sBvbOx0N/AE/nlafISPs8S+QtXX+Viy6dcQwVWwYHQPAcuY3bFt3xgoAwb4ZNQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.45.2.tgz", + "integrity": "sha512-7Ehow/7Wp3aoyCrZwQpU7a2CnoMq0XhIcioFuKjBb0PLYfBfmTsFTUyatlHu0fRxhwcRsSQRTvEhmZu8CppBpQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.57.2.tgz", + "integrity": "sha512-1Uz5iJ9ZAlFOiPuwYg29Bf7bJJc/GeoeJIFKJYQf67nTVKFe8RHbEtxgkOmK4UGZNHKXcpW4P8cWBYzBn1USpg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/instrumentation": "0.57.2", + "@opentelemetry/semantic-conventions": "1.28.0", + "forwarded-parse": "2.1.2", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.47.1.tgz", + "integrity": "sha512-OtFGSN+kgk/aoKgdkKQnBsQFDiG8WdCxu+UrHr0bXScdAmtSzLSraLo7wFIb25RVHfRWvzI5kZomqJYEg/l1iA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-kafkajs": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.7.1.tgz", + "integrity": "sha512-OtjaKs8H7oysfErajdYr1yuWSjMAectT7Dwr+axIoZqT9lmEOkD/H/3rgAs8h/NIuEi2imSXD+vL4MZtOuJfqQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-knex": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.44.1.tgz", + "integrity": "sha512-U4dQxkNhvPexffjEmGwCq68FuftFK15JgUF05y/HlK3M6W/G2iEaACIfXdSnwVNe9Qh0sPfw8LbOPxrWzGWGMQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-koa": { + "version": "0.47.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.47.1.tgz", + "integrity": "sha512-l/c+Z9F86cOiPJUllUCt09v+kICKvT+Vg1vOAJHtHPsJIzurGayucfCMq2acd/A/yxeNWunl9d9eqZ0G+XiI6A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.44.1.tgz", + "integrity": "sha512-5MPkYCvG2yw7WONEjYj5lr5JFehTobW7wX+ZUFy81oF2lr9IPfZk9qO+FTaM0bGEiymwfLwKe6jE15nHn1nmHg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.52.0.tgz", + "integrity": "sha512-1xmAqOtRUQGR7QfJFfGV/M2kC7wmI2WgZdpru8hJl3S0r4hW0n3OQpEHlSGXJAaNFyvT+ilnwkT+g5L4ljHR6g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose": { + "version": "0.46.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.46.1.tgz", + "integrity": "sha512-3kINtW1LUTPkiXFRSSBmva1SXzS/72we/jL22N+BnF3DFcoewkdkHPYOIdAAk9gSicJ4d5Ojtt1/HeibEc5OQg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql": { + "version": "0.45.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.45.1.tgz", + "integrity": "sha512-TKp4hQ8iKQsY7vnp/j0yJJ4ZsP109Ht6l4RHTj0lNEG1TfgTrIH5vJMbgmoYXWzNHAqBH2e7fncN12p3BP8LFg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/mysql": "2.15.26" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.45.2.tgz", + "integrity": "sha512-h6Ad60FjCYdJZ5DTz1Lk2VmQsShiViKe0G7sYikb0GHI0NVvApp2XQNRHNjEMz87roFttGPLHOYVPlfy+yVIhQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.40.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg": { + "version": "0.51.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.51.1.tgz", + "integrity": "sha512-QxgjSrxyWZc7Vk+qGSfsejPVFL1AgAJdSBMYZdDUbwg730D09ub3PXScB9d04vIqPriZ+0dqzjmQx0yWKiCi2Q==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.26.0", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.40.1", + "@types/pg": "8.6.1", + "@types/pg-pool": "2.0.6" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-redis-4": { + "version": "0.46.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.46.1.tgz", + "integrity": "sha512-UMqleEoabYMsWoTkqyt9WAzXwZ4BlFZHO40wr3d5ZvtjKCHlD4YXLm+6OLCeIi/HkX7EXvQaz8gtAwkwwSEvcQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/redis-common": "^0.36.2", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.18.1.tgz", + "integrity": "sha512-5Cuy/nj0HBaH+ZJ4leuD7RjgvA844aY2WW+B5uLcWtxGjRZl3MNLuxnNg5DYWZNPO+NafSSnra0q49KWAHsKBg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/tedious": "^4.0.14" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.10.1.tgz", + "integrity": "sha512-rkOGikPEyRpMCmNu9AQuV5dtRlDmJp2dK5sw8roVshAGoB6hH/3QjDtRhdwd75SsJwgynWUNRUYe0wAkTo16tQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.8.0", + "@opentelemetry/instrumentation": "^0.57.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" + } + }, + "node_modules/@opentelemetry/instrumentation/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@opentelemetry/redis-common": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.36.2.tgz", + "integrity": "sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz", + "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.36.0.tgz", + "integrity": "sha512-TtxJSRD8Ohxp6bKkhrm27JRHAxPczQA7idtcTOMYI+wQRRrfgqxHv1cFbCApcSnNjtXkmzFozn6jQtFrOmbjPQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sql-common": { + "version": "0.40.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.40.1.tgz", + "integrity": "sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^1.1.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0" + } + }, "node_modules/@pkgr/core": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz", @@ -2743,6 +3305,18 @@ "url": "https://opencollective.com/pkgr" } }, + "node_modules/@prisma/instrumentation": { + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-6.11.1.tgz", + "integrity": "sha512-mrZOev24EDhnefmnZX7WVVT7v+r9LttPRqf54ONvj6re4XMF7wFTpK2tLJi4XHB7fFp/6xhYbgRel8YV7gQiyA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0 || ^0.57.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.8" + } + }, "node_modules/@repeaterjs/repeater": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.6.tgz", @@ -3434,6 +4008,119 @@ "node": ">=18" } }, + "node_modules/@sentry/node": { + "version": "9.39.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-9.39.0.tgz", + "integrity": "sha512-UDDT+yPvggrTcHqdGqnSQjEkyT982rFEAp5Zc8X/yKWSK8n6EA2kXIUe/M7293WtDuAvYsHY36tMqIalqGe1Ew==", + "license": "MIT", + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1", + "@opentelemetry/core": "^1.30.1", + "@opentelemetry/instrumentation": "^0.57.2", + "@opentelemetry/instrumentation-amqplib": "^0.46.1", + "@opentelemetry/instrumentation-connect": "0.43.1", + "@opentelemetry/instrumentation-dataloader": "0.16.1", + "@opentelemetry/instrumentation-express": "0.47.1", + "@opentelemetry/instrumentation-fs": "0.19.1", + "@opentelemetry/instrumentation-generic-pool": "0.43.1", + "@opentelemetry/instrumentation-graphql": "0.47.1", + "@opentelemetry/instrumentation-hapi": "0.45.2", + "@opentelemetry/instrumentation-http": "0.57.2", + "@opentelemetry/instrumentation-ioredis": "0.47.1", + "@opentelemetry/instrumentation-kafkajs": "0.7.1", + "@opentelemetry/instrumentation-knex": "0.44.1", + "@opentelemetry/instrumentation-koa": "0.47.1", + "@opentelemetry/instrumentation-lru-memoizer": "0.44.1", + "@opentelemetry/instrumentation-mongodb": "0.52.0", + "@opentelemetry/instrumentation-mongoose": "0.46.1", + "@opentelemetry/instrumentation-mysql": "0.45.1", + "@opentelemetry/instrumentation-mysql2": "0.45.2", + "@opentelemetry/instrumentation-pg": "0.51.1", + "@opentelemetry/instrumentation-redis-4": "0.46.1", + "@opentelemetry/instrumentation-tedious": "0.18.1", + "@opentelemetry/instrumentation-undici": "0.10.1", + "@opentelemetry/resources": "^1.30.1", + "@opentelemetry/sdk-trace-base": "^1.30.1", + "@opentelemetry/semantic-conventions": "^1.34.0", + "@prisma/instrumentation": "6.11.1", + "@sentry/core": "9.39.0", + "@sentry/node-core": "9.39.0", + "@sentry/opentelemetry": "9.39.0", + "import-in-the-middle": "^1.14.2", + "minimatch": "^9.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/node-core": { + "version": "9.39.0", + "resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-9.39.0.tgz", + "integrity": "sha512-e+D/5xharSysEqwjGOToI6zyn7zkuufwhO3n4jtqqjCXbSwI2zK9ARmn8ZLIdVnNETL+KZ82+5HRVhJWXxrpNg==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.39.0", + "@sentry/opentelemetry": "9.39.0", + "import-in-the-middle": "^1.14.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0", + "@opentelemetry/core": "^1.30.1 || ^2.0.0", + "@opentelemetry/instrumentation": "^0.57.1 || ^0.202.0", + "@opentelemetry/resources": "^1.30.1 || ^2.0.0", + "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0", + "@opentelemetry/semantic-conventions": "^1.34.0" + } + }, + "node_modules/@sentry/node/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@sentry/node/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/opentelemetry": { + "version": "9.39.0", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-9.39.0.tgz", + "integrity": "sha512-FaD+tMXFSdHIyjx1UumTXYayBT9PJHCM8nbTTRsMSlZYWoaSeAl6oO7N8djFVxNGU/mTJMCx2RvjKGI42GNFuA==", + "license": "MIT", + "dependencies": { + "@sentry/core": "9.39.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.0.0", + "@opentelemetry/core": "^1.30.1 || ^2.0.0", + "@opentelemetry/instrumentation": "^0.57.1 || ^0.202.0", + "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.0.0", + "@opentelemetry/semantic-conventions": "^1.34.0" + } + }, "node_modules/@sentry/react": { "version": "9.39.0", "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.39.0.tgz", @@ -3563,6 +4250,15 @@ "@types/deep-eql": "*" } }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", @@ -3616,6 +4312,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/mysql": { + "version": "2.15.26", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.26.tgz", + "integrity": "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "22.16.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.16.3.tgz", @@ -3635,6 +4340,26 @@ "@types/qunit": "^2.5.4" } }, + "node_modules/@types/pg": { + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", + "integrity": "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@types/pg-pool": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", + "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", + "license": "MIT", + "dependencies": { + "@types/pg": "*" + } + }, "node_modules/@types/qunit": { "version": "2.19.12", "resolved": "https://registry.npmjs.org/@types/qunit/-/qunit-2.19.12.tgz", @@ -3671,6 +4396,12 @@ "@types/react": "*" } }, + "node_modules/@types/shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", + "license": "MIT" + }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", @@ -3684,6 +4415,15 @@ "integrity": "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==", "license": "MIT" }, + "node_modules/@types/tedious": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", + "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -4752,6 +5492,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -5950,6 +6699,12 @@ "node": ">=8" } }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "license": "MIT" + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -8581,6 +9336,12 @@ "node": ">= 0.6" } }, + "node_modules/forwarded-parse": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "license": "MIT" + }, "node_modules/fresh": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", @@ -8630,7 +9391,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9189,7 +9949,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -9467,6 +10226,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-in-the-middle": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.14.2.tgz", + "integrity": "sha512-5tCuY9BV8ujfOpwtAGgsTx9CGUapcFMEEyByLv1B+v2+6DhAcw+Zr0nhQT7uwaZ7DiourxFEscghOR8e1aPLQw==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -9732,7 +10503,6 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -10958,6 +11728,12 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -11560,7 +12336,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, "license": "MIT" }, "node_modules/path-root": { @@ -11659,6 +12434,37 @@ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", "license": "MIT" }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz", + "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -11886,6 +12692,45 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -12517,6 +13362,20 @@ "node": ">=0.10.0" } }, + "node_modules/require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/requireindex": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", @@ -12531,7 +13390,6 @@ "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", @@ -13445,6 +14303,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause" + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -13971,7 +14835,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" diff --git a/package.json b/package.json index 5dc956e4..04ad626e 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@fastify/static": "^8.1.1", "@fastify/vite": "^8.1.3", "@hookform/resolvers": "^5.0.0", + "@sentry/node": "^9.39.0", "@sentry/react": "^9.39.0", "@sentry/vite-plugin": "^3.6.0", "@ui5/webcomponents": "^2.7.2", diff --git a/server.js b/server.js index 2734ac9c..4d9ac188 100644 --- a/server.js +++ b/server.js @@ -5,9 +5,17 @@ import path from 'node:path'; import dotenv from 'dotenv'; import proxy from './server/app.js'; import { copyFileSync } from 'node:fs'; +import * as Sentry from '@sentry/node'; dotenv.config(); +Sentry.init({ + dsn: process.env.BFF_SENTRY_DSN, + // Setting this option to true will send default PII data to Sentry. + // For example, automatic IP address collection on events + sendDefaultPii: true, +}); + const isDev = process.argv.includes('--dev'); const __filename = fileURLToPath(import.meta.url); @@ -24,6 +32,8 @@ const fastify = Fastify({ logger: true, }); +Sentry.setupFastifyErrorHandler(fastify); + fastify.register(proxy, { prefix: '/api', }); diff --git a/server/encrypted-session.js b/server/encrypted-session.js index 6fc5b73a..f9507656 100644 --- a/server/encrypted-session.js +++ b/server/encrypted-session.js @@ -52,7 +52,7 @@ async function encryptedSession(fastify) { await fastify.decorateRequest(REQUEST_DECORATOR, { getter() { return createStore(this); - } + }, }); } @@ -103,7 +103,7 @@ function createStore(request) { return { async set(key, value) { unencryptedStore[key] = value; - await save() + await save(); }, get(key) { return unencryptedStore[key]; diff --git a/server/plugins/auth-utils.js b/server/plugins/auth-utils.js index 26e02b37..18713e0d 100644 --- a/server/plugins/auth-utils.js +++ b/server/plugins/auth-utils.js @@ -1,5 +1,6 @@ import fp from 'fastify-plugin'; import crypto from 'node:crypto'; +import * as Sentry from '@sentry/node'; export class AuthenticationError extends Error { constructor(message) { @@ -171,6 +172,12 @@ async function authUtilsPlugin(fastify) { result.expiresAt = expiresAt; } + Sentry.addBreadcrumb({ + category: 'auth', + message: 'Successfully authenticated user: ' + result.userInfo.email, + level: 'info', + }); + request.log.info('OIDC callback succeeded; tokens retrieved.'); return result; }); diff --git a/server/plugins/http-proxy.js b/server/plugins/http-proxy.js index eba36cbc..431add50 100644 --- a/server/plugins/http-proxy.js +++ b/server/plugins/http-proxy.js @@ -1,6 +1,7 @@ import fp from 'fastify-plugin'; import httpProxy from '@fastify/http-proxy'; import { AuthenticationError } from './auth-utils.js'; +import * as Sentry from '@sentry/node'; function proxyPlugin(fastify) { const { API_BACKEND_URL } = fastify.config; @@ -13,6 +14,7 @@ function proxyPlugin(fastify) { request.log.info('Entering HTTP proxy preHandler.'); const useCrate = request.headers['x-use-crate']; + Sentry.setTag('useCrate', useCrate); const keyAccessToken = useCrate ? 'onboarding_accessToken' : 'mcp_accessToken'; const keyTokenExpiresAt = useCrate ? 'onboarding_tokenExpiresAt' : 'mcp_tokenExpiresAt'; @@ -34,6 +36,15 @@ function proxyPlugin(fastify) { return; } + Sentry.addBreadcrumb({ + category: 'auth', + message: 'Attempt token refresh', + level: 'info', + data: { + expiresAt, + }, + }); + request.log.info( { expiresAt: new Date(expiresAt).toISOString() }, 'Access token is expired or about to expire; attempting refresh.', From 722887dea68d6b5488d30526b83a703befe69bba Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Wed, 16 Jul 2025 13:58:47 +0200 Subject: [PATCH 04/18] feat: add environment configuration to Sentry initialization --- server.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server.js b/server.js index 4d9ac188..15204358 100644 --- a/server.js +++ b/server.js @@ -14,6 +14,7 @@ Sentry.init({ // Setting this option to true will send default PII data to Sentry. // For example, automatic IP address collection on events sendDefaultPii: true, + environment: process.env.VITE_ENVIRONMENT, }); const isDev = process.argv.includes('--dev'); From bb98d537266c12d110cde919dcd8065df403e621 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Wed, 16 Jul 2025 14:00:12 +0200 Subject: [PATCH 05/18] feat: streamline imports in AppRouter and mount files, add Sentry to AuthContextOnboarding --- src/AppRouter.tsx | 2 +- src/mount.ts | 10 +--------- src/spaces/onboarding/auth/AuthContextOnboarding.tsx | 1 + 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx index bfa936c3..b65c4ff4 100644 --- a/src/AppRouter.tsx +++ b/src/AppRouter.tsx @@ -1,4 +1,4 @@ -import { HashRouter as Router, Navigate, Route, Routes } from 'react-router-dom'; +import { HashRouter as Router, Navigate, Route } from 'react-router-dom'; import ControlPlaneView from './views/ControlPlanes/ControlPlaneView.tsx'; import ProjectListView from './views/ProjectList'; import ControlPlaneListView from './views/ControlPlanes/ControlPlaneListView.tsx'; diff --git a/src/mount.ts b/src/mount.ts index 801278f2..40778774 100644 --- a/src/mount.ts +++ b/src/mount.ts @@ -2,15 +2,7 @@ import { createRoot } from 'react-dom/client'; import { createApp } from './main.tsx'; import * as Sentry from '@sentry/react'; import React from 'react'; -import { - Routes, - Route, - BrowserRouter, - useLocation, - useNavigationType, - createRoutesFromChildren, - matchRoutes, -} from 'react-router-dom'; +import { Routes, useLocation, useNavigationType, createRoutesFromChildren, matchRoutes } from 'react-router-dom'; let sentryRoutes = Routes; if (import.meta.env.VITE_SENTRY_DSN.length > 0) { diff --git a/src/spaces/onboarding/auth/AuthContextOnboarding.tsx b/src/spaces/onboarding/auth/AuthContextOnboarding.tsx index bd5b7f71..9091014a 100644 --- a/src/spaces/onboarding/auth/AuthContextOnboarding.tsx +++ b/src/spaces/onboarding/auth/AuthContextOnboarding.tsx @@ -1,6 +1,7 @@ import { createContext, useState, useEffect, ReactNode, use } from 'react'; import { MeResponseSchema, User } from './auth.schemas'; import { AUTH_FLOW_SESSION_KEY } from '../../../common/auth/AuthCallbackHandler.tsx'; +import * as Sentry from '@sentry/react'; interface AuthContextOnboardingType { isLoading: boolean; From 97ade2e5f8ae7545068d1f0919dfd6c2c43fd2bb Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Fri, 18 Jul 2025 09:38:37 +0200 Subject: [PATCH 06/18] Update src/mount.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/mount.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mount.ts b/src/mount.ts index 40778774..07b5b579 100644 --- a/src/mount.ts +++ b/src/mount.ts @@ -5,7 +5,7 @@ import React from 'react'; import { Routes, useLocation, useNavigationType, createRoutesFromChildren, matchRoutes } from 'react-router-dom'; let sentryRoutes = Routes; -if (import.meta.env.VITE_SENTRY_DSN.length > 0) { +if (import.meta.env.VITE_SENTRY_DSN && import.meta.env.VITE_SENTRY_DSN.length > 0) { Sentry.init({ dsn: import.meta.env.VITE_SENTRY_DSN, // Setting this option to true will send default PII data to Sentry. From 93363f74fce48b9573937e4da526580302a1f304 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Fri, 18 Jul 2025 09:38:54 +0200 Subject: [PATCH 07/18] Update vite.config.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- vite.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vite.config.js b/vite.config.js index 0fdc754f..ddd47fc8 100644 --- a/vite.config.js +++ b/vite.config.js @@ -12,7 +12,7 @@ export default defineConfig({ viteFastify({ spa: true }), react(), sentryVitePlugin({ - org: 'sap', + org: process.env.SENTRY_ORG, project: 'ui-frontend', reactComponentAnnotation: { enabled: true, From beb0715d73417169efb091cc247c9a355a408c33 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Fri, 18 Jul 2025 09:39:16 +0200 Subject: [PATCH 08/18] Update vite.config.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- vite.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vite.config.js b/vite.config.js index ddd47fc8..67252d55 100644 --- a/vite.config.js +++ b/vite.config.js @@ -13,7 +13,7 @@ export default defineConfig({ react(), sentryVitePlugin({ org: process.env.SENTRY_ORG, - project: 'ui-frontend', + project: process.env.SENTRY_PROJECT || 'ui-frontend', reactComponentAnnotation: { enabled: true, }, From bad484527a95520b0f335d9295ee9fbd2462f18b Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Fri, 18 Jul 2025 09:39:42 +0200 Subject: [PATCH 09/18] Update src/views/Login.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/views/Login.tsx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/views/Login.tsx b/src/views/Login.tsx index 8802a983..9d261532 100644 --- a/src/views/Login.tsx +++ b/src/views/Login.tsx @@ -6,18 +6,19 @@ import { ThemingParameters } from '@ui5/webcomponents-react-base'; import { useLink } from '../lib/shared/useLink.ts'; import { useTranslation } from 'react-i18next'; import * as Sentry from '@sentry/react'; +import { useEffect } from 'react'; export default function LoginView() { const auth = useAuthOnboarding(); const { documentationHomepage } = useLink(); const { t } = useTranslation(); - - Sentry.addBreadcrumb({ - category: 'auth', - message: 'Visit Login Page', - level: 'info', - }); - + useEffect(() => { + Sentry.addBreadcrumb({ + category: 'auth', + message: 'Visit Login Page', + level: 'info', + }); + }, []); return ( Date: Fri, 18 Jul 2025 09:40:03 +0200 Subject: [PATCH 10/18] Update server.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- server.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/server.js b/server.js index 37a02e7f..bd263daf 100644 --- a/server.js +++ b/server.js @@ -11,13 +11,17 @@ import * as Sentry from '@sentry/node'; dotenv.config(); -Sentry.init({ - dsn: process.env.BFF_SENTRY_DSN, - // Setting this option to true will send default PII data to Sentry. - // For example, automatic IP address collection on events - sendDefaultPii: true, - environment: process.env.VITE_ENVIRONMENT, -}); +if (!process.env.BFF_SENTRY_DSN || process.env.BFF_SENTRY_DSN.trim() === '') { + console.error('Error: Sentry DSN is not provided. Sentry will not be initialized.'); +} else { + Sentry.init({ + dsn: process.env.BFF_SENTRY_DSN, + // Setting this option to true will send default PII data to Sentry. + // For example, automatic IP address collection on events + sendDefaultPii: true, + environment: process.env.VITE_ENVIRONMENT, + }); +} const isLocalDev = process.argv.includes('--local-dev'); From 69e18b4e5728f0311cba380547af9d65fae24cdc Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Fri, 18 Jul 2025 09:40:28 +0200 Subject: [PATCH 11/18] Add Sentry organization and project configuration to .env.template --- .env.template | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.env.template b/.env.template index 8fe9ef7f..91dd5700 100644 --- a/.env.template +++ b/.env.template @@ -2,6 +2,8 @@ VITE_ENVIRONMENT= # Sentry DSN configuration, no need to be set for local setup VITE_SENTRY_DSN= BFF_SENTRY_DSN= +SENTRY_ORG= +SENTRY_PROJECT= # OpenID Connect Configuration for Onboarding API From 101d7bbe916d8b0cdd9a75f36551574e9a010853 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Fri, 18 Jul 2025 09:44:06 +0200 Subject: [PATCH 12/18] Reorder Sentry DSN configuration in .env.template for clarity --- .env.template | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.env.template b/.env.template index 91dd5700..398503ba 100644 --- a/.env.template +++ b/.env.template @@ -1,9 +1,11 @@ VITE_ENVIRONMENT= # Sentry DSN configuration, no need to be set for local setup -VITE_SENTRY_DSN= -BFF_SENTRY_DSN= +# Frontend: SENTRY_ORG= SENTRY_PROJECT= +VITE_SENTRY_DSN= +# BFF: +BFF_SENTRY_DSN= # OpenID Connect Configuration for Onboarding API From 83e6780e6ca11e9e967aa5e2404adfb35fe6322d Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Fri, 18 Jul 2025 10:13:52 +0200 Subject: [PATCH 13/18] added sentry to csp --- server.js | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/server.js b/server.js index bd263daf..2f05704b 100644 --- a/server.js +++ b/server.js @@ -5,7 +5,7 @@ import { fileURLToPath } from 'node:url'; import path from 'node:path'; import dotenv from 'dotenv'; import proxy from './server/app.js'; -import envPlugin from "./server/config/env.js"; +import envPlugin from './server/config/env.js'; import { copyFileSync } from 'node:fs'; import * as Sentry from '@sentry/node'; @@ -27,9 +27,7 @@ const isLocalDev = process.argv.includes('--local-dev'); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); -const frontendConfigLocation = isLocalDev - ? 'public/frontend-config.json' - : 'dist/client/frontend-config.json'; +const frontendConfigLocation = isLocalDev ? 'public/frontend-config.json' : 'dist/client/frontend-config.json'; if (process.env.FRONTEND_CONFIG_PATH !== undefined && process.env.FRONTEND_CONFIG_PATH.length > 0) { console.log('FRONTEND_CONFIG_PATH is specified. Will copy the frontend-config from there.'); @@ -44,18 +42,15 @@ const fastify = Fastify({ Sentry.setupFastifyErrorHandler(fastify); await fastify.register(envPlugin); -fastify.register( - helmet, - { - contentSecurityPolicy: { - directives: { - "connect-src": ["'self'", "sdk.openui5.org"], - "script-src": isLocalDev ? ["'self'", "'unsafe-inline'"] : ["'self'"], - "frame-ancestors": [fastify.config.FRAME_ANCESTORS] - }, - } - } -) +fastify.register(helmet, { + contentSecurityPolicy: { + directives: { + 'connect-src': ["'self'", 'sdk.openui5.org', 'o1240783.ingest.us.sentry.io'], + 'script-src': isLocalDev ? ["'self'", "'unsafe-inline'"] : ["'self'"], + 'frame-ancestors': [fastify.config.FRAME_ANCESTORS], + }, + }, +}); fastify.register(proxy, { prefix: '/api', From 820301fb8d19d12600fb5664256ab475e0959d1b Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Fri, 18 Jul 2025 10:26:54 +0200 Subject: [PATCH 14/18] Add dynamic Sentry host configuration to helmet's connect-src directive --- server.js | 7 ++++++- server/config/env.js | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/server.js b/server.js index 2f05704b..a4327b99 100644 --- a/server.js +++ b/server.js @@ -42,10 +42,15 @@ const fastify = Fastify({ Sentry.setupFastifyErrorHandler(fastify); await fastify.register(envPlugin); +let sentryHost = null; +if (fastify.config.BFF_SENTRY_DSN && fastify.config.BFF_SENTRY_DSN.length > 0) { + sentryHost = new URL(fastify.config.BFF_SENTRY_DSN).hostname; +} + fastify.register(helmet, { contentSecurityPolicy: { directives: { - 'connect-src': ["'self'", 'sdk.openui5.org', 'o1240783.ingest.us.sentry.io'], + 'connect-src': ["'self'", 'sdk.openui5.org', sentryHost], 'script-src': isLocalDev ? ["'self'", "'unsafe-inline'"] : ["'self'"], 'frame-ancestors': [fastify.config.FRAME_ANCESTORS], }, diff --git a/server/config/env.js b/server/config/env.js index b2c765b2..2d28720e 100644 --- a/server/config/env.js +++ b/server/config/env.js @@ -29,6 +29,9 @@ const schema = { FEEDBACK_SLACK_URL: { type: 'string' }, FEEDBACK_URL_LINK: { type: 'string' }, FRAME_ANCESTORS: { type: 'string' }, + BFF_SENTRY_DSN: { type: 'string' }, + VITE_SENTRY_DSN: { type: 'string' }, + VITE_ENVIRONMENT: { type: 'string' }, // System variables NODE_ENV: { type: 'string', enum: ['development', 'production'] }, From 120c75392ebd1d9258423d382f5cf07fe981f175 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Fri, 18 Jul 2025 15:25:21 +0200 Subject: [PATCH 15/18] feat: Add beforeSend hook to Sentry for cookie handling --- server.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/server.js b/server.js index a4327b99..bec7c6e0 100644 --- a/server.js +++ b/server.js @@ -20,6 +20,15 @@ if (!process.env.BFF_SENTRY_DSN || process.env.BFF_SENTRY_DSN.trim() === '') { // For example, automatic IP address collection on events sendDefaultPii: true, environment: process.env.VITE_ENVIRONMENT, + beforeSend(event) { + if (event.request && event.request.cookies) { + event.request.cookies = Object.keys(event.request.cookies).reduce((acc, key) => { + acc[key] = ''; + return acc; + }, {}); + } + return event; + }, }); } From 5de454c8d794c159cc955374962d247dae808ab8 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Mon, 21 Jul 2025 08:13:00 +0200 Subject: [PATCH 16/18] Update vite.config.js Co-authored-by: Andreas Kienle --- vite.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vite.config.js b/vite.config.js index 67252d55..3239d584 100644 --- a/vite.config.js +++ b/vite.config.js @@ -13,7 +13,7 @@ export default defineConfig({ react(), sentryVitePlugin({ org: process.env.SENTRY_ORG, - project: process.env.SENTRY_PROJECT || 'ui-frontend', + project: process.env.SENTRY_PROJECT, reactComponentAnnotation: { enabled: true, }, From a502dc1d721ad89677745255deb4dd9094804818 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Mon, 21 Jul 2025 08:17:30 +0200 Subject: [PATCH 17/18] fix: Rename VITE_ENVIRONMENT to VITE_SENTRY_ENVIRONMENT for consistency in Sentry configuration added try catch for url parsing --- .env.template | 2 +- server.js | 11 ++++++++--- server/config/env.js | 2 +- src/mount.ts | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.env.template b/.env.template index 398503ba..92bec95b 100644 --- a/.env.template +++ b/.env.template @@ -1,4 +1,4 @@ -VITE_ENVIRONMENT= +VITE_SENTRY_ENVIRONMENT= # Sentry DSN configuration, no need to be set for local setup # Frontend: SENTRY_ORG= diff --git a/server.js b/server.js index bec7c6e0..82cd6fc0 100644 --- a/server.js +++ b/server.js @@ -19,7 +19,7 @@ if (!process.env.BFF_SENTRY_DSN || process.env.BFF_SENTRY_DSN.trim() === '') { // Setting this option to true will send default PII data to Sentry. // For example, automatic IP address collection on events sendDefaultPii: true, - environment: process.env.VITE_ENVIRONMENT, + environment: process.env.VITE_SENTRY_ENVIRONMENT, beforeSend(event) { if (event.request && event.request.cookies) { event.request.cookies = Object.keys(event.request.cookies).reduce((acc, key) => { @@ -51,9 +51,14 @@ const fastify = Fastify({ Sentry.setupFastifyErrorHandler(fastify); await fastify.register(envPlugin); -let sentryHost = null; +let sentryHost = ''; if (fastify.config.BFF_SENTRY_DSN && fastify.config.BFF_SENTRY_DSN.length > 0) { - sentryHost = new URL(fastify.config.BFF_SENTRY_DSN).hostname; + try { + sentryHost = new URL(fastify.config.BFF_SENTRY_DSN).hostname; + } catch { + console.log('BFF_SENTRY_DSN is not a valid URL'); + sentryHost = ''; + } } fastify.register(helmet, { diff --git a/server/config/env.js b/server/config/env.js index 2d28720e..67780753 100644 --- a/server/config/env.js +++ b/server/config/env.js @@ -31,7 +31,7 @@ const schema = { FRAME_ANCESTORS: { type: 'string' }, BFF_SENTRY_DSN: { type: 'string' }, VITE_SENTRY_DSN: { type: 'string' }, - VITE_ENVIRONMENT: { type: 'string' }, + VITE_SENTRY_ENVIRONMENT: { type: 'string' }, // System variables NODE_ENV: { type: 'string', enum: ['development', 'production'] }, diff --git a/src/mount.ts b/src/mount.ts index 07b5b579..b7e1445b 100644 --- a/src/mount.ts +++ b/src/mount.ts @@ -11,7 +11,7 @@ if (import.meta.env.VITE_SENTRY_DSN && import.meta.env.VITE_SENTRY_DSN.length > // Setting this option to true will send default PII data to Sentry. // For example, automatic IP address collection on events sendDefaultPii: true, - environment: import.meta.env.VITE_ENVIRONMENT, + environment: import.meta.env.VITE_SENTRY_ENVIRONMENT, integrations: [ Sentry.reactRouterV7BrowserTracingIntegration({ useEffect: React.useEffect, From c820a3b97c9b05c63e9b7e1ad8b86bba607a8c79 Mon Sep 17 00:00:00 2001 From: Moritz Reich Date: Mon, 21 Jul 2025 08:45:34 +0200 Subject: [PATCH 18/18] fix: Update Sentry DSN variable from BFF_SENTRY_DSN to VITE_SENTRY_DSN for consistency --- server.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index 82cd6fc0..d5c4ea32 100644 --- a/server.js +++ b/server.js @@ -52,11 +52,11 @@ Sentry.setupFastifyErrorHandler(fastify); await fastify.register(envPlugin); let sentryHost = ''; -if (fastify.config.BFF_SENTRY_DSN && fastify.config.BFF_SENTRY_DSN.length > 0) { +if (fastify.config.VITE_SENTRY_DSN && fastify.config.VITE_SENTRY_DSN.length > 0) { try { - sentryHost = new URL(fastify.config.BFF_SENTRY_DSN).hostname; + sentryHost = new URL(fastify.config.VITE_SENTRY_DSN).hostname; } catch { - console.log('BFF_SENTRY_DSN is not a valid URL'); + console.log('VITE_SENTRY_DSN is not a valid URL'); sentryHost = ''; } }