UNPKG

@atproto/repo

Version:

atproto repo and MST implementation

118 lines (100 loc) 2.52 kB
import { CID } from 'multiformats' import { BlockMap } from './block-map' import { CidSet } from './cid-set' import { MST, NodeEntry, mstDiff } from './mst' export class DataDiff { adds: Record<string, DataAdd> = {} updates: Record<string, DataUpdate> = {} deletes: Record<string, DataDelete> = {} newMstBlocks: BlockMap = new BlockMap() newLeafCids: CidSet = new CidSet() removedCids: CidSet = new CidSet() static async of(curr: MST, prev: MST | null): Promise<DataDiff> { return mstDiff(curr, prev) } async nodeAdd(node: NodeEntry) { if (node.isLeaf()) { this.leafAdd(node.key, node.value) } else { const data = await node.serialize() this.treeAdd(data.cid, data.bytes) } } async nodeDelete(node: NodeEntry) { if (node.isLeaf()) { const key = node.key const cid = node.value this.deletes[key] = { key, cid } this.removedCids.add(cid) } else { const cid = await node.getPointer() this.treeDelete(cid) } } leafAdd(key: string, cid: CID) { this.adds[key] = { key, cid } if (this.removedCids.has(cid)) { this.removedCids.delete(cid) } else { this.newLeafCids.add(cid) } } leafUpdate(key: string, prev: CID, cid: CID) { if (prev.equals(cid)) return this.updates[key] = { key, prev, cid } this.removedCids.add(prev) this.newLeafCids.add(cid) } leafDelete(key: string, cid: CID) { this.deletes[key] = { key, cid } if (this.newLeafCids.has(cid)) { this.newLeafCids.delete(cid) } else { this.removedCids.add(cid) } } treeAdd(cid: CID, bytes: Uint8Array) { if (this.removedCids.has(cid)) { this.removedCids.delete(cid) } else { this.newMstBlocks.set(cid, bytes) } } treeDelete(cid: CID) { if (this.newMstBlocks.has(cid)) { this.newMstBlocks.delete(cid) } else { this.removedCids.add(cid) } } addList(): DataAdd[] { return Object.values(this.adds) } updateList(): DataUpdate[] { return Object.values(this.updates) } deleteList(): DataDelete[] { return Object.values(this.deletes) } updatedKeys(): string[] { const keys = [ ...Object.keys(this.adds), ...Object.keys(this.updates), ...Object.keys(this.deletes), ] return [...new Set(keys)] } } export type DataAdd = { key: string cid: CID } export type DataUpdate = { key: string prev: CID cid: CID } export type DataDelete = { key: string cid: CID }