59 lines
1.2 KiB
TypeScript
59 lines
1.2 KiB
TypeScript
|
import { v4 as uuidv4 } from 'uuid';
|
|||
|
import { Syncable } from './sync';
|
|||
|
import { Store } from './store';
|
|||
|
import { PubSub } from './transport';
|
|||
|
|
|||
|
function toIndexKey(id:string):string {
|
|||
|
const d = Date.now();
|
|||
|
return d + '_' + id + '_' + uuidv4();
|
|||
|
}
|
|||
|
|
|||
|
const _re_indexKey = /^\d+_(.+)_[-\d\w]+$/;
|
|||
|
function fromIndexKey(s:string):string {
|
|||
|
const m = s.match(_re_indexKey);
|
|||
|
if (m === null) {
|
|||
|
throw 'Invalid index key';
|
|||
|
}
|
|||
|
return m[1];
|
|||
|
}
|
|||
|
|
|||
|
class Dispatcher {
|
|||
|
|
|||
|
idx: Array<string>
|
|||
|
syncer: PubSub
|
|||
|
store: Store
|
|||
|
|
|||
|
constructor(store:Store, syncer:PubSub) {
|
|||
|
this.idx = new Array<string>()
|
|||
|
this.syncer = syncer;
|
|||
|
this.store = store;
|
|||
|
}
|
|||
|
|
|||
|
public isDirty(): boolean {
|
|||
|
return this.idx.length > 0;
|
|||
|
}
|
|||
|
|
|||
|
public add(id:string, item:Syncable): string {
|
|||
|
const v = item.toJSON();
|
|||
|
const k = toIndexKey(id);
|
|||
|
this.store.put(k, v, true);
|
|||
|
localStorage.setItem(k, v);
|
|||
|
this.idx.push(k);
|
|||
|
return k;
|
|||
|
}
|
|||
|
|
|||
|
public sync(offset:number): number {
|
|||
|
let i = 0;
|
|||
|
this.idx.forEach((k) => {
|
|||
|
const v = localStorage.getItem(k);
|
|||
|
const k_id = fromIndexKey(k);
|
|||
|
this.syncer.pub(v); // this must block until guaranteed delivery
|
|||
|
localStorage.removeItem(k);
|
|||
|
i++;
|
|||
|
});
|
|||
|
return i;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
export { Dispatcher, toIndexKey, fromIndexKey }
|