Skip to content

Commit 3af3d57

Browse files
committed
Fix persistent storage check that was defeated by MemoryStorage fallback
StorageManager.getStorage("asyncStorage") silently falls back to MemoryStorage when AsyncStorage hasn't been initialized, and MemoryStorage.isAvailable() always returns true. This made the lifecycle guard ineffective — install events would still fire on every cold start without AsyncStorage. Fix: Add StorageManager.hasPersistentStorage() that checks if an initialized AsyncStorage adapter exists in the storages map, bypassing the fallback logic in getStorage(). https://claude.ai/code/session_0117WwRELH1nzVbxRj7Kmm5N
1 parent 4389c28 commit 3af3d57

3 files changed

Lines changed: 14 additions & 12 deletions

File tree

src/__tests__/lifecycle.test.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,8 @@ const mockStorageInstance = {
1919
isAvailable: jest.fn().mockReturnValue(true),
2020
};
2121

22-
const mockAsyncStorageInstance = {
23-
isAvailable: jest.fn().mockReturnValue(true),
24-
};
25-
2622
const mockStorageManager = {
27-
getStorage: jest.fn().mockReturnValue(mockAsyncStorageInstance),
23+
hasPersistentStorage: jest.fn().mockReturnValue(true),
2824
};
2925

3026
jest.mock('../lib/storage', () => ({
@@ -56,8 +52,7 @@ describe('AppLifecycleManager', () => {
5652
mockAnalytics = { track: jest.fn().mockResolvedValue(undefined) };
5753
mockStorageInstance.get.mockReturnValue(null);
5854
mockStorageInstance.set.mockReturnValue(undefined);
59-
mockAsyncStorageInstance.isAvailable.mockReturnValue(true);
60-
mockStorageManager.getStorage.mockReturnValue(mockAsyncStorageInstance);
55+
mockStorageManager.hasPersistentStorage.mockReturnValue(true);
6156
(storage as jest.Mock).mockReturnValue(mockStorageInstance);
6257
(getStorageManager as jest.Mock).mockReturnValue(mockStorageManager);
6358
(AppState.addEventListener as jest.Mock).mockReturnValue({ remove: jest.fn() });
@@ -229,7 +224,7 @@ describe('AppLifecycleManager', () => {
229224

230225
describe('no persistent storage', () => {
231226
it('should skip install/update detection when AsyncStorage is not available', async () => {
232-
mockAsyncStorageInstance.isAvailable.mockReturnValue(false);
227+
mockStorageManager.hasPersistentStorage.mockReturnValue(false);
233228

234229
await manager.start({ version: '1.0.0', build: '1' });
235230

@@ -244,7 +239,7 @@ describe('AppLifecycleManager', () => {
244239
});
245240

246241
it('should still fire Application Opened without persistent storage', async () => {
247-
mockAsyncStorageInstance.isAvailable.mockReturnValue(false);
242+
mockStorageManager.hasPersistentStorage.mockReturnValue(false);
248243

249244
await manager.start({ version: '1.0.0', build: '1' });
250245

src/lib/lifecycle/index.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,7 @@ export class AppLifecycleManager {
125125
*/
126126
private async detectInstallOrUpdate(): Promise<void> {
127127
const manager = getStorageManager();
128-
const hasPersistentStorage = manager
129-
? manager.getStorage("asyncStorage").isAvailable()
130-
: false;
128+
const hasPersistentStorage = manager?.hasPersistentStorage() ?? false;
131129

132130
if (!hasPersistentStorage) {
133131
logger.warn(

src/lib/storage/StorageManager.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,15 @@ export class StorageManager {
7575
}
7676
return this.getStorage("memoryStorage");
7777
}
78+
79+
/**
80+
* Check if persistent storage (AsyncStorage) has been initialized.
81+
* Returns false if only MemoryStorage is available.
82+
*/
83+
public hasPersistentStorage(): boolean {
84+
const stored = this.storages.get("asyncStorage");
85+
return stored !== undefined && stored.isAvailable();
86+
}
7887
}
7988

8089
// Global storage manager instance

0 commit comments

Comments
 (0)