import { Observable, switchMap } from "rxjs"; import { AppName, AppStorageType, BackupAppDataError, BackupAppDataEvent, BackupAppDataEventType, StorageProvider, } from "./types"; import { AppStorageInfo } from "@ledgerhq/device-core/index"; import { DeviceModelId } from "@ledgerhq/devices"; /** * Backs up the application data for a specific app on a Ledger device. All interactions * with the storage provider are handled by this function. * * @param storageProvider - The storage provider object used for storing the backup data. * @param appName - The name of the application to backup. * @param backupAppDataFn - The function that returns observable for the backup process. * @returns An observable that emits BackupAppDataEvent during the backup process. * @throws {BackupAppDataError} */ export function backupAppDataUseCase( appName: AppName, deviceModelId: DeviceModelId, storageProvider: StorageProvider, backupAppDataFn: () => Observable, ): Observable { let appDataInfo: AppStorageInfo; const obs: Observable = backupAppDataFn().pipe( switchMap(async (event: BackupAppDataEvent): Promise => { switch (event.type) { case BackupAppDataEventType.AppDataInfoFetched: { const appStorage = await storageProvider.getItem(`${deviceModelId}-${appName}`); // Check if the app data is already backed up if (appStorage && appStorage.appDataInfo?.hash === event.data.hash) { /** * We cannot get the observer's complete callback here, so need to execute it manually if needed */ return { type: BackupAppDataEventType.AppDataAlreadyBackedUp }; } // If not, store the app data info and transfer the event appDataInfo = event.data; return event; } case BackupAppDataEventType.AppDataBackedUp: // Store the app data if (appDataInfo) { await storageProvider.setItem(`${deviceModelId}-${appName}`, { appDataInfo, appData: event.data, }); } // Erase the app data, then return the event return { type: BackupAppDataEventType.AppDataBackedUp, data: "" }; case BackupAppDataEventType.Progress: case BackupAppDataEventType.NoAppDataToBackup: return event; default: throw new BackupAppDataError("Invalid event type"); } }), ); return obs; }