UNPKG

rxidb

Version:

RxJS wrapper for IndexedDB

92 lines (73 loc) 2.64 kB
import { Observable, forkJoin, Subject, of, Observer } from 'rxjs'; import { take, map, switchMap } from 'rxjs/operators'; import { RxIDB } from './rxidb-db'; import { RxIDBLayers } from './rxidb.types'; import { RxIDBUpgrade } from './rxidb-upgrade'; export function openDB(dbName: string, dbVersion: number, stores?: RxIDBLayers[]): Observable<RxIDB> { let db$: Subject<RxIDB> = new Subject(); let upgrade$: Subject<void> = new Subject(); let rxIDB: RxIDB; let _onError = (e: any) => db$.error(e); let _onBlocked = (e: any) => db$.error(e); let _onSuccess = (event: any) => { rxIDB = rxIDB || new RxIDB(event.target.result); db$.next(rxIDB); db$.complete(); if (dbVersion === rxIDB.idb.version) { upgrade$.next(); upgrade$.complete(); } else { upgrade$.error('Upgrade error'); } }; let _onUpgradeNeeded = (event: any) => { rxIDB = rxIDB || new RxIDB(event.target.result); onUpgradeNeeded(new RxIDBUpgrade(rxIDB, event), stores).subscribe( () => upgrade$.next(), (e) => upgrade$.error(e), () => upgrade$.complete() ); }; return of(null).pipe( map(() => indexedDB.open(dbName, dbVersion)), switchMap((request: IDBOpenDBRequest) => { Object.assign(request, { onerror : _onError, onblocked : _onBlocked, onsuccess : _onSuccess, onupgradeneeded : (e: any) => _onUpgradeNeeded(e) }); return forkJoin([db$, upgrade$]).pipe( map(() => rxIDB) ); }) ); } export function onUpgradeNeeded(rxIDBUpgrade: RxIDBUpgrade, stores?: RxIDBLayers[]): Observable<any> { if (!stores || !stores.length) { return of(null); } return forkJoin(stores.map(layers => setupLayers(rxIDBUpgrade, layers))); } export function setupLayers(rxIDBUpgrade: RxIDBUpgrade, layers: RxIDBLayers = new Map()): Observable<any>[] { let { oldVersion } = rxIDBUpgrade; let observables: Observable<any>[] = [of(true)]; for (const [layerVersion, layerInstaller] of layers) { if (oldVersion < layerVersion) { let result = layerInstaller(rxIDBUpgrade); if (result instanceof Observable) { observables.push(result); } } } return observables; } export function dropDB(dbName: string): Observable<void> { return Observable.create((observer: Observer<void>) => { let request = indexedDB.deleteDatabase(dbName); request.onblocked = (e) => observer.error(e); request.onsuccess = () => observer.next(undefined); request.onerror = (e) => observer.error(e); }).pipe(take(1)); } export const rxidb = { openDB, dropDB };