diff --git a/App.ts b/App.ts index 8642fae..ee4758e 100644 --- a/App.ts +++ b/App.ts @@ -1,3 +1,13 @@ +import * as Sentry from '@sentry/react-native'; + import App from './src/App'; -export default App; +// The DSN is only set in EAS builds (see eas.json); dev builds don't report +Sentry.init({ + dsn: process.env.EXPO_PUBLIC_SENTRY_DSN || undefined, + enabled: !__DEV__, + // Events go to our self-hosted Bugsink, so PII is ok and helps debugging + sendDefaultPii: true, +}); + +export default Sentry.wrap(App); diff --git a/README.md b/README.md index 9a04b83..e4eb20c 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,12 @@ history, code and binary blobs related to React Native functionality filtered ou - privacy policy - delete my account - ??? +- upload source maps to Bugsink so release-build stack traces are symbolicated (until then + they're minified): create an auth token in Bugsink and set `SENTRY_AUTH_TOKEN` as an + [EAS secret](https://docs.expo.dev/eas/environment-variables/) — the Sentry plugin config + in `app.json` (url/organization/project) is already set up for the upload. Needs + [Bugsink ≥ 2.0.14](https://www.bugsink.com/docs/sourcemaps/); verify the project slug in + Bugsink matches `cnapp` - test in ios emulator? (`npm run ios`, requires macOS) - use [Expo Application Services](https://expo.dev/eas) to build and submit app to stores - replace redux (`redux` v5 + `redux-thunk`, hand-written actions and the deprecated @@ -80,10 +86,6 @@ history, code and binary blobs related to React Native functionality filtered ou fetching/caching, with the token in React context + AsyncStorage — replaces `src/reducers.ts`, the fetch thunks in `src/api.ts` and the `isFetching*`/error flags - follow-ups from the [Expo SDK 54 upgrade](https://expo.dev/changelog/sdk-54): - - decide on Sentry: `@sentry/react-native` is installed but never initialized (see the - commented-out init in `index.ts`), and its config plugin (now applied via `app.json`) - warns about missing `organization`/`project` at every build — either finish the setup - or drop the dependency - try the [React Compiler](https://docs.expo.dev/guides/react-compiler/) (enabled by default in new SDK 54 projects, opt-in for existing ones via `"experiments": { "reactCompiler": true }` in `app.json`) diff --git a/app.json b/app.json index fe68075..2abcf8d 100644 --- a/app.json +++ b/app.json @@ -42,7 +42,14 @@ "color": "#E5E2D7" } ], - "@sentry/react-native", + [ + "@sentry/react-native/expo", + { + "url": "https://bugsink.neuf.no/", + "organization": "bugsinkhasnoorgs", + "project": "cnapp" + } + ], [ "@stripe/stripe-react-native", {} diff --git a/eas.json b/eas.json index 83d8e0b..de3d9c3 100644 --- a/eas.json +++ b/eas.json @@ -7,7 +7,8 @@ "EXPO_PUBLIC_DUSKEN_API_URL": "https://galtinn.neuf.no", "EXPO_PUBLIC_DUSKEN_FORGOT_PASSWORD_URL": "https://galtinn.neuf.no/auth/password_reset/", "EXPO_PUBLIC_DUSKEN_PRIVACY_POLICY_URL": "https://galtinn.neuf.no/nb/personvern/", - "EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY": "pk_test_4SNAIZZczSJKZ0y2wrZI4Ngb" + "EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY": "pk_live_4SNAG73lw9kqFGb5u1s0yHhA", + "EXPO_PUBLIC_SENTRY_DSN": "https://af0b4ac4258049d9a21a615b9696190b@bugsink.neuf.no/2" } }, "production": { diff --git a/env-example b/env-example index 3d5368e..96fc5a2 100644 --- a/env-example +++ b/env-example @@ -3,4 +3,4 @@ EXPO_PUBLIC_DUSKEN_API_URL=https://galtinn.neuf.no EXPO_PUBLIC_DUSKEN_FORGOT_PASSWORD_URL=https://galtinn.neuf.no/auth/password_reset/ EXPO_PUBLIC_DUSKEN_PRIVACY_POLICY_URL=https://galtinn.neuf.no/nb/personvern/ EXPO_PUBLIC_SENTRY_DSN= -EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY= +EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_4SNAIZZczSJKZ0y2wrZI4Ngb diff --git a/index.ts b/index.ts deleted file mode 100644 index 253f7a9..0000000 --- a/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -// FIXME: This is never loaded by expo -import { AppRegistry } from 'react-native'; -// import * as Sentry from '@sentry/react-native'; - -import { expo as expoConfig } from './app.json'; -import App from './src/App'; - -// if (Config.SENTRY_DSN) { -// Sentry.init({ dsn: Config.SENTRY_DSN }); -// } - -AppRegistry.registerComponent(expoConfig.name, () => App); diff --git a/package-lock.json b/package-lock.json index aad251b..220eb64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "@react-navigation/bottom-tabs": "^7.4.7", "@react-navigation/native": "^7.1.17", "@react-navigation/native-stack": "^7.3.26", - "@sentry/react-native": "~7.11.0", + "@sentry/react-native": "~8.20.0", "@shopify/react-native-skia": "2.6.2", "@stripe/stripe-react-native": "0.64.0", "date-fns": "^4.4.0", @@ -3253,128 +3253,91 @@ "dev": true, "license": "MIT" }, - "node_modules/@sentry-internal/browser-utils": { - "version": "10.37.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.37.0.tgz", - "integrity": "sha512-rqdESYaVio9Ktz55lhUhtBsBUCF3wvvJuWia5YqoHDd+egyIfwWxITTAa0TSEyZl7283A4WNHNl0hyeEMblmfA==", - "license": "MIT", - "dependencies": { - "@sentry/core": "10.37.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry-internal/feedback": { - "version": "10.37.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.37.0.tgz", - "integrity": "sha512-P0PVlfrDvfvCYg2KPIS7YUG/4i6ZPf8z1MicXx09C9Cz9W9UhSBh/nii13eBdDtLav2BFMKhvaFMcghXHX03Hw==", - "license": "MIT", - "dependencies": { - "@sentry/core": "10.37.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry-internal/replay": { - "version": "10.37.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.37.0.tgz", - "integrity": "sha512-snuk12ZaDerxesSnetNIwKoth/51R0y/h3eXD/bGtXp+hnSkeXN5HanI/RJl297llRjn4zJYRShW9Nx86Ay0Dw==", - "license": "MIT", - "dependencies": { - "@sentry-internal/browser-utils": "10.37.0", - "@sentry/core": "10.37.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@sentry-internal/replay-canvas": { - "version": "10.37.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.37.0.tgz", - "integrity": "sha512-PyIYSbjLs+L5essYV0MyIsh4n5xfv2eV7l0nhUoPJv9Bak3kattQY3tholOj0EP3SgKgb+8HSZnmazgF++Hbog==", - "license": "MIT", - "dependencies": { - "@sentry-internal/replay": "10.37.0", - "@sentry/core": "10.37.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@sentry/babel-plugin-component-annotate": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-4.8.0.tgz", - "integrity": "sha512-cy/9Eipkv23MsEJ4IuB4dNlVwS9UqOzI3Eu+QPake5BVFgPYCX0uP0Tr3Z43Ime6Rb+BiDnWC51AJK9i9afHYw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-5.3.0.tgz", + "integrity": "sha512-p4q8gn8wcFqZGP/s2MnJCAAd8fTikaU6A0mM97RDHQgStcrYiaS0Sc5zUNfb1V+UOLPuvdEdL6MwyxfzjYJQTA==", "license": "MIT", "engines": { - "node": ">= 14" + "node": ">= 18" } }, "node_modules/@sentry/browser": { - "version": "10.37.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.37.0.tgz", - "integrity": "sha512-kheqJNqGZP5TSBCPv4Vienv1sfZwXKHQDYR+xrdHHYdZqwWuZMJJW/cLO9XjYAe+B9NnJ4UwJOoY4fPvU+HQ1Q==", + "version": "10.67.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.67.0.tgz", + "integrity": "sha512-/ZhsAvte4rYhg0A0RtSFFgAgXhyMOfQIeOAfMfptN+X6IVSYOfkA9jtrP+Ej4+6vlaUFWRir1HweF56y63dEEA==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "10.37.0", - "@sentry-internal/feedback": "10.37.0", - "@sentry-internal/replay": "10.37.0", - "@sentry-internal/replay-canvas": "10.37.0", - "@sentry/core": "10.37.0" + "@sentry/browser-utils": "10.67.0", + "@sentry/conventions": "^0.16.0", + "@sentry/core": "10.67.0", + "@sentry/feedback": "10.67.0", + "@sentry/replay": "10.67.0", + "@sentry/replay-canvas": "10.67.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/browser-utils": { + "version": "10.67.0", + "resolved": "https://registry.npmjs.org/@sentry/browser-utils/-/browser-utils-10.67.0.tgz", + "integrity": "sha512-HUzaf0xAnPAB+OHBkD7N1Py+CTbD5InHulQ/pdhX4JctWtxuwD8odMD1LzdPnW8J6gVHlDVvcVBR8mXMZYSLSw==", + "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0", + "@sentry/core": "10.67.0" }, "engines": { "node": ">=18" } }, "node_modules/@sentry/cli": { - "version": "2.58.4", - "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.58.4.tgz", - "integrity": "sha512-ArDrpuS8JtDYEvwGleVE+FgR+qHaOp77IgdGSacz6SZy6Lv90uX0Nu4UrHCQJz8/xwIcNxSqnN22lq0dH4IqTg==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-3.6.1.tgz", + "integrity": "sha512-9KGZEe/o+vdHS69JhkNztPysqknnI3W5cceovi2G3yb5z29At6SAbGGOdFe3qxYDfC/c2Uw5MKYfev8K9xFI9Q==", "hasInstallScript": true, "license": "FSL-1.1-MIT", "dependencies": { - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.7", "progress": "^2.0.3", "proxy-from-env": "^1.1.0", + "undici": "^6.22.0", "which": "^2.0.2" }, "bin": { "sentry-cli": "bin/sentry-cli" }, "engines": { - "node": ">= 10" + "node": ">= 18" }, "optionalDependencies": { - "@sentry/cli-darwin": "2.58.4", - "@sentry/cli-linux-arm": "2.58.4", - "@sentry/cli-linux-arm64": "2.58.4", - "@sentry/cli-linux-i686": "2.58.4", - "@sentry/cli-linux-x64": "2.58.4", - "@sentry/cli-win32-arm64": "2.58.4", - "@sentry/cli-win32-i686": "2.58.4", - "@sentry/cli-win32-x64": "2.58.4" + "@sentry/cli-darwin": "3.6.1", + "@sentry/cli-linux-arm": "3.6.1", + "@sentry/cli-linux-arm64": "3.6.1", + "@sentry/cli-linux-i686": "3.6.1", + "@sentry/cli-linux-x64": "3.6.1", + "@sentry/cli-win32-arm64": "3.6.1", + "@sentry/cli-win32-i686": "3.6.1", + "@sentry/cli-win32-x64": "3.6.1" } }, "node_modules/@sentry/cli-darwin": { - "version": "2.58.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.58.4.tgz", - "integrity": "sha512-kbTD+P4X8O+nsNwPxCywtj3q22ecyRHWff98rdcmtRrvwz8CKi/T4Jxn/fnn2i4VEchy08OWBuZAqaA5Kh2hRQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-3.6.1.tgz", + "integrity": "sha512-hit8SHXYTSZnKvT87/n/5RLwJnl0Nm24dewqEXwMzw7YkDFg7Ptq0bIhvGWINgyuBsmEfXGMnrbBZw5sueBtnQ==", "license": "FSL-1.1-MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/@sentry/cli-linux-arm": { - "version": "2.58.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.58.4.tgz", - "integrity": "sha512-rdQ8beTwnN48hv7iV7e7ZKucPec5NJkRdrrycMJMZlzGBPi56LqnclgsHySJ6Kfq506A2MNuQnKGaf/sBC9REA==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-3.6.1.tgz", + "integrity": "sha512-FgfKPa4sXianCQxpujNE1JrJYbF6Ug+UPjwdEGAnCZtDeRRQdXbSIih7ikaocg4BcpHxwoRm0BHG1wYeizkCbQ==", "cpu": [ "arm" ], @@ -3386,13 +3349,13 @@ "android" ], "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/@sentry/cli-linux-arm64": { - "version": "2.58.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.58.4.tgz", - "integrity": "sha512-0g0KwsOozkLtzN8/0+oMZoOuQ0o7W6O+hx+ydVU1bktaMGKEJLMAWxOQNjsh1TcBbNIXVOKM/I8l0ROhaAb8Ig==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-3.6.1.tgz", + "integrity": "sha512-+6UpbQo56wW5pf1TTBfNoYzf+WuG7c1fj9DAKchQwUzDN7886OwSYC326rDyh/PaafszYj5gAOElFhymNVA1WA==", "cpu": [ "arm64" ], @@ -3404,13 +3367,13 @@ "android" ], "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/@sentry/cli-linux-i686": { - "version": "2.58.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.58.4.tgz", - "integrity": "sha512-NseoIQAFtkziHyjZNPTu1Gm1opeQHt7Wm1LbLrGWVIRvUOzlslO9/8i6wETUZ6TjlQxBVRgd3Q0lRBG2A8rFYA==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-3.6.1.tgz", + "integrity": "sha512-xDzb2knLayJKv6FGggjrfvQiIpA4wvYvxeNV6B3plTlu1Qunkz5889A+Ayrp4wv19bgMVI6wLdKF9U2TpHPTbQ==", "cpu": [ "x86", "ia32" @@ -3423,13 +3386,13 @@ "android" ], "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/@sentry/cli-linux-x64": { - "version": "2.58.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.58.4.tgz", - "integrity": "sha512-d3Arz+OO/wJYTqCYlSN3Ktm+W8rynQ/IMtSZLK8nu0ryh5mJOh+9XlXY6oDXw4YlsM8qCRrNquR8iEI1Y/IH+Q==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-3.6.1.tgz", + "integrity": "sha512-OJChq61ZoKFLAVC+LPqensvBcoToxnAfAZF19emTLNQNjBbGZBL6G/4P0uK4tlwlhB5wAeobu58xX2kfJEgkjA==", "cpu": [ "x64" ], @@ -3441,13 +3404,13 @@ "android" ], "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/@sentry/cli-win32-arm64": { - "version": "2.58.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.58.4.tgz", - "integrity": "sha512-bqYrF43+jXdDBh0f8HIJU3tbvlOFtGyRjHB8AoRuMQv9TEDUfENZyCelhdjA+KwDKYl48R1Yasb4EHNzsoO83w==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-3.6.1.tgz", + "integrity": "sha512-SR4JESQdr1+XmK3kAVa9BAUdOA9QYkreJkWzUlj1oXbTlD5OdRmzc1yMHlkrkbbKSu6vrlqYiEaox3Pgsc08sg==", "cpu": [ "arm64" ], @@ -3457,13 +3420,13 @@ "win32" ], "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/@sentry/cli-win32-i686": { - "version": "2.58.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.58.4.tgz", - "integrity": "sha512-3triFD6jyvhVcXOmGyttf+deKZcC1tURdhnmDUIBkiDPJKGT/N5xa4qAtHJlAB/h8L9jgYih9bvJnvvFVM7yug==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-3.6.1.tgz", + "integrity": "sha512-EBOR2Yx5nYUcwbGXp5AHuQPjNZ9QLcoKlTKAt9ygQX4SF7S0pwnrAfXktkA4QOZqSXtzlKhrpwwnWNq0zPksNw==", "cpu": [ "x86", "ia32" @@ -3474,13 +3437,13 @@ "win32" ], "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/@sentry/cli-win32-x64": { - "version": "2.58.4", - "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.58.4.tgz", - "integrity": "sha512-cSzN4PjM1RsCZ4pxMjI0VI7yNCkxiJ5jmWncyiwHXGiXrV1eXYdQ3n1LhUYLZ91CafyprR0OhDcE+RVZ26Qb5w==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-3.6.1.tgz", + "integrity": "sha512-qQkVQOMoE5U6NtigezFNYSJncP1DOuauvp7JS+1DRpE5pXTKjHkOT6niWceGQc7wH4UGk6iwzOkNzx6klNd4Yw==", "cpu": [ "x64" ], @@ -3490,26 +3453,78 @@ "win32" ], "engines": { - "node": ">=10" + "node": ">=18" + } + }, + "node_modules/@sentry/conventions": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@sentry/conventions/-/conventions-0.16.0.tgz", + "integrity": "sha512-fO9PLmHdVURcSPUpWCItWAtgKiMwGdJHbovoSEyLplX5sxs2ugvI4CBPTrkkgqhObnZOD0CnWBKDzSVQYBKEyQ==", + "license": "MIT", + "engines": { + "node": ">=14" } }, "node_modules/@sentry/core": { - "version": "10.37.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.37.0.tgz", - "integrity": "sha512-hkRz7S4gkKLgPf+p3XgVjVm7tAfvcEPZxeACCC6jmoeKhGkzN44nXwLiqqshJ25RMcSrhfFvJa/FlBg6zupz7g==", + "version": "10.67.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.67.0.tgz", + "integrity": "sha512-b6U3pJ8AUvN9aouq0vl+VZI8KT8RslBsfGMFuNwRr313zOmdmFJBZqTiUw9VGgJ2jGKxLO9alm9rlxBfX4hf+w==", "license": "MIT", + "dependencies": { + "@sentry/conventions": "^0.16.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/expo-upload-sourcemaps": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@sentry/expo-upload-sourcemaps/-/expo-upload-sourcemaps-8.20.0.tgz", + "integrity": "sha512-FWIJmNTWWY+E/tHQdFIxKMzEB0n47mF8W+1otcXr1hqEsePgBjMqeY2X3NhGRrt4b8rvTCXCjPlc3APyR+nCAg==", + "license": "MIT", + "dependencies": { + "@sentry/cli": "3.6.1" + }, + "bin": { + "expo-upload-sourcemaps": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@expo/env": "*", + "dotenv": "*" + }, + "peerDependenciesMeta": { + "@expo/env": { + "optional": true + }, + "dotenv": { + "optional": true + } + } + }, + "node_modules/@sentry/feedback": { + "version": "10.67.0", + "resolved": "https://registry.npmjs.org/@sentry/feedback/-/feedback-10.67.0.tgz", + "integrity": "sha512-I4ML2/SF3enwikb6ZSoRiqolQrx0zSzTSnUgwCmugICF/jpHW0th1pCray9R+t1Zzibw/Dpj4t/DNXaSDRa2MA==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.67.0" + }, "engines": { "node": ">=18" } }, "node_modules/@sentry/react": { - "version": "10.37.0", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.37.0.tgz", - "integrity": "sha512-XLnXJOHgsCeVAVBbO+9AuGlZWnCxLQHLOmKxpIr8wjE3g7dHibtug6cv8JLx78O4dd7aoCqv2TTyyKY9FLJ2EQ==", + "version": "10.67.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.67.0.tgz", + "integrity": "sha512-fS0DplcP9eMxBIRurPC/uxa4NrFK+l9ZsnvQo7wZvNutc7DpTAH0hgFt6laVNCe57s1pFo+OZuKsYBA6JDvH4Q==", "license": "MIT", "dependencies": { - "@sentry/browser": "10.37.0", - "@sentry/core": "10.37.0" + "@sentry/browser": "10.67.0", + "@sentry/conventions": "^0.16.0", + "@sentry/core": "10.67.0" }, "engines": { "node": ">=18" @@ -3519,19 +3534,22 @@ } }, "node_modules/@sentry/react-native": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@sentry/react-native/-/react-native-7.11.0.tgz", - "integrity": "sha512-OiDaLCAGpRN18YG/o7IIwLhU0Xpb0tYKQ5QxkGHiwb+L3VHn+MqGCGfITYNdhqr06HHMvu9Lysm+UJxaNmGaJg==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@sentry/react-native/-/react-native-8.20.0.tgz", + "integrity": "sha512-Visy8xWo4wJm3OW1QWiHB4avj0mp+En4fiY9uiaPmWhgX0RIx2fwAm73x3o5+etZdRDnC6oVhV5skofy9rEC6A==", "license": "MIT", "dependencies": { - "@sentry/babel-plugin-component-annotate": "4.8.0", - "@sentry/browser": "10.37.0", - "@sentry/cli": "2.58.4", - "@sentry/core": "10.37.0", - "@sentry/react": "10.37.0", - "@sentry/types": "10.37.0" + "@sentry/babel-plugin-component-annotate": "5.3.0", + "@sentry/browser": "10.67.0", + "@sentry/cli": "3.6.1", + "@sentry/core": "10.67.0", + "@sentry/expo-upload-sourcemaps": "8.20.0", + "@sentry/react": "10.67.0" }, "bin": { + "sentry-eas-build-on-complete": "scripts/eas-build-hook.js", + "sentry-eas-build-on-error": "scripts/eas-build-hook.js", + "sentry-eas-build-on-success": "scripts/eas-build-hook.js", "sentry-expo-upload-sourcemaps": "scripts/expo-upload-sourcemaps.js" }, "peerDependencies": { @@ -3545,13 +3563,27 @@ } } }, - "node_modules/@sentry/types": { - "version": "10.37.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-10.37.0.tgz", - "integrity": "sha512-umpnUKRC0AAbJrADg6SlFtqN2yzf7NHciCF9lkHau+ax2PIZ/NDmoG4RQujFVflVaVoD60Ly2t+CcPnYIWMPlw==", + "node_modules/@sentry/replay": { + "version": "10.67.0", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-10.67.0.tgz", + "integrity": "sha512-nkEUgPCR82EcyJkCf3XCE9H0R5KisCqyCAaSGxe7NpAoQbvASHx4MUNgXVAn+D0M494gvPZh6lFH7JgzqTcSqQ==", "license": "MIT", "dependencies": { - "@sentry/core": "10.37.0" + "@sentry/browser-utils": "10.67.0", + "@sentry/core": "10.67.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/replay-canvas": { + "version": "10.67.0", + "resolved": "https://registry.npmjs.org/@sentry/replay-canvas/-/replay-canvas-10.67.0.tgz", + "integrity": "sha512-neNA4T6MFtZzMdKYetiR+LZd9BNSd0q2szMn0wk+A15PqHE/IN7a34V6JZc9rCtmzB0wldh0eWGOBb49MSNKjA==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.67.0", + "@sentry/replay": "10.67.0" }, "engines": { "node": ">=18" @@ -4982,6 +5014,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "license": "MIT", "dependencies": { "debug": "4" @@ -9041,6 +9074,7 @@ "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==", + "dev": true, "license": "MIT", "dependencies": { "agent-base": "6", @@ -12276,48 +12310,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/node-fetch": { - "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==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/node-forge": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", @@ -15452,6 +15444,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici": { + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", + "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, "node_modules/undici-types": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", diff --git a/package.json b/package.json index 3dc611d..e34ed00 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@react-navigation/bottom-tabs": "^7.4.7", "@react-navigation/native": "^7.1.17", "@react-navigation/native-stack": "^7.3.26", - "@sentry/react-native": "~7.11.0", + "@sentry/react-native": "~8.20.0", "@shopify/react-native-skia": "2.6.2", "@stripe/stripe-react-native": "0.64.0", "date-fns": "^4.4.0", @@ -68,7 +68,7 @@ "typescript": "~6.0.3" }, "allowScripts": { - "@sentry/cli@2.58.4": true, + "@sentry/cli@3.6.1": true, "@shopify/react-native-skia@2.6.2": true, "unrs-resolver@1.12.2": true } diff --git a/src/utils.test.ts b/src/utils.test.ts new file mode 100644 index 0000000..1a17722 --- /dev/null +++ b/src/utils.test.ts @@ -0,0 +1,42 @@ +import { withAppSource } from '@/utils'; + +describe('withAppSource', () => { + it('tags links to our own sites with UTM params', () => { + expect(withAppSource('https://neuf.no/arrangement/123/')).toBe( + 'https://neuf.no/arrangement/123/?utm_source=neuf-app&utm_medium=app', + ); + expect(withAppSource('https://www.studentersamfundet.no/')).toBe( + 'https://www.studentersamfundet.no/?utm_source=neuf-app&utm_medium=app', + ); + }); + + it('tags subdomains of our own sites', () => { + expect(withAppSource('https://galtinn.neuf.no/nb/personvern/')).toBe( + 'https://galtinn.neuf.no/nb/personvern/?utm_source=neuf-app&utm_medium=app', + ); + }); + + it('preserves existing query params and fragments', () => { + expect(withAppSource('https://neuf.no/sok?q=konsert')).toBe( + 'https://neuf.no/sok?q=konsert&utm_source=neuf-app&utm_medium=app', + ); + expect(withAppSource('https://neuf.no/praktisk#apningstider')).toBe( + 'https://neuf.no/praktisk?utm_source=neuf-app&utm_medium=app#apningstider', + ); + }); + + it('leaves other sites untouched', () => { + expect(withAppSource('https://www.facebook.com/studentersamfundet/')).toBe( + 'https://www.facebook.com/studentersamfundet/', + ); + // Suffix match must not catch lookalike domains + expect(withAppSource('https://evilneuf.no/')).toBe('https://evilneuf.no/'); + }); + + it('leaves non-web URLs and invalid URLs untouched', () => { + expect(withAppSource('tel:+4794430002')).toBe('tel:+4794430002'); + expect(withAppSource('mailto:ledelsen@studentersamfundet.no')).toBe('mailto:ledelsen@studentersamfundet.no'); + expect(withAppSource('fb://page/?id=23664032291')).toBe('fb://page/?id=23664032291'); + expect(withAppSource('')).toBe(''); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index df7e86c..9f23503 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,5 +9,5 @@ "types": ["jest", "node"] }, "extends": "expo/tsconfig.base", - "include": ["src", "src/types/svg.d.ts", "App.ts", "index.ts"] + "include": ["src", "src/types/svg.d.ts", "App.ts"] }