import { Job , JobNumbered } from './jobTypes' ; type PersistedJob = JobNumbered & { isDone : boolean ; } ; const prefix = "@react-native-persisted-job" ; export type AsyncStorage = { setItem : ( key : string , item : any ) => Promise < void > ; getItem : ( key : string ) => Promise < any > ; removeItem : ( key : string ) => Promise < void > ; multiRemove : ( key : Array < string > ) => Promise < void > ; multiSet : < T > ( pairs : Array < { key : string ; value : T ; } > ) => Promise < void > ; } ; export type JobPersisterType = { persistNewJob : ( job : Job ) => Promise < JobNumbered > ; updateJob : ( job : JobNumbered ) => Promise < void > ; clearPersistedJob : ( job : JobNumbered ) => Promise < void > ; fetchAllPersistedJobs : ( ) => Promise < Array < PersistedJob > > ; clearDoneJobsFromStore : ( ) => Promise < void > ; } ; export async function JobPersister ( storeName , asyncStorage ) { const serialNumberKey = `${ prefix }:${ storeName }:currentSerialNumber` ; let currentSerialNumber = await asyncStorage . getItem ( serialNumberKey ) || 0 ; const stripPersistentFields = ( job ) => ( { id : job . id , args : job . args , jobType : job . jobType , serialNumber : job . serialNumber , timestamp : job . timestamp , state : job . state , extraPersistentData : job . extraPersistentData , } ) ; const getJobKey = ( serialNumber ) => `${ prefix }:${ storeName }:${ serialNumber }` ; async function persistNewJob ( job ) { currentSerialNumber ++ ; const serialNumber = currentSerialNumber ; const jobNumbered = { ... job , serialNumber } ; await asyncStorage . setItem ( serialNumberKey , currentSerialNumber ) ; await asyncStorage . setItem ( getJobKey ( serialNumber ) , { ... stripPersistentFields ( jobNumbered ) , isDone : false } ) ; return jobNumbered ; } async function updateJob ( job ) { await asyncStorage . setItem ( getJobKey ( job . serialNumber ) , { ... stripPersistentFields ( job ) , isDone : false } ) ; } async function clearPersistedJob ( job ) { await asyncStorage . setItem ( getJobKey ( job . serialNumber ) , { ... job , isDone : true } ) ; } async function fetchAllPersistedJobs ( ) { const persistedJobs = [ ] ; for ( let i = 1 ; i <= currentSerialNumber ; i ++ ) { persistedJobs . push ( await asyncStorage . getItem ( getJobKey ( i ) ) ) ; } return persistedJobs ; } async function clearDoneJobsFromStore ( ) { const allJobs = await fetchAllPersistedJobs ( ) ; const jobsInProgress = allJobs . filter ( job => job && ! job . isDone ) . map ( ( job , i ) => ( { ... job , serialNumber : i + 1 } ) ) ; const itemsToRemove = [ ] ; for ( let i = jobsInProgress . length + 1 ; i <= currentSerialNumber ; i ++ ) { itemsToRemove . push ( getJobKey ( i ) ) ; } const itemsToUpdate = jobsInProgress . map ( job => ( { key : getJobKey ( job . serialNumber ) , value : job } ) ) ; currentSerialNumber = jobsInProgress . length ; await Promise . all ( [ asyncStorage . multiSet ( itemsToUpdate ) , asyncStorage . multiRemove ( itemsToRemove ) , asyncStorage . setItem ( serialNumberKey , currentSerialNumber ) ] ) ; } return { persistNewJob , updateJob , clearPersistedJob , fetchAllPersistedJobs , clearDoneJobsFromStore , } ; }