mobx-persist-store
Version:
Mobx Persist Store
174 lines (173 loc) • 8.67 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PersistStore = void 0;
const mobx_1 = require("mobx");
const PersistStoreMap_1 = require("./PersistStoreMap");
const StorageAdapter_1 = require("./StorageAdapter");
const configurePersistable_1 = require("./configurePersistable");
const serializableProperty_1 = require("./serializableProperty");
const utils_1 = require("./utils");
class PersistStore {
constructor(target, options, reactionOptions = {}) {
var _a, _b, _c, _d, _e, _f, _g, _h;
this.cancelWatch = null;
this.properties = [];
this.reactionOptions = {};
this.storageAdapter = null;
this.target = null;
this.version = undefined;
this.debugMode = false;
this.isHydrated = false;
this.isPersisting = false;
this.storageName = '';
this.target = target;
this.storageName = options.name;
this.version = (_a = options.version) !== null && _a !== void 0 ? _a : configurePersistable_1.mpsConfig.version;
this.properties = (0, serializableProperty_1.makeSerializableProperties)(options.properties);
this.reactionOptions = Object.assign({ fireImmediately: true }, configurePersistable_1.mpsReactionOptions, reactionOptions);
this.debugMode = (_c = (_b = options.debugMode) !== null && _b !== void 0 ? _b : configurePersistable_1.mpsConfig.debugMode) !== null && _c !== void 0 ? _c : false;
this.storageAdapter = new StorageAdapter_1.StorageAdapter({
version: this.version,
expireIn: (_d = options.expireIn) !== null && _d !== void 0 ? _d : configurePersistable_1.mpsConfig.expireIn,
removeOnExpiration: (_f = (_e = options.removeOnExpiration) !== null && _e !== void 0 ? _e : configurePersistable_1.mpsConfig.removeOnExpiration) !== null && _f !== void 0 ? _f : true,
stringify: (_h = (_g = options.stringify) !== null && _g !== void 0 ? _g : configurePersistable_1.mpsConfig.stringify) !== null && _h !== void 0 ? _h : true,
storage: options.storage ? options.storage : configurePersistable_1.mpsConfig.storage,
debugMode: this.debugMode,
});
(0, mobx_1.makeObservable)(this, {
clearPersistedStore: mobx_1.action,
hydrateStore: mobx_1.action,
isHydrated: mobx_1.observable,
isPersisting: mobx_1.observable,
pausePersisting: mobx_1.action,
startPersisting: mobx_1.action,
stopPersisting: mobx_1.action,
}, { autoBind: true, deep: false });
(0, utils_1.invalidStorageAdaptorWarningIf)(this.storageAdapter.options.storage, this.storageName);
(0, utils_1.consoleDebug)(this.debugMode, `${this.storageName} - (makePersistable)`, {
properties: this.properties,
storageAdapter: this.storageAdapter,
reactionOptions: this.reactionOptions,
});
}
async init() {
await this.hydrateStore();
this.startPersisting();
return this;
}
async hydrateStore() {
// If the user calls stopPersist and then rehydrateStore we don't want to automatically call startPersist below
const isBeingWatched = Boolean(this.cancelWatch);
if (this.isPersisting) {
this.pausePersisting();
}
(0, mobx_1.runInAction)(() => {
this.isHydrated = false;
(0, utils_1.consoleDebug)(this.debugMode, `${this.storageName} - (hydrateStore) isHydrated:`, this.isHydrated);
});
if (this.storageAdapter && this.target) {
const data = await this.storageAdapter.getItem(this.storageName);
// Reassigning so TypeScript doesn't complain (Object is possibly 'null') about this.target within forEach
const target = this.target;
if (data) {
(0, mobx_1.runInAction)(() => {
this.properties.forEach((property) => {
const allowPropertyHydration = [
property.key in target,
typeof data[property.key] !== 'undefined',
].every(Boolean);
if (allowPropertyHydration) {
const propertyData = data[property.key];
if (target[property.key] instanceof mobx_1.ObservableMap && (0, utils_1.isArrayForMap)(propertyData)) {
target[property.key] = property.deserialize(new Map(propertyData));
}
else if (target[property.key] instanceof mobx_1.ObservableSet && (0, utils_1.isArrayForSet)(propertyData)) {
target[property.key] = property.deserialize(new Set(propertyData));
}
else {
target[property.key] = property.deserialize(propertyData);
}
}
});
});
}
}
(0, mobx_1.runInAction)(() => {
this.isHydrated = true;
(0, utils_1.consoleDebug)(this.debugMode, `${this.storageName} - isHydrated:`, this.isHydrated);
});
if (isBeingWatched) {
this.startPersisting();
}
}
startPersisting() {
if (!this.storageAdapter || !this.target || this.cancelWatch) {
return;
}
// Reassigning so TypeScript doesn't complain (Object is possibly 'null') about and this.target within reaction
const target = this.target;
this.cancelWatch = (0, mobx_1.reaction)(() => {
const propertiesToWatch = {};
this.properties.forEach((property) => {
const isComputedProperty = (0, mobx_1.isComputedProp)(target, property.key);
const isActionProperty = (0, mobx_1.isAction)(target[property.key]);
(0, utils_1.computedPersistWarningIf)(isComputedProperty, String(property.key));
(0, utils_1.actionPersistWarningIf)(isActionProperty, String(property.key));
if (!isComputedProperty && !isActionProperty) {
let propertyData = property.serialize(target[property.key]);
if (propertyData instanceof mobx_1.ObservableMap) {
const mapArray = [];
propertyData.forEach((v, k) => {
mapArray.push([k, (0, mobx_1.toJS)(v)]);
});
propertyData = mapArray;
}
else if (propertyData instanceof mobx_1.ObservableSet) {
propertyData = Array.from(propertyData).map(mobx_1.toJS);
}
propertiesToWatch[property.key] = (0, mobx_1.toJS)(propertyData);
}
});
return propertiesToWatch;
}, async (dataToSave) => {
if (this.storageAdapter) {
await this.storageAdapter.setItem(this.storageName, dataToSave);
}
}, this.reactionOptions);
this.isPersisting = true;
(0, utils_1.consoleDebug)(this.debugMode, `${this.storageName} - (startPersisting) isPersisting:`, this.isPersisting);
}
pausePersisting() {
this.isPersisting = false;
(0, utils_1.consoleDebug)(this.debugMode, `${this.storageName} - pausePersisting (isPersisting):`, this.isPersisting);
if (this.cancelWatch) {
this.cancelWatch();
this.cancelWatch = null;
}
}
stopPersisting() {
this.pausePersisting();
(0, utils_1.consoleDebug)(this.debugMode, `${this.storageName} - (stopPersisting)`);
PersistStoreMap_1.PersistStoreMap.delete(this.target);
this.cancelWatch = null;
this.properties = [];
this.reactionOptions = {};
this.storageAdapter = null;
this.target = null;
}
async clearPersistedStore() {
if (this.storageAdapter) {
(0, utils_1.consoleDebug)(this.debugMode, `${this.storageName} - (clearPersistedStore)`);
await this.storageAdapter.removeItem(this.storageName);
}
}
async getPersistedStore() {
if (this.storageAdapter) {
(0, utils_1.consoleDebug)(this.debugMode, `${this.storageName} - (getPersistedStore)`);
// @ts-ignore
return this.storageAdapter.getItem(this.storageName);
}
return null;
}
}
exports.PersistStore = PersistStore;