import { Level } from 'level'; import { ExporterState, PartialStateUpdate, Status } from './index'; import Config from '../config'; type LevelError = Error | null | undefined; //@ts-ignore const errorNotFound = (err: LevelError) => err.code && err.code == 'LEVEL_NOT_FOUND'; class LevelState { private _db = new Level('landsbankinn-exporter', { valueEncoding: 'json' }); private currentTTLHandle: number | undefined = -1; constructor() { function creator(err: Error | null | undefined) { if (err) { if (errorNotFound(err)) { console.info('Creating initial empty state'); //@ts-ignore this._db.put('state', {}); } } } const self = this; this.prepTTL().then(() => self._db.get('state', {}, creator.bind(self))); } get current(): Promise { return this._db.get('state') as unknown as Promise; } async clear() { console.info('Cleared state'); return await this._db.put('state', { status: Status.NotReady } as any); } private async clearTTL() { if (this.currentTTLHandle) { window.clearTimeout(this.currentTTLHandle); } } private async prepTTL() { console.info(`Will clear state in ${Config.StateTTL} milliseconds`); this.currentTTLHandle = window.setTimeout(async () => await this.clear(), Config.StateTTL); } async update(stateUpdate: ExporterState | PartialStateUpdate): Promise { this.clearTTL(); const currentState: ExporterState = await this.current; let newState = { ...currentState, ...stateUpdate }; await this._db.put('state', newState as any); this.prepTTL(); return this.current; } } export const State: LevelState = new LevelState();