Fix EAS local builds and resolve require cycles

- Add dotenv-cli for EAS local builds to load env vars
- Break circular dependencies in store/hooks imports
- Add env var validation with clear error messages
- Remove hardcoded Sentry auth token from sentry.properties
- Add .ipa files to .gitignore

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
jjbruntonandClaude Opus 4.5 committed 2026-01-04 16:43:24 +00:00
1 parent bb2ce5a6a6
commit 58209b94ef
19 files changed
+458 -114

No files matched your search

+65 -65
View File
@@ -1,54 +1,54 @@
// Polyfills must be imported FIRST before any other React Native imports
import "../src/polyfills/web";
import "../src/polyfills/crypto";
// Initialize Sentry early to capture all errors
import { initSentry, setUserContext, clearUserContext } from "../src/lib/sentry";
initSentry();
// Initialize Analytics
import { initAnalytics, setUserId, clearUserId, logScreenView, Events } from "../src/lib/analytics";
initAnalytics();
// Track cold start immediately
Events.appOpened("cold");
// Import push notification utilities
import {
clearPushToken,
setupNotificationResponseListener,
getInitialNotification,
handleNotificationResponse,
} from "../src/lib/notifications";
import React, { useEffect, useRef } from "react";
import { Platform, View, AppState, AppStateStatus } from "react-native";
// Suppress useLayoutEffect warning on server-side rendering
if (Platform.OS === "web" && typeof globalThis.window === "undefined") {
React.useLayoutEffect = useEffect;
// Also silence the warning in case some libraries ignore the monkey-patch
const originalError = console.error;
console.error = (...args) => {
if (typeof args[0] === "string" && args[0].includes("useLayoutEffect does nothing on the server")) {
return;
}
originalError(...args);
};
}
import { Stack, router, usePathname } from "expo-router";
import { StatusBar } from "expo-status-bar";
// GestureHandlerRootView is only needed on native platforms
// On web, we use a simple View to avoid findNodeHandle errors
const GestureHandlerRootView = Platform.OS === "web"
? View
: require("react-native-gesture-handler").GestureHandlerRootView;
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import * as Linking from "expo-linking";
import { useAuthStore } from "../src/store";
import { supabase } from "../src/lib/supabase";
import { EncryptionKeyInitializer } from "../src/components/EncryptionKeyInitializer";
// Polyfills must be imported FIRST before any other React Native imports
import "../src/polyfills/web";
import "../src/polyfills/crypto";
// Initialize Sentry early to capture all errors
import { initSentry, setUserContext, clearUserContext } from "../src/lib/sentry";
initSentry();
// Initialize Analytics
import { initAnalytics, setUserId, clearUserId, logScreenView, Events } from "../src/lib/analytics";
initAnalytics();
// Track cold start immediately
Events.appOpened("cold");
// Import push notification utilities
import {
clearPushToken,
setupNotificationResponseListener,
getInitialNotification,
handleNotificationResponse,
} from "../src/lib/notifications";
import React, { useEffect, useRef } from "react";
import { Platform, View, AppState, AppStateStatus } from "react-native";
// Suppress useLayoutEffect warning on server-side rendering
if (Platform.OS === "web" && typeof globalThis.window === "undefined") {
React.useLayoutEffect = useEffect;
// Also silence the warning in case some libraries ignore the monkey-patch
const originalError = console.error;
console.error = (...args) => {
if (typeof args[0] === "string" && args[0].includes("useLayoutEffect does nothing on the server")) {
return;
}
originalError(...args);
};
}
import { Stack, router, usePathname } from "expo-router";
import { StatusBar } from "expo-status-bar";
// GestureHandlerRootView is only needed on native platforms
// On web, we use a simple View to avoid findNodeHandle errors
const GestureHandlerRootView = Platform.OS === "web"
? View
: require("react-native-gesture-handler").GestureHandlerRootView;
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import * as Linking from "expo-linking";
import { useAuthStore } from "../src/store";
import { supabase } from "../src/lib/supabase";
import { EncryptionKeyInitializer } from "../src/components/EncryptionKeyInitializer";
const queryClient = new QueryClient();
@@ -209,18 +209,18 @@ export default function RootLayout() {
}, []);
return (
<QueryClientProvider client={queryClient}>
<GestureHandlerRootView style={{ flex: 1 }}>
<StatusBar style="light" />
<EncryptionKeyInitializer />
<Stack
screenOptions={{
headerShown: false,
contentStyle: { backgroundColor: "#1a1a2e" },
}}
/>
</GestureHandlerRootView>
</QueryClientProvider>
);
return (
<QueryClientProvider client={queryClient}>
<GestureHandlerRootView style={{ flex: 1 }}>
<StatusBar style="light" />
<EncryptionKeyInitializer />
<Stack
screenOptions={{
headerShown: false,
contentStyle: { backgroundColor: "#1a1a2e" },
}}
/>
</GestureHandlerRootView>
</QueryClientProvider>
);
}