@elemental-concept/rx-persist
Version:
Persistence operator for RxJS
118 lines (110 loc) • 3.76 kB
JavaScript
import { Observable, from, of } from 'rxjs';
import { take, map, switchMap, filter, concatMap, takeLast } from 'rxjs/operators';
class DOMStorageDriver {
constructor(storage) {
this.storage = storage;
}
get(key) {
try {
const value = this.storage.getItem(key);
if (typeof value === 'string') {
return JSON.parse(value);
}
}
catch (e) {
}
return null;
}
set(key, value) {
this.storage.setItem(key, JSON.stringify(value));
return;
}
remove(key) {
this.storage.removeItem(key);
return;
}
}
const sessionStorageDriver = new DOMStorageDriver(sessionStorage);
const localStorageDriver = new DOMStorageDriver(localStorage);
function load(key, next, storage) {
const result = storage.get(key);
if (result instanceof Observable) {
result.pipe(take(1)).subscribe(v => next(v));
return;
}
if (typeof result?.then === 'function') {
result.then(v => next(v));
return;
}
if (result !== null && result !== undefined) {
next(result);
}
}
function loadAsObservable(key, storage) {
const result = storage.get(key);
if (result instanceof Observable) {
return result.pipe(take(1));
}
if (typeof result?.then === 'function') {
return from(result);
}
return of(result);
}
function save(key, storage, value) {
const result = storage.set(key, value);
if (result instanceof Observable) {
return result.pipe(take(1));
}
if (typeof result?.then === 'function') {
return from(result);
}
return of(true);
}
function getStorageKey(key) {
return typeof key === 'string' ? key : key.join('.');
}
class StorageAccessMock {
constructor() {
this.storage = {};
this.length = 0;
}
clear() {
}
getItem(key) {
return this.storage[key] === undefined ? null : this.storage[key];
}
key(index) {
return null;
}
removeItem(key) {
delete this.storage[key];
}
setItem(key, value) {
this.storage[key] = value;
}
}
function persistent(subject, key, storage = localStorageDriver) {
const next = subject.next.bind(subject);
const storageKey = getStorageKey(key);
load(storageKey, next, storage);
subject.next = (value) => save(storageKey, storage, value).subscribe(() => next(value));
return subject;
}
function persistentAndVersioned(subject, key, options) {
const next = subject.next.bind(subject);
const storage = options.storage !== undefined ? options.storage : localStorageDriver;
const storageKey = getStorageKey(key);
const versionKey = getStorageKey(options.versionKey);
loadAsObservable(versionKey, storage)
.pipe(map(version => typeof version === 'number' ? version : 0), switchMap(version => from([...Array(options.currentVersion).keys()])
.pipe(filter(v => v >= version))), concatMap(version => loadAsObservable(storageKey, storage)
.pipe(map(value => options.migrate(version, value)), concatMap(value => save(storageKey, storage, value)), concatMap(() => save(versionKey, storage, version + 1)))), takeLast(1))
.subscribe({ complete: () => load(storageKey, next, storage) });
subject.next = (value) => save(storageKey, storage, value).subscribe(() => next(value));
return subject;
}
/**
* Generated bundle index. Do not edit.
*/
export { DOMStorageDriver, localStorageDriver, persistent, persistentAndVersioned, sessionStorageDriver };
//# sourceMappingURL=elemental-concept-rx-persist.mjs.map