@bsv/wallet-toolbox
Version:
BRC100 conforming wallet, wallet storage and wallet signer components
73 lines (68 loc) • 2.2 kB
text/typescript
import {} from '../../index.client'
import { maxDate, sdk, verifyId } from '../../../index.client'
import { EntityBase, EntityStorage, EntitySyncMap, SyncMap } from './EntityBase'
/**
* @param API one of the storage table interfaces.
* @param DE the corresponding entity class
*/
export class MergeEntity<API extends sdk.EntityTimeStamp, DE extends EntityBase<API>> {
idMap: Record<number, number>
constructor(
public stateArray: API[] | undefined,
public find: (
storage: EntityStorage,
userId: number,
ei: API,
syncMap: SyncMap,
trx?: sdk.TrxToken
) => Promise<{ found: boolean; eo: DE; eiId: number }>,
/** id map for primary id of API and DE object. */
public esm: EntitySyncMap
) {
this.idMap = esm.idMap
}
updateSyncMap(map: Record<number, number>, inId: number, outId: number) {
const i = verifyId(inId)
const o = verifyId(outId)
if (map[i] === undefined) {
map[i] = o
} else if (map[i] !== o)
throw new sdk.WERR_INTERNAL(`updateSyncMap map[${inId}] can't override ${map[i]} with ${o}`)
}
/**
* @param since date of current sync chunk
*/
async merge(
since: Date | undefined,
storage: EntityStorage,
userId: number,
syncMap: SyncMap,
trx?: sdk.TrxToken
): Promise<{ inserts: number; updates: number }> {
let inserts = 0,
updates = 0
if (!this.stateArray) return { inserts, updates }
for (const ei of this.stateArray) {
this.esm.maxUpdated_at = maxDate(this.esm.maxUpdated_at, ei.updated_at)
/**
* TODO:
* Switch to using syncMap. If the ei id is in the map its an existing merge, else its a new merge.
*/
try {
const { found, eo, eiId } = await this.find(storage, userId, ei, syncMap, trx)
if (found) {
if (await eo.mergeExisting(storage, since, ei, syncMap, trx)) {
updates++
}
} else {
await eo.mergeNew(storage, userId, syncMap, trx)
inserts++
}
if (eiId > -1) this.updateSyncMap(this.idMap, eiId, eo.id)
} catch (eu: unknown) {
throw eu
}
}
return { inserts, updates }
}
}