chore: update package-lock.json with peer dependency flags#1
Conversation
Reorganize peer dependency flags in package-lock.json after npm install.
📝 WalkthroughWalkthroughUpdates project configuration and dependencies, adds Babel config, migrates inline SVGs to react-native-svg, introduces a navigation loading guard, and makes filesystem backup operations properly awaited. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…nore, and autoBackup.ts async/await fixes
Ensure backup files are deleted with await to prevent race conditions and ensure deletions complete before proceeding. Also add babel.config.js to include Babel configuration for the project build/transpilation.
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/CheckOutModal.tsx (1)
173-176: 🧹 Nitpick | 🔵 TrivialStale
modalIconstyle is now unused.After migrating
WarningIcon/DocumentIcontoreact-native-svgcomponents, the text-orientedmodalIconstyle (withfontSize/marginRight) is no longer applied anywhere in this file. Consider removing it to avoid confusion.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/CheckOutModal.tsx` around lines 173 - 176, The modalIcon style entry in the styles object (property name "modalIcon") is stale and unused after migrating WarningIcon/DocumentIcon to react-native-svg; remove the "modalIcon" key (the fontSize and marginRight fields) from the styles declaration in CheckOutModal.tsx and ensure there are no remaining references to styles.modalIcon elsewhere in the component (if any, replace with appropriate container/spacing styles or the svg-specific prop instead).src/navigation/Navigation.tsx (1)
75-108:⚠️ Potential issue | 🔴 CriticalCritical: Rules of Hooks violation — early return placed before
useStateanduseEffectcalls.The conditional return at lines 78–84 executes before the
useStatecalls at lines 85–87 anduseEffectcalls at lines 89 and 95. On the first render whenloadingistrue, React records only theuseApp()hook. Whenloadingbecomesfalseon the next render, React encounters three additionaluseStatehooks and twouseEffecthooks, causing a hook-count mismatch. This will throw "Rendered more hooks than during the previous render" and crash on every cold start.Move all hooks before the conditional return, or render the loading view as part of the returned JSX.
🛠️ Proposed fix
const Navigation = () => { const { appData, loading } = useApp(); - // Wait for data to load before rendering navigation - if (loading) { - return ( - <View style={{ flex: 1, backgroundColor: '#0f172a', justifyContent: 'center', alignItems: 'center' }}> - <ActivityIndicator size="large" color="#6366f1" /> - </View> - ); - } const [showOnboarding, setShowOnboarding] = useState(!appData.onboardingCompleted); const [updateInfo, setUpdateInfo] = useState<UpdateInfo | null>(null); const [showUpdateModal, setShowUpdateModal] = useState(false); useEffect(() => { setShowOnboarding(!appData.onboardingCompleted); }, [appData.onboardingCompleted]); useEffect(() => { - if (!showOnboarding && Platform.OS !== 'web') { + if (!loading && !showOnboarding && Platform.OS !== 'web') { checkForUpdate() .then(update => { if (update) { setUpdateInfo(update); setShowUpdateModal(true); } }) .catch(error => { console.log('Update check failed (non-critical):', error?.message || error); }); } - }, [showOnboarding]); + }, [loading, showOnboarding]); + // Wait for data to load before rendering navigation + if (loading) { + return ( + <View style={{ flex: 1, backgroundColor: '#0f172a', justifyContent: 'center', alignItems: 'center' }}> + <ActivityIndicator size="large" color="#6366f1" /> + </View> + ); + } + return ( <NavigationContainer>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/navigation/Navigation.tsx` around lines 75 - 108, The Navigation component currently returns early when loading before calling subsequent hooks, violating Rules of Hooks; move all hook calls (the useState calls for showOnboarding, updateInfo, showUpdateModal and the useEffect hooks that setShowOnboarding and checkForUpdate) above the conditional loading return so hooks are always invoked in the same order, or alternatively keep the hooks where they are but render the loading UI inside the component's returned JSX (e.g., render a loading View when loading is true) so useState/useEffect invocations (in Navigation) always run before any conditional return; ensure references to useApp(), setShowOnboarding, checkForUpdate, Platform, and setUpdateInfo remain intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@package.json`:
- Line 16: The dependency "@types/react" is currently listed under dependencies
but should be a dev-time only package; update package.json by removing
"@types/react" from "dependencies" and adding it to "devDependencies" with the
recommended semver (e.g., "^19"), then reinstall (npm/yarn/pnpm install) so
consumers don't receive runtime type packages and the project uses the correct
compile-time type dependency.
In `@src/navigation/Navigation.tsx`:
- Around line 76-84: The Navigation component currently blocks the UI while
useApp().loading is true; add a defensive max-wait (e.g., 10s) inside Navigation
by using a useEffect timer that flips a local "timedOut" state if loading
remains true, clear the timer when loading changes, and then render a recovery
UI when timedOut is true (e.g., show storage/app error from appData.storageError
or a retry button) instead of an indefinite ActivityIndicator; reference
useApp(), the loading flag, appData (storageError) and the current
ActivityIndicator render path to locate where to add the useEffect/timer and the
alternate render branch.
In `@src/utils/autoBackup.ts`:
- Around line 21-35: The code calls await on synchronous expo-file-system
methods — remove the unnecessary await when calling Directory.create(),
File.write(), and File.delete() (e.g., the backupDir.create() call that uses
Paths.cache and BACKUP_DIR_NAME and the File.write/File.delete sites) so the
code reflects the synchronous API, or if you deliberately want to future-proof
for potential async changes add a concise comment above each call explaining the
await was intentionally omitted/left for forward-compatibility; update the uses
of backupDir.create(), File.write(), and File.delete() accordingly.
---
Outside diff comments:
In `@src/components/CheckOutModal.tsx`:
- Around line 173-176: The modalIcon style entry in the styles object (property
name "modalIcon") is stale and unused after migrating WarningIcon/DocumentIcon
to react-native-svg; remove the "modalIcon" key (the fontSize and marginRight
fields) from the styles declaration in CheckOutModal.tsx and ensure there are no
remaining references to styles.modalIcon elsewhere in the component (if any,
replace with appropriate container/spacing styles or the svg-specific prop
instead).
In `@src/navigation/Navigation.tsx`:
- Around line 75-108: The Navigation component currently returns early when
loading before calling subsequent hooks, violating Rules of Hooks; move all hook
calls (the useState calls for showOnboarding, updateInfo, showUpdateModal and
the useEffect hooks that setShowOnboarding and checkForUpdate) above the
conditional loading return so hooks are always invoked in the same order, or
alternatively keep the hooks where they are but render the loading UI inside the
component's returned JSX (e.g., render a loading View when loading is true) so
useState/useEffect invocations (in Navigation) always run before any conditional
return; ensure references to useApp(), setShowOnboarding, checkForUpdate,
Platform, and setUpdateInfo remain intact.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 79663f90-3898-4994-a188-1f261d46396d
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (9)
.gitignoreapp.jsonbabel.config.jseas.jsonpackage.jsonsrc/components/CheckInModal.tsxsrc/components/CheckOutModal.tsxsrc/navigation/Navigation.tsxsrc/utils/autoBackup.ts
📜 Review details
🔇 Additional comments (3)
.gitignore (1)
20-20: Good addition for secret hygiene.Adding
*.keystoreis the right safeguard to prevent Android signing files from being committed.eas.json (1)
8-8: Looks good — preview Android profile is now cleaner and consistent.Using only
"buildType": "apk"here is valid and keeps thepreviewprofile simpler without hardcoding task-level behavior.package.json (1)
26-37: Dependency versions are correctly aligned with Expo SDK 54.The versions declared (React 19.1.0, React Native 0.81.5, React Native Web 0.21.0) match Expo SDK 54's official compatibility matrix. No misalignment detected; no additional verification needed.
| "@react-navigation/bottom-tabs": "^7.2.0", | ||
| "@react-navigation/native": "^7.0.14", | ||
| "@react-navigation/native-stack": "^7.2.0", | ||
| "@types/react": "~19.1.10", |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Move @types/react to devDependencies.
@types/react is only needed at compile time and shouldn't ship as a runtime dependency. Keeping it under dependencies increases install footprint for consumers (and pollutes type resolution in some setups). It belongs alongside babel-preset-expo in devDependencies.
🛠️ Proposed fix
"dependencies": {
"@react-native-async-storage/async-storage": "2.2.0",
"@react-navigation/bottom-tabs": "^7.2.0",
"@react-navigation/native": "^7.0.14",
"@react-navigation/native-stack": "^7.2.0",
- "@types/react": "~19.1.10",
"expo": "~54.0.33",
...
},
"private": true,
"devDependencies": {
+ "@types/react": "~19.1.10",
"babel-preset-expo": "~54.0.10"
}As per React 19 upgrade guide recommendations, install @types/react@^19 as a dev-time type dependency.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "@types/react": "~19.1.10", | |
| { | |
| "name": "my-app", | |
| ... | |
| "dependencies": { | |
| "@react-native-async-storage/async-storage": "2.2.0", | |
| "@react-navigation/bottom-tabs": "^7.2.0", | |
| "@react-navigation/native": "^7.0.14", | |
| "@react-navigation/native-stack": "^7.2.0", | |
| "expo": "~54.0.33", | |
| ... | |
| }, | |
| "private": true, | |
| "devDependencies": { | |
| "@types/react": "~19.1.10", | |
| "babel-preset-expo": "~54.0.10" | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@package.json` at line 16, The dependency "@types/react" is currently listed
under dependencies but should be a dev-time only package; update package.json by
removing "@types/react" from "dependencies" and adding it to "devDependencies"
with the recommended semver (e.g., "^19"), then reinstall (npm/yarn/pnpm
install) so consumers don't receive runtime type packages and the project uses
the correct compile-time type dependency.
| const { appData, loading } = useApp(); | ||
| // Wait for data to load before rendering navigation | ||
| if (loading) { | ||
| return ( | ||
| <View style={{ flex: 1, backgroundColor: '#0f172a', justifyContent: 'center', alignItems: 'center' }}> | ||
| <ActivityIndicator size="large" color="#6366f1" /> | ||
| </View> | ||
| ); | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Reliability: loading flag depends on loadData() completing — guard against indefinite loading.
Navigation now blocks all UI on loading. Per src/context/AppContext.tsx (Lines 76–89, 130–224), setLoading(false) is called in loadData's finally block and a fallback setLoading(false) exists in initApp's catch. That covers most cases, but if any synchronous code path in loadData itself throws before reaching the try (e.g., a thrown error during setLoading(true) or storage initialization, or a hung native call), users will see an indefinite spinner with no recovery path.
Consider adding a max-wait timeout (e.g., 10s) that forces past the loading screen and surfaces storageError, so the app degrades gracefully instead of hanging on the splash.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/navigation/Navigation.tsx` around lines 76 - 84, The Navigation component
currently blocks the UI while useApp().loading is true; add a defensive max-wait
(e.g., 10s) inside Navigation by using a useEffect timer that flips a local
"timedOut" state if loading remains true, clear the timer when loading changes,
and then render a recovery UI when timedOut is true (e.g., show storage/app
error from appData.storageError or a retry button) instead of an indefinite
ActivityIndicator; reference useApp(), the loading flag, appData (storageError)
and the current ActivityIndicator render path to locate where to add the
useEffect/timer and the alternate render branch.
| try { | ||
| // Use Paths.cache for backup storage | ||
| const backupDir = new Directory(Paths.cache, BACKUP_DIR_NAME); | ||
| // Create directory if it doesn't exist | ||
| if (!backupDir.exists) { | ||
| await backupDir.create(); | ||
| } | ||
| return backupDir; | ||
| } catch (error) { | ||
| console.error('Error getting backup directory:', error); | ||
| return null; | ||
| } | ||
| }; |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
🌐 Web query:
expo-file-system File.write Directory.create synchronous or async return type
💡 Result:
In the modern expo-file-system API (default import): - File.write(content): synchronous, returns void. Example: file.write('Hello, world!'); // no await needed, throws on error. - Directory.create(options?): synchronous, returns void. Example: dir.create; // no await, throws if fails. In the legacy API (import * as FileSystem from 'expo-file-system/legacy'): - FileSystem.writeAsStringAsync(fileUri, contents, options?): asynchronous, returns Promise. - FileSystem.makeDirectoryAsync(fileUri, options?): asynchronous, returns Promise. The modern API provides both sync (e.g., write, create, textSync) and async methods (e.g., text). Legacy methods ending in Async are promises. Official docs show sync usage without await/then for modern File.write and Directory.create.
Citations:
- 1: https://docs.expo.dev/versions/latest/sdk/filesystem/
- 2: https://docs.expo.dev/versions/v54.0.0/sdk/filesystem
- 3: https://github.com/expo/expo/blob/68661df5/packages/expo-file-system/build/ExpoFileSystem.types.d.ts
- 4: https://docs.expo.dev/versions/unversioned/sdk/filesystem/
- 5: https://docs.expo.dev/versions/v55.0.0/sdk/filesystem-legacy
Remove unnecessary await on synchronous methods, or add clarifying comments about intent.
In expo-file-system v19's modern API, Directory.create(), File.write(), and File.delete() are synchronous methods returning void — not Promises. Awaiting them is harmless but a no-op; the original code was already executing correctly. The PR framing this as an "async/await fix" is misleading since no async ordering bug existed.
If the intent is forward-compatibility for a potential future API change, consider adding an explanatory comment instead. Otherwise, remove the unnecessary await for clarity.
Applies to lines 21–35, 104, and 145–148.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/utils/autoBackup.ts` around lines 21 - 35, The code calls await on
synchronous expo-file-system methods — remove the unnecessary await when calling
Directory.create(), File.write(), and File.delete() (e.g., the
backupDir.create() call that uses Paths.cache and BACKUP_DIR_NAME and the
File.write/File.delete sites) so the code reflects the synchronous API, or if
you deliberately want to future-proof for potential async changes add a concise
comment above each call explaining the await was intentionally omitted/left for
forward-compatibility; update the uses of backupDir.create(), File.write(), and
File.delete() accordingly.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/navigation/Navigation.tsx`:
- Around line 100-107: The loading branch currently uses an inline style object
and an ActivityIndicator without accessibility labeling; extract the inline View
style into the component's StyleSheet (e.g., add styles.loadingContainer) and
move any ActivityIndicator style into the StyleSheet as well (e.g.,
styles.activityIndicator), then replace the inline object with
style={styles.loadingContainer} and add an accessibilityLabel prop to the
ActivityIndicator (e.g., accessibilityLabel="Loading"). Update any references in
the render return and ensure StyleSheet.create includes the new keys so the
loading UI matches the file's existing styling pattern.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: db07853c-f8c3-4779-8f16-90bbb08e7e94
📒 Files selected for processing (1)
src/navigation/Navigation.tsx
| // Wait for data to load before rendering navigation | ||
| if (loading) { | ||
| return ( | ||
| <View style={{ flex: 1, backgroundColor: '#0f172a', justifyContent: 'center', alignItems: 'center' }}> | ||
| <ActivityIndicator size="large" color="#6366f1" /> | ||
| </View> | ||
| ); | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Optional: extract inline style to StyleSheet and add accessibility label.
The loading gate is correct and works with AppContext.loadData's try/finally (which guarantees setLoading(false)). Two small polish items for this branch:
- Inline style object on
Viewallocates on every render and diverges from the rest of this file, which usesStyleSheet.create. ActivityIndicatorhas noaccessibilityLabel, so screen readers announce nothing while the app is gated on the splash.
♻️ Proposed refinement
// Wait for data to load before rendering navigation
if (loading) {
return (
- <View style={{ flex: 1, backgroundColor: '#0f172a', justifyContent: 'center', alignItems: 'center' }}>
- <ActivityIndicator size="large" color="#6366f1" />
+ <View style={styles.loadingContainer}>
+ <ActivityIndicator
+ size="large"
+ color="#6366f1"
+ accessibilityLabel="Loading"
+ />
</View>
);
}And in styles:
const styles = StyleSheet.create({
+ loadingContainer: {
+ flex: 1,
+ backgroundColor: '#0f172a',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
updateOverlay: {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Wait for data to load before rendering navigation | |
| if (loading) { | |
| return ( | |
| <View style={{ flex: 1, backgroundColor: '#0f172a', justifyContent: 'center', alignItems: 'center' }}> | |
| <ActivityIndicator size="large" color="#6366f1" /> | |
| </View> | |
| ); | |
| } | |
| // Wait for data to load before rendering navigation | |
| if (loading) { | |
| return ( | |
| <View style={styles.loadingContainer}> | |
| <ActivityIndicator | |
| size="large" | |
| color="#6366f1" | |
| accessibilityLabel="Loading" | |
| /> | |
| </View> | |
| ); | |
| } |
| // Wait for data to load before rendering navigation | |
| if (loading) { | |
| return ( | |
| <View style={{ flex: 1, backgroundColor: '#0f172a', justifyContent: 'center', alignItems: 'center' }}> | |
| <ActivityIndicator size="large" color="#6366f1" /> | |
| </View> | |
| ); | |
| } | |
| const styles = StyleSheet.create({ | |
| loadingContainer: { | |
| flex: 1, | |
| backgroundColor: '#0f172a', | |
| justifyContent: 'center', | |
| alignItems: 'center', | |
| }, | |
| // ... other existing styles | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/navigation/Navigation.tsx` around lines 100 - 107, The loading branch
currently uses an inline style object and an ActivityIndicator without
accessibility labeling; extract the inline View style into the component's
StyleSheet (e.g., add styles.loadingContainer) and move any ActivityIndicator
style into the StyleSheet as well (e.g., styles.activityIndicator), then replace
the inline object with style={styles.loadingContainer} and add an
accessibilityLabel prop to the ActivityIndicator (e.g.,
accessibilityLabel="Loading"). Update any references in the render return and
ensure StyleSheet.create includes the new keys so the loading UI matches the
file's existing styling pattern.
Summary
Changes
package-lock.jsonwith updated peer dependency flags for various @babel packages