mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
feat(mobile): replace Sentry with Firebase Crashlytics
Migrate error tracking from Sentry to Firebase Crashlytics. Bump version to 1.0.4, add Discord notification triggers.
This commit is contained in:
1 parent
620369a7ce
commit
14b0199625
16 files changed
+531
-407
No files matched your search
@@ -23,6 +23,7 @@ apps/mobile/.env.*
|
||||
|
||||
# Supabase
|
||||
.supabase/
|
||||
supabase/.temp/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
|
||||
@@ -80,8 +80,6 @@ def enableProguardInReleaseBuilds = (findProperty('android.enableProguardInRelea
|
||||
*/
|
||||
def jscFlavor = 'org.webkit:android-jsc:+'
|
||||
|
||||
apply from: new File(["node", "--print", "require('path').dirname(require.resolve('@sentry/react-native/package.json'))"].execute().text.trim(), "sentry.gradle")
|
||||
|
||||
android {
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
|
||||
@@ -93,8 +91,8 @@ android {
|
||||
applicationId 'com.sauci.app'
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 37
|
||||
versionName "1.0.3"
|
||||
versionCode 42
|
||||
versionName "1.0.4"
|
||||
}
|
||||
signingConfigs {
|
||||
debug {
|
||||
@@ -178,3 +176,4 @@ dependencies {
|
||||
}
|
||||
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
apply plugin: 'com.google.firebase.crashlytics'
|
||||
@@ -15,6 +15,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:3.0.6'
|
||||
classpath 'com.google.gms:google-services:4.4.1'
|
||||
classpath('com.android.tools.build:gradle')
|
||||
classpath('com.facebook.react:react-native-gradle-plugin')
|
||||
|
||||
+5
-11
@@ -2,7 +2,7 @@
|
||||
"expo": {
|
||||
"name": "Sauci",
|
||||
"slug": "sauci",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.4",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/icon.png",
|
||||
"scheme": "app.sauci",
|
||||
@@ -16,10 +16,11 @@
|
||||
"ios": {
|
||||
"supportsTablet": false,
|
||||
"bundleIdentifier": "com.sauci.app",
|
||||
"buildNumber": "33",
|
||||
"buildNumber": "35",
|
||||
"usesAppleSignIn": true,
|
||||
"googleServicesFile": "./GoogleService-Info.plist",
|
||||
"infoPlist": {
|
||||
"GOOGLE_ANALYTICS_INAPURCHASE_COLLECTION_ENABLED": false,
|
||||
"UIBackgroundModes": [
|
||||
"remote-notification"
|
||||
],
|
||||
@@ -177,7 +178,7 @@
|
||||
"backgroundColor": "#1a1a2e"
|
||||
},
|
||||
"package": "com.sauci.app",
|
||||
"versionCode": 37,
|
||||
"versionCode": 42,
|
||||
"googleServicesFile": "./google-services.json",
|
||||
"permissions": [
|
||||
"RECEIVE_BOOT_COMPLETED",
|
||||
@@ -227,14 +228,7 @@
|
||||
"faceIDPermission": "Sauci uses Face ID to unlock the app and keep your conversations private."
|
||||
}
|
||||
],
|
||||
[
|
||||
"@sentry/react-native/expo",
|
||||
{
|
||||
"organization": "molten-prints",
|
||||
"project": "sauci"
|
||||
}
|
||||
],
|
||||
"@sentry/react-native",
|
||||
"@react-native-firebase/crashlytics",
|
||||
"expo-font",
|
||||
"expo-asset",
|
||||
[
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// Polyfills must be imported FIRST before any other React Native imports
|
||||
import "../src/polyfills/web";
|
||||
|
||||
// Initialize Sentry early to capture all errors
|
||||
import { initSentry, setUserContext, clearUserContext } from "../src/lib/sentry";
|
||||
initSentry();
|
||||
// Initialize Crashlytics early to capture all errors
|
||||
import { initCrashlytics, setUserContext, clearUserContext } from "../src/lib/crashlytics";
|
||||
initCrashlytics();
|
||||
|
||||
// Analytics imports (initialization deferred until app mounts)
|
||||
import { initAnalytics, setUserId, clearUserId, logScreenView, Events } from "../src/lib/analytics";
|
||||
@@ -212,7 +212,7 @@ export default function RootLayout() {
|
||||
if (event === "SIGNED_IN" || event === "TOKEN_REFRESHED" || event === "USER_UPDATED") {
|
||||
console.log('[Auth] Calling fetchUser...');
|
||||
fetchUser();
|
||||
// Set Sentry user context for error tracking
|
||||
// Set Crashlytics user context for error tracking
|
||||
if (session?.user) {
|
||||
setUserContext(session.user.id, session.user.email);
|
||||
// Set Analytics user ID
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
"env": {
|
||||
"EXPO_PUBLIC_SUPABASE_URL": "https://ckjcrkjpmhqhiucifukx.supabase.co",
|
||||
"EXPO_PUBLIC_SUPABASE_ANON_KEY": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNramNya2pwbWhxaGl1Y2lmdWt4Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjcxMDc1ODEsImV4cCI6MjA4MjY4MzU4MX0.7FA_RmFXUjlmZF96O9xlAUfxHrQrSIZcJclNReLL4lI",
|
||||
"EXPO_PUBLIC_SENTRY_DSN": "https://03a91f8a1b1ecdce2d5f38a4c23ca9d5@o4510613894070272.ingest.de.sentry.io/4510613896560720",
|
||||
"EXPO_PUBLIC_REVENUECAT_IOS_API_KEY": "appl_lfPyYonFQtVytftPAfXIrGsMNFu",
|
||||
"EXPO_PUBLIC_REVENUECAT_ANDROID_API_KEY": "goog_zoHtaRswsgvxtvYWIhZyvrPBGgh",
|
||||
"EXPO_PUBLIC_REVENUECAT_ENTITLEMENT_ID": "Sauci Pro",
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"react-native": {
|
||||
"analytics_auto_collection_enabled": true,
|
||||
"google_analytics_adid_collection_enabled": false
|
||||
"google_analytics_adid_collection_enabled": false,
|
||||
"crashlytics_auto_collection_enabled": true,
|
||||
"crashlytics_debug_enabled": false,
|
||||
"crashlytics_ndk_enabled": true
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.3</string>
|
||||
<string>1.0.4</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
@@ -47,7 +47,9 @@
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>33</string>
|
||||
<string>35</string>
|
||||
<key>GOOGLE_ANALYTICS_INAPURCHASE_COLLECTION_ENABLED</key>
|
||||
<false/>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>12.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
"@react-native-async-storage/async-storage": "1.23.1",
|
||||
"@react-native-firebase/analytics": "^23.8.2",
|
||||
"@react-native-firebase/app": "^23.8.2",
|
||||
"@react-native-firebase/crashlytics": "^23.8.4",
|
||||
"@react-native-google-signin/google-signin": "^16.1.1",
|
||||
"@react-navigation/bottom-tabs": "^7.0.0",
|
||||
"@react-navigation/native": "^7.0.0",
|
||||
"@react-navigation/native-stack": "^7.0.0",
|
||||
"@sentry/react-native": "~6.10.0",
|
||||
"@supabase/supabase-js": "^2.39.0",
|
||||
"@tanstack/react-query": "^5.17.0",
|
||||
"babel-preset-expo": "~12.0.0",
|
||||
|
||||
@@ -240,7 +240,7 @@ export const Events = {
|
||||
error_message: safeParam(errorMessage),
|
||||
}),
|
||||
purchaseCompleted: (packageType: string) =>
|
||||
logEvent("purchase", { package_type: packageType }),
|
||||
logEvent("purchase_completed", { package_type: packageType }),
|
||||
purchaseRestored: () => logEvent("purchase_restored"),
|
||||
|
||||
// Pack events
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
import { Platform } from "react-native";
|
||||
import Constants from "expo-constants";
|
||||
import crashlytics from "@react-native-firebase/crashlytics";
|
||||
|
||||
let isInitialized = false;
|
||||
let crashlyticsUnavailable = false;
|
||||
let crashlyticsUnavailableLogged = false;
|
||||
|
||||
function getErrorMessage(error: unknown): string {
|
||||
if (!error) return "";
|
||||
if (typeof error === "string") return error;
|
||||
if (error instanceof Error) return error.message;
|
||||
if (typeof (error as { message?: unknown }).message === "string") {
|
||||
return (error as { message?: string }).message || "";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function isCrashlyticsSupported(): boolean {
|
||||
if (Platform.OS === "web") return false;
|
||||
if (Constants.appOwnership === "expo") return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function logCrashlyticsUnavailableOnce(reason: string) {
|
||||
if (crashlyticsUnavailableLogged) return;
|
||||
crashlyticsUnavailableLogged = true;
|
||||
if (__DEV__) console.log("[Crashlytics] " + reason);
|
||||
}
|
||||
|
||||
function getCrashlyticsInstance(): ReturnType<typeof crashlytics> | null {
|
||||
if (crashlyticsUnavailable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isCrashlyticsSupported()) {
|
||||
crashlyticsUnavailable = true;
|
||||
logCrashlyticsUnavailableOnce("Skipping Firebase Crashlytics on Expo Go or web.");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return crashlytics();
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
if (message.includes("module could not be found")) {
|
||||
crashlyticsUnavailable = true;
|
||||
logCrashlyticsUnavailableOnce(
|
||||
"Firebase Crashlytics native module missing. Rebuild with a dev client or native app."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
console.warn("[Crashlytics] Failed to get crashlytics instance:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function initCrashlytics() {
|
||||
if (isInitialized) return;
|
||||
|
||||
try {
|
||||
const instance = getCrashlyticsInstance();
|
||||
if (instance) {
|
||||
instance.setCrashlyticsCollectionEnabled(true);
|
||||
isInitialized = true;
|
||||
console.log("[Crashlytics] Firebase Crashlytics initialized");
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("[Crashlytics] Failed to initialize:", error);
|
||||
}
|
||||
}
|
||||
|
||||
export function captureError(error: Error, context?: Record<string, unknown>) {
|
||||
try {
|
||||
const instance = getCrashlyticsInstance();
|
||||
if (!instance) return;
|
||||
|
||||
if (context) {
|
||||
for (const [key, value] of Object.entries(context)) {
|
||||
instance.setAttribute(key, String(value ?? ""));
|
||||
}
|
||||
}
|
||||
instance.recordError(error);
|
||||
} catch (e) {
|
||||
console.warn("[Crashlytics] Failed to capture error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
export function setUserContext(userId: string, email?: string) {
|
||||
try {
|
||||
const instance = getCrashlyticsInstance();
|
||||
if (!instance) return;
|
||||
|
||||
instance.setUserId(userId);
|
||||
if (email) {
|
||||
instance.setAttribute("email", email);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("[Crashlytics] Failed to set user context:", error);
|
||||
}
|
||||
}
|
||||
|
||||
export function clearUserContext() {
|
||||
try {
|
||||
const instance = getCrashlyticsInstance();
|
||||
if (!instance) return;
|
||||
|
||||
instance.setUserId("");
|
||||
instance.setAttribute("email", "");
|
||||
} catch (error) {
|
||||
console.warn("[Crashlytics] Failed to clear user context:", error);
|
||||
}
|
||||
}
|
||||
|
||||
export function addBreadcrumb(
|
||||
message: string,
|
||||
category: string,
|
||||
data?: Record<string, unknown>
|
||||
) {
|
||||
try {
|
||||
const instance = getCrashlyticsInstance();
|
||||
if (!instance) return;
|
||||
|
||||
instance.log(`[${category}] ${message}${data ? " " + JSON.stringify(data) : ""}`);
|
||||
} catch (error) {
|
||||
console.warn("[Crashlytics] Failed to add breadcrumb:", error);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import Constants from "expo-constants";
|
||||
import { Platform } from "react-native";
|
||||
import { router } from "expo-router";
|
||||
import { supabase } from "./supabase";
|
||||
import { captureError } from "./sentry";
|
||||
import { captureError } from "./crashlytics";
|
||||
import { Events } from "./analytics";
|
||||
import { useMatchStore } from "../store/matchStore";
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
import * as Sentry from "@sentry/react-native";
|
||||
import Constants from "expo-constants";
|
||||
|
||||
const SENTRY_DSN = process.env.EXPO_PUBLIC_SENTRY_DSN;
|
||||
|
||||
export function initSentry() {
|
||||
if (!SENTRY_DSN) {
|
||||
console.warn("Sentry DSN not configured - error tracking disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
Sentry.init({
|
||||
dsn: SENTRY_DSN,
|
||||
debug: __DEV__,
|
||||
enabled: !__DEV__, // Only enable in production
|
||||
environment: __DEV__ ? "development" : "production",
|
||||
release: Constants.expoConfig?.version ?? "1.0.0",
|
||||
dist: Constants.expoConfig?.ios?.buildNumber ?? Constants.expoConfig?.android?.versionCode?.toString(),
|
||||
|
||||
// Performance monitoring
|
||||
tracesSampleRate: 0.2, // 20% of transactions for performance
|
||||
|
||||
// Session tracking
|
||||
enableAutoSessionTracking: true,
|
||||
sessionTrackingIntervalMillis: 30000,
|
||||
|
||||
// Capture unhandled promise rejections
|
||||
enableNative: true,
|
||||
|
||||
// Filter out noisy errors
|
||||
beforeSend(event) {
|
||||
// Filter out network errors that are expected (e.g., user offline)
|
||||
if (event.exception?.values?.[0]?.value?.includes("Network request failed")) {
|
||||
return null;
|
||||
}
|
||||
return event;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Helper to capture errors with context
|
||||
export function captureError(error: Error, context?: Record<string, unknown>) {
|
||||
if (context) {
|
||||
Sentry.setContext("additional", context);
|
||||
}
|
||||
Sentry.captureException(error);
|
||||
}
|
||||
|
||||
// Set user context when they log in
|
||||
export function setUserContext(userId: string, email?: string) {
|
||||
Sentry.setUser({
|
||||
id: userId,
|
||||
email,
|
||||
});
|
||||
}
|
||||
|
||||
// Clear user context on logout
|
||||
export function clearUserContext() {
|
||||
Sentry.setUser(null);
|
||||
}
|
||||
|
||||
// Add breadcrumb for debugging
|
||||
export function addBreadcrumb(message: string, category: string, data?: Record<string, unknown>) {
|
||||
Sentry.addBreadcrumb({
|
||||
message,
|
||||
category,
|
||||
data,
|
||||
level: "info",
|
||||
});
|
||||
}
|
||||
|
||||
export { Sentry };
|
||||
@@ -58,7 +58,7 @@ if (!isTestEnv && (!supabaseUrl || !supabaseAnonKey)) {
|
||||
if (!supabaseAnonKey) missing.push('EXPO_PUBLIC_SUPABASE_ANON_KEY');
|
||||
const errorMsg = `Missing required environment variables: ${missing.join(', ')}. App cannot start.`;
|
||||
console.error('[Supabase]', errorMsg);
|
||||
// In production, this will be caught by Sentry before crashing
|
||||
// In production, this will be caught by Crashlytics before crashing
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
|
||||
|
||||
Generated
+235
-308
@@ -79,11 +79,11 @@
|
||||
"@react-native-async-storage/async-storage": "1.23.1",
|
||||
"@react-native-firebase/analytics": "^23.8.2",
|
||||
"@react-native-firebase/app": "^23.8.2",
|
||||
"@react-native-firebase/crashlytics": "^23.8.4",
|
||||
"@react-native-google-signin/google-signin": "^16.1.1",
|
||||
"@react-navigation/bottom-tabs": "^7.0.0",
|
||||
"@react-navigation/native": "^7.0.0",
|
||||
"@react-navigation/native-stack": "^7.0.0",
|
||||
"@sentry/react-native": "~6.10.0",
|
||||
"@supabase/supabase-js": "^2.39.0",
|
||||
"@tanstack/react-query": "^5.17.0",
|
||||
"babel-preset-expo": "~12.0.0",
|
||||
@@ -142,6 +142,168 @@
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/@firebase/ai": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/ai/-/ai-2.7.0.tgz",
|
||||
"integrity": "sha512-PwpCz+TtAMWICM7uQNO0mkSPpUKwrMV4NSwHkbVKDvPKoaQmSlO96vIz+Suw2Ao1EaUUsxYb5LGImHWt/fSnRQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/app-check-interop-types": "0.3.3",
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/logger": "0.5.0",
|
||||
"@firebase/util": "1.13.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x",
|
||||
"@firebase/app-types": "0.x"
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/@firebase/app": {
|
||||
"version": "0.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.7.tgz",
|
||||
"integrity": "sha512-o3ZfnOx0AWBD5n/36p2zPoB0rDDxQP8H/A60zDLvvfRLtW8b3LfCyV97GKpJaAVV1JMMl/BC89EDzMyzxFZxTw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/logger": "0.5.0",
|
||||
"@firebase/util": "1.13.0",
|
||||
"idb": "7.1.1",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/@firebase/app-compat": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.7.tgz",
|
||||
"integrity": "sha512-MO+jfap8IBZQ+K8L2QCiHObyMgpYHrxo4Hc7iJgfb9hjGRW/z1y6LWVdT9wBBK+VJ7cRP2DjAiWQP+thu53hHA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/app": "0.14.7",
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/logger": "0.5.0",
|
||||
"@firebase/util": "1.13.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/@firebase/firestore": {
|
||||
"version": "4.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.10.0.tgz",
|
||||
"integrity": "sha512-fgF6EbpoagGWh5Vwfu/7/jYgBFwUCwTlPNVF/aSjHcoEDRXpRsIqVfAFTp1LD+dWAUcAKEK3h+osk8spMJXtxA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/logger": "0.5.0",
|
||||
"@firebase/util": "1.13.0",
|
||||
"@firebase/webchannel-wrapper": "1.0.5",
|
||||
"@grpc/grpc-js": "~1.9.0",
|
||||
"@grpc/proto-loader": "^0.7.8",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/@firebase/firestore-compat": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.4.4.tgz",
|
||||
"integrity": "sha512-JvxxIgi+D5v9BecjLA1YomdyF7LA6CXhJuVK10b4GtRrB3m2O2hT1jJWbKYZYHUAjTaajkvnos+4U5VNxqkI2w==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/firestore": "4.10.0",
|
||||
"@firebase/firestore-types": "3.0.3",
|
||||
"@firebase/util": "1.13.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/@firebase/remote-config": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.8.0.tgz",
|
||||
"integrity": "sha512-sJz7C2VACeE257Z/3kY9Ap2WXbFsgsDLfaGfZmmToKAK39ipXxFan+vzB9CSbF6mP7bzjyzEnqPcMXhAnYE6fQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/installations": "0.6.19",
|
||||
"@firebase/logger": "0.5.0",
|
||||
"@firebase/util": "1.13.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x"
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/@firebase/remote-config-compat": {
|
||||
"version": "0.2.21",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.21.tgz",
|
||||
"integrity": "sha512-9+lm0eUycxbu8GO25JfJe4s6R2xlDqlVt0CR6CvN9E6B4AFArEV4qfLoDVRgIEB7nHKwvH2nYRocPWfmjRQTnw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/logger": "0.5.0",
|
||||
"@firebase/remote-config": "0.8.0",
|
||||
"@firebase/remote-config-types": "0.5.0",
|
||||
"@firebase/util": "1.13.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app-compat": "0.x"
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/@react-native-firebase/app": {
|
||||
"version": "23.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-firebase/app/-/app-23.8.4.tgz",
|
||||
"integrity": "sha512-xURXijgL5gH5O6X7aUXKS5TObDT/aqWpdJpyUNWvRtG2cUxDRcLaSfJnSJP0TREBFAP1Dntdms2kmt5l2oSYZg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"firebase": "12.8.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"expo": ">=47.0.0",
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"expo": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/@react-native-firebase/crashlytics": {
|
||||
"version": "23.8.4",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-firebase/crashlytics/-/crashlytics-23.8.4.tgz",
|
||||
"integrity": "sha512-5zGzbXQ7u24TqwTCRIqo63Sw2C6VgPdgEJnR+Iwh5G2NSt339wcbsxyLRaM5cP25M7Obve0JrUUG9bTDI2qIOQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"stacktrace-js": "^2.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-native-firebase/app": "23.8.4",
|
||||
"expo": ">=47.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"expo": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/expo-sharing": {
|
||||
"version": "13.0.1",
|
||||
"resolved": "https://registry.npmjs.org/expo-sharing/-/expo-sharing-13.0.1.tgz",
|
||||
@@ -151,6 +313,66 @@
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/firebase": {
|
||||
"version": "12.8.0",
|
||||
"resolved": "https://registry.npmjs.org/firebase/-/firebase-12.8.0.tgz",
|
||||
"integrity": "sha512-S1tCIR3ENecee0tY2cfTHfMkXqkitHfbsvqpCtvsT0Zi9vDB7A4CodAjHfHCjVvu/XtGy1LHLjOasVcF10rCVw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/ai": "2.7.0",
|
||||
"@firebase/analytics": "0.10.19",
|
||||
"@firebase/analytics-compat": "0.2.25",
|
||||
"@firebase/app": "0.14.7",
|
||||
"@firebase/app-check": "0.11.0",
|
||||
"@firebase/app-check-compat": "0.4.0",
|
||||
"@firebase/app-compat": "0.5.7",
|
||||
"@firebase/app-types": "0.9.3",
|
||||
"@firebase/auth": "1.12.0",
|
||||
"@firebase/auth-compat": "0.6.2",
|
||||
"@firebase/data-connect": "0.3.12",
|
||||
"@firebase/database": "1.1.0",
|
||||
"@firebase/database-compat": "2.1.0",
|
||||
"@firebase/firestore": "4.10.0",
|
||||
"@firebase/firestore-compat": "0.4.4",
|
||||
"@firebase/functions": "0.13.1",
|
||||
"@firebase/functions-compat": "0.4.1",
|
||||
"@firebase/installations": "0.6.19",
|
||||
"@firebase/installations-compat": "0.2.19",
|
||||
"@firebase/messaging": "0.12.23",
|
||||
"@firebase/messaging-compat": "0.2.23",
|
||||
"@firebase/performance": "0.7.9",
|
||||
"@firebase/performance-compat": "0.2.22",
|
||||
"@firebase/remote-config": "0.8.0",
|
||||
"@firebase/remote-config-compat": "0.2.21",
|
||||
"@firebase/storage": "0.14.0",
|
||||
"@firebase/storage-compat": "0.4.0",
|
||||
"@firebase/util": "1.13.0"
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/firebase/node_modules/@firebase/auth": {
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.12.0.tgz",
|
||||
"integrity": "sha512-zkvLpsrxynWHk07qGrUDfCSqKf4AvfZGEqJ7mVCtYGjNNDbGE71k0Yn84rg8QEZu4hQw1BC0qDEHzpNVBcSVmA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/logger": "0.5.0",
|
||||
"@firebase/util": "1.13.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@firebase/app": "0.x",
|
||||
"@react-native-async-storage/async-storage": "^2.2.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@react-native-async-storage/async-storage": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"apps/mobile/node_modules/react-native-svg": {
|
||||
"version": "15.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.8.0.tgz",
|
||||
@@ -4194,6 +4416,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@firebase/ai/-/ai-2.6.1.tgz",
|
||||
"integrity": "sha512-qJd9bpABqsanFnwdbjZEDbKKr1jRtuUZ+cHyNBLWsxobH4pd73QncvuO3XlMq4eKBLlg1f5jNdFpJ3G3ABu2Tg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@firebase/app-check-interop-types": "0.3.3",
|
||||
"@firebase/component": "0.7.0",
|
||||
@@ -4252,6 +4475,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.6.tgz",
|
||||
"integrity": "sha512-4uyt8BOrBsSq6i4yiOV/gG6BnnrvTeyymlNcaN/dKvyU1GoolxAafvIvaNP1RCGPlNab3OuE4MKUQuv2lH+PLQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/logger": "0.5.0",
|
||||
@@ -4318,6 +4542,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.6.tgz",
|
||||
"integrity": "sha512-YYGARbutghQY4zZUWMYia0ib0Y/rb52y72/N0z3vglRHL7ii/AaK9SA7S/dzScVOlCdnbHXz+sc5Dq+r8fwFAg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@firebase/app": "0.14.6",
|
||||
"@firebase/component": "0.7.0",
|
||||
@@ -4473,6 +4698,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.9.3.tgz",
|
||||
"integrity": "sha512-RVuvhcQzs1sD5Osr2naQS71H0bQMbSnib16uOWAKk3GaKb/WBPyCYSr2Ry7MqlxDP/YhwknUxECL07lw9Rq1nA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/logger": "0.5.0",
|
||||
@@ -4494,6 +4720,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.4.3.tgz",
|
||||
"integrity": "sha512-1ylF/njF68Pmb6p0erP0U78XQv1w77Wap4bUmqZ7ZVkmN1oMgplyu0TyirWtCBoKFRV2+SUZfWXvIij/z39LYg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/firestore": "4.9.3",
|
||||
@@ -4698,6 +4925,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.7.0.tgz",
|
||||
"integrity": "sha512-dX95X6WlW7QlgNd7aaGdjAIZUiQkgWgNS+aKNu4Wv92H1T8Ue/NDUjZHd9xb8fHxLXIHNZeco9/qbZzr500MjQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/installations": "0.6.19",
|
||||
@@ -4714,6 +4942,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.20.tgz",
|
||||
"integrity": "sha512-P/ULS9vU35EL9maG7xp66uljkZgcPMQOxLj3Zx2F289baTKSInE6+YIkgHEi1TwHoddC/AFePXPpshPlEFkbgg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/logger": "0.5.0",
|
||||
@@ -7759,6 +7988,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@react-native-firebase/app/-/app-23.8.3.tgz",
|
||||
"integrity": "sha512-woH8Y+9MInWK3SG2Y+V4bxi4406AuDDoUaB7x2WmEueUiJxVvlAvPJ/uGLPrqmUFyk0tiv2DXPlcEfBzxXUlZQ==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"firebase": "12.7.0"
|
||||
},
|
||||
@@ -8662,303 +8892,6 @@
|
||||
"join-component": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/browser-utils": {
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.54.0.tgz",
|
||||
"integrity": "sha512-DKWCqb4YQosKn6aD45fhKyzhkdG7N6goGFDeyTaJFREJDFVDXiNDsYZu30nJ6BxMM7uQIaARhPAC5BXfoED3pQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "8.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/feedback": {
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.54.0.tgz",
|
||||
"integrity": "sha512-nQqRacOXoElpE0L0ADxUUII0I3A94niqG9Z4Fmsw6057QvyrV/LvTiMQBop6r5qLjwMqK+T33iR4/NQI5RhsXQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "8.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay": {
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.54.0.tgz",
|
||||
"integrity": "sha512-8xuBe06IaYIGJec53wUC12tY2q4z2Z0RPS2s1sLtbA00EvK1YDGuXp96IDD+HB9mnDMrQ/jW5f97g9TvPsPQUg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "8.54.0",
|
||||
"@sentry/core": "8.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay-canvas": {
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.54.0.tgz",
|
||||
"integrity": "sha512-K/On3OAUBeq/TV2n+1EvObKC+WMV9npVXpVyJqCCyn8HYMm8FUGzuxeajzm0mlW4wDTPCQor6mK9/IgOquUzCw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/replay": "8.54.0",
|
||||
"@sentry/core": "8.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/babel-plugin-component-annotate": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.2.tgz",
|
||||
"integrity": "sha512-D+SKQ266ra/wo87s9+UI/rKQi3qhGPCR8eSCDe0VJudhjHsqyNU+JJ5lnIGCgmZaWFTXgdBP/gdr1Iz1zqGs4Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.54.0.tgz",
|
||||
"integrity": "sha512-BgUtvxFHin0fS0CmJVKTLXXZcke0Av729IVfi+2fJ4COX8HO7/HAP02RKaSQGmL2HmvWYTfNZ7529AnUtrM4Rg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "8.54.0",
|
||||
"@sentry-internal/feedback": "8.54.0",
|
||||
"@sentry-internal/replay": "8.54.0",
|
||||
"@sentry-internal/replay-canvas": "8.54.0",
|
||||
"@sentry/core": "8.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli": {
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.42.4.tgz",
|
||||
"integrity": "sha512-BoSZDAWJiz/40tu6LuMDkSgwk4xTsq6zwqYoUqLU3vKBR/VsaaQGvu6EWxZXORthfZU2/5Agz0+t220cge6VQw==",
|
||||
"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.42.4",
|
||||
"@sentry/cli-linux-arm": "2.42.4",
|
||||
"@sentry/cli-linux-arm64": "2.42.4",
|
||||
"@sentry/cli-linux-i686": "2.42.4",
|
||||
"@sentry/cli-linux-x64": "2.42.4",
|
||||
"@sentry/cli-win32-i686": "2.42.4",
|
||||
"@sentry/cli-win32-x64": "2.42.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-darwin": {
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.42.4.tgz",
|
||||
"integrity": "sha512-PZV4Y97VDWBR4rIt0HkJfXaBXlebIN2s/FDzC3iHINZE5OG62CDFsnC4/lbGlf2/UZLDaGGIK7mYwSHhTvN+HQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-linux-arm": {
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.4.tgz",
|
||||
"integrity": "sha512-lBn0oeeg62h68/4Eo6zbPq99Idz5t0VRV48rEU/WKeM4MtQCvG/iGGQ3lBFW2yNiUBzXZIK9poXLEcgbwmcRVw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux",
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-linux-arm64": {
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.4.tgz",
|
||||
"integrity": "sha512-Ex8vRnryyzC/9e43daEmEqPS+9uirY/l6Hw2lAvhBblFaL7PTWNx52H+8GnYGd9Zy2H3rWNyBDYfHwnErg38zA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux",
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-linux-i686": {
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.4.tgz",
|
||||
"integrity": "sha512-IBJg0aHjsLCL4LvcFa3cXIjA+4t5kPqBT9y+PoDu4goIFxYD8zl7mbUdGJutvJafTk8Akf4ss4JJXQBjg019zA==",
|
||||
"cpu": [
|
||||
"x86",
|
||||
"ia32"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux",
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-linux-x64": {
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.4.tgz",
|
||||
"integrity": "sha512-gXI5OEiOSNiAEz7VCE6AZcAgHJ47mlgal3+NmbE8XcHmFOnyDws9FNie6PJAy8KZjXi3nqoBP9JVAbnmOix3uA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux",
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-win32-i686": {
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.4.tgz",
|
||||
"integrity": "sha512-vZuR3UPHKqOMniyrijrrsNwn9usaRysXq78F6WV0cL0ZyPLAmY+KBnTDSFk1Oig2pURnzaTm+RtcZu2fc8mlzg==",
|
||||
"cpu": [
|
||||
"x86",
|
||||
"ia32"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-win32-x64": {
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.4.tgz",
|
||||
"integrity": "sha512-OIBj3uaQ6nAERSm5Dcf8UIhyElEEwMNsZEEppQpN4IKl0mrwb/57AznM23Dvpu6GR8WGbVQUSolt879YZR5E9g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.54.0.tgz",
|
||||
"integrity": "sha512-03bWf+D1j28unOocY/5FDB6bUHtYlm6m6ollVejhg45ZmK9iPjdtxNWbrLsjT1WRym0Tjzowu+A3p+eebYEv0Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/react": {
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.54.0.tgz",
|
||||
"integrity": "sha512-42T/fp8snYN19Fy/2P0Mwotu4gcdy+1Lx+uYCNcYP1o7wNGigJ7qb27sW7W34GyCCHjoCCfQgeOqDQsyY8LC9w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/browser": "8.54.0",
|
||||
"@sentry/core": "8.54.0",
|
||||
"hoist-non-react-statics": "^3.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.14.0 || 17.x || 18.x || 19.x"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/react-native": {
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/react-native/-/react-native-6.10.0.tgz",
|
||||
"integrity": "sha512-B56vc+pnFHMiu3cabFb454v4qD0zObW6JVzJ5Gb6fIMdt93AFIJg10ZErzC+ump7xM4BOEROFFRuLiyvadvlPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/babel-plugin-component-annotate": "3.2.2",
|
||||
"@sentry/browser": "8.54.0",
|
||||
"@sentry/cli": "2.42.4",
|
||||
"@sentry/core": "8.54.0",
|
||||
"@sentry/react": "8.54.0",
|
||||
"@sentry/types": "8.54.0",
|
||||
"@sentry/utils": "8.54.0"
|
||||
},
|
||||
"bin": {
|
||||
"sentry-expo-upload-sourcemaps": "scripts/expo-upload-sourcemaps.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"expo": ">=49.0.0",
|
||||
"react": ">=17.0.0",
|
||||
"react-native": ">=0.65.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"expo": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/types": {
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.54.0.tgz",
|
||||
"integrity": "sha512-wztdtr7dOXQKi0iRvKc8XJhJ7HaAfOv8lGu0yqFOFwBZucO/SHnu87GOPi8mvrTiy1bentQO5l+zXWAaMvG4uw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "8.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/utils": {
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.54.0.tgz",
|
||||
"integrity": "sha512-JL8UDjrsKxKclTdLXfuHfE7B3KbrAPEYP7tMyN/xiO2vsF6D84fjwYyalO0ZMtuFZE6vpSze8ZOLEh6hLnPYsw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "8.54.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sinclair/typebox": {
|
||||
"version": "0.27.8",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
||||
@@ -10626,6 +10559,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"
|
||||
@@ -15477,6 +15411,7 @@
|
||||
"resolved": "https://registry.npmjs.org/firebase/-/firebase-12.7.0.tgz",
|
||||
"integrity": "sha512-ZBZg9jFo8uH4Emd7caOqtalKJfDGHnHQSrCPiqRAdTFQd0wL3ERilUBfhnhBLnlernugkN/o7nJa0p+sE71Izg==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@firebase/ai": "2.6.1",
|
||||
"@firebase/analytics": "0.10.19",
|
||||
@@ -15513,6 +15448,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.12.0.tgz",
|
||||
"integrity": "sha512-zkvLpsrxynWHk07qGrUDfCSqKf4AvfZGEqJ7mVCtYGjNNDbGE71k0Yn84rg8QEZu4hQw1BC0qDEHzpNVBcSVmA==",
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@firebase/component": "0.7.0",
|
||||
"@firebase/logger": "0.5.0",
|
||||
@@ -16317,6 +16253,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",
|
||||
@@ -21929,12 +21866,6 @@
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"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/psl": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
|
||||
@@ -23792,7 +23723,6 @@
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz",
|
||||
"integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"stackframe": "^1.3.4"
|
||||
@@ -23829,7 +23759,6 @@
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz",
|
||||
"integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"source-map": "0.5.6",
|
||||
@@ -23840,7 +23769,6 @@
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
|
||||
"integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -23850,7 +23778,6 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",
|
||||
"integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"error-stack-parser": "^2.0.6",
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
-- Helper function: sends a Discord notification via the send-discord-notification edge function
|
||||
CREATE OR REPLACE FUNCTION public.notify_discord_event(p_event text, p_payload jsonb)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
AS $$
|
||||
BEGIN
|
||||
PERFORM net.http_post(
|
||||
url := 'https://ckjcrkjpmhqhiucifukx.supabase.co/functions/v1/send-discord-notification',
|
||||
headers := jsonb_build_object('Content-Type', 'application/json'),
|
||||
body := jsonb_build_object(
|
||||
'event', p_event,
|
||||
'payload', p_payload
|
||||
)
|
||||
);
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- Trigger function: new user signup
|
||||
CREATE OR REPLACE FUNCTION public.notify_new_user_discord()
|
||||
RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
AS $$
|
||||
BEGIN
|
||||
PERFORM public.notify_discord_event(
|
||||
'new_user',
|
||||
jsonb_build_object(
|
||||
'user_id', NEW.id,
|
||||
'name', NEW.name,
|
||||
'email', NEW.email,
|
||||
'created_at', NEW.created_at
|
||||
)
|
||||
);
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- Trigger function: couple paired (fires when second partner joins)
|
||||
CREATE OR REPLACE FUNCTION public.notify_couple_paired_discord()
|
||||
RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
AS $$
|
||||
DECLARE
|
||||
v_member_count integer;
|
||||
v_profiles jsonb;
|
||||
BEGIN
|
||||
IF NEW.couple_id IS NULL OR OLD.couple_id IS NOT DISTINCT FROM NEW.couple_id THEN
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
SELECT COUNT(*)
|
||||
INTO v_member_count
|
||||
FROM public.profiles
|
||||
WHERE couple_id = NEW.couple_id;
|
||||
|
||||
IF v_member_count = 2 THEN
|
||||
SELECT jsonb_agg(
|
||||
jsonb_build_object(
|
||||
'id', p.id,
|
||||
'name', p.name,
|
||||
'email', p.email
|
||||
)
|
||||
ORDER BY p.created_at
|
||||
)
|
||||
INTO v_profiles
|
||||
FROM public.profiles p
|
||||
WHERE p.couple_id = NEW.couple_id;
|
||||
|
||||
PERFORM public.notify_discord_event(
|
||||
'couple_paired',
|
||||
jsonb_build_object(
|
||||
'couple_id', NEW.couple_id,
|
||||
'profiles', COALESCE(v_profiles, '[]'::jsonb),
|
||||
'paired_at', now()
|
||||
)
|
||||
);
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- Trigger function: feedback submitted
|
||||
CREATE OR REPLACE FUNCTION public.notify_feedback_submitted_discord()
|
||||
RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
AS $$
|
||||
DECLARE
|
||||
v_user jsonb;
|
||||
BEGIN
|
||||
SELECT jsonb_build_object(
|
||||
'id', p.id,
|
||||
'name', p.name,
|
||||
'email', p.email
|
||||
)
|
||||
INTO v_user
|
||||
FROM public.profiles p
|
||||
WHERE p.id = NEW.user_id;
|
||||
|
||||
PERFORM public.notify_discord_event(
|
||||
'feedback_submitted',
|
||||
jsonb_build_object(
|
||||
'feedback_id', NEW.id,
|
||||
'user_id', NEW.user_id,
|
||||
'type', NEW.type,
|
||||
'title', NEW.title,
|
||||
'description', NEW.description,
|
||||
'status', NEW.status,
|
||||
'screenshot_url', NEW.screenshot_url,
|
||||
'question_id', NEW.question_id,
|
||||
'created_at', NEW.created_at,
|
||||
'user', v_user
|
||||
)
|
||||
);
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- Create triggers (drop first to be idempotent)
|
||||
DROP TRIGGER IF EXISTS on_profile_created_discord ON public.profiles;
|
||||
CREATE TRIGGER on_profile_created_discord
|
||||
AFTER INSERT ON public.profiles
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.notify_new_user_discord();
|
||||
|
||||
DROP TRIGGER IF EXISTS on_profile_couple_paired_discord ON public.profiles;
|
||||
CREATE TRIGGER on_profile_couple_paired_discord
|
||||
AFTER UPDATE OF couple_id ON public.profiles
|
||||
FOR EACH ROW
|
||||
WHEN (OLD.couple_id IS DISTINCT FROM NEW.couple_id AND NEW.couple_id IS NOT NULL)
|
||||
EXECUTE FUNCTION public.notify_couple_paired_discord();
|
||||
|
||||
DROP TRIGGER IF EXISTS on_feedback_submitted_discord ON public.feedback;
|
||||
CREATE TRIGGER on_feedback_submitted_discord
|
||||
AFTER INSERT ON public.feedback
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION public.notify_feedback_submitted_discord();
|
||||
Reference in new issue
Block a user