UNPKG

state-pool

Version:

Transform your React app with our state management library! Declare global and local states like variables, powered by the magic of React hooks 🪄✨

263 lines (262 loc) • 9.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createStore = void 0; var State_1 = require("./State"); var notImplementedErrorMsg = [ "You must implement 'loadState' and 'saveState' to be able ", 'to save state to your preffered storage. E.g \n', 'store.persist({ \n', ' saveState: function(key, state, isInitialSet){/*Code to save state to your storage*/}, \n', ' loadState: function(key, noState){/*Code to load state from your storage*/} \n', '}) \n' ].join(""); var Empty = /** @class */ (function () { function Empty() { } return Empty; }()); // Class for empty state/value var EMPTY = new Empty(); var PersistentStorage = /** @class */ (function () { function PersistentStorage() { this.SHOULD_PERSIST_BY_DEFAULT = false; } PersistentStorage.prototype.loadState = function (key, noState) { throw TypeError(notImplementedErrorMsg); }; PersistentStorage.prototype.saveState = function (key, state, isInitialSet) { throw TypeError(notImplementedErrorMsg); }; return PersistentStorage; }()); var Store = /** @class */ (function () { function Store(storeInitializer) { this.states = new Map(); this.subscribers = []; this.persistentStorage = new PersistentStorage(); if (storeInitializer) { if (typeof storeInitializer === "function") { storeInitializer = storeInitializer(); } for (var key in storeInitializer) { if (storeInitializer.hasOwnProperty(key)) { this.setState(key, storeInitializer[key]); } } } } Store.prototype.subscribe = function (observer) { var _this = this; if (this.subscribers.indexOf(observer) === -1) { // Subscribe a component to this store this.subscribers.push(observer); } var unsubscribe = function () { _this.subscribers = _this.subscribers.filter(function (subscriber) { return subscriber !== observer; }); }; return unsubscribe; }; Store.prototype.onStoreUpdate = function (key, value) { this.subscribers.forEach(function (subscriber) { subscriber(key, value); }); }; Store.prototype.persist = function (config) { if (config.saveState) { this.persistentStorage.saveState = config.saveState; } if (config.loadState) { this.persistentStorage.loadState = config.loadState; } if (config.removeState) { this.persistentStorage.removeState = config.removeState; } if (config.clear) { this.persistentStorage.clear = config.clear; } if (config.PERSIST_ENTIRE_STORE) { this.persistentStorage.SHOULD_PERSIST_BY_DEFAULT = config.PERSIST_ENTIRE_STORE; } }; Store.prototype.setState = function (key, initialValue, _a) { var _this = this; var _b = _a === void 0 ? {} : _a, persist = _b.persist; var shouldPersist = persist === undefined ? this.persistentStorage.SHOULD_PERSIST_BY_DEFAULT : persist; var shouldSaveToPersistentStorage = false; if (shouldPersist) { // Try to load state from persistent storage var savedState = this.persistentStorage.loadState(key, EMPTY); if (savedState !== EMPTY) { // We have a saved state, so we use it as the initialValue initialValue = savedState; } else { // We don't have a saved state so we have to set/save it // Here we set this flag to true but we'll save later after creating a state successfully shouldSaveToPersistentStorage = true; } } var onStateChange = function (newValue) { // Note key & persist variables depends on scope _this.onStoreUpdate(key, newValue); if (shouldPersist) { _this.persistentStorage.saveState(key, newValue, false); } }; // Create a state var state = (0, State_1.createState)(initialValue); var unsubscribe = state.subscribe({ observer: onStateChange, selector: function (st) { return st; } }); var storeState = { "state": state, "unsubscribe": unsubscribe, "persist": shouldPersist }; // Add state to the store this.states.set(key, storeState); if (shouldSaveToPersistentStorage) { // Saving state to persistent storage after we've created it successfully this.persistentStorage.saveState(key, state.getValue(), true); } }; Store.prototype.getState = function (key, config) { if (config === void 0) { config = {}; } var defaultValue; if (config.hasOwnProperty('default')) { // Use has set default explicitly defaultValue = config.default; } else { // No default value defaultValue = EMPTY; } // Get key based state if (!this.has(key)) { // state is not found if (defaultValue !== EMPTY) { // Default value is found // Create a state and use defaultValue as the initial value this.setState(key, defaultValue, // Make sure we don't pass EMPTY value { persist: config.persist }); } else { // state is not found and the default value is not specified var errorMsg = [ "There is no state with the key '".concat(key, "', "), "You are either trying to access a ", "state that doesn't exist or it was deleted." ]; throw Error(errorMsg.join("")); } } return this.states.get(key).state; }; Store.prototype.has = function (key) { // Check if we have a state in a store return this.states.has(key); }; Store.prototype.items = function () { var storeItems = []; this.states.forEach(function (storeState, key) { storeItems.push([key, storeState.state.getValue(), storeState.persist]); }); return storeItems; }; Store.prototype.getStateValue = function (key, selector) { var state = this.getState(key); return state.getValue(selector); }; Store.prototype.clear = function (fn) { var _this = this; // Copy store var storeCopy = this.states; // Clear store this.states = new Map(); if (this.persistentStorage.clear) { try { this.persistentStorage.clear(); } catch (error) { // Ignore errors in clearing states } } if (fn) { // Run store re-initialization fn(); } storeCopy.forEach(function (oldState, key) { // Unsubscribe from an old state oldState.unsubscribe(); // Notify subscribers to a store that a state has been removed if (_this.has(key)) { var newState = _this.getState(key); _this.onStoreUpdate(key, newState.getValue()); } // Rerender all components using this state oldState.state.refresh(); }); }; Store.prototype.remove = function (Statekey, fn) { var _this = this; var keys = []; if (typeof Statekey === 'string') { keys = [Statekey]; } else { keys = Statekey; } var StatesToRemove = new Map(); keys.forEach(function (key) { // Copy state to remove from a store StatesToRemove.set(key, _this.states.get(key)); // Remove state from a store _this.states.delete(key); if (StatesToRemove.get(key).persist && // Is state persisted _this.persistentStorage.removeState // Is removeState Implemented ) { try { _this.persistentStorage.removeState(key); } catch (error) { // Ignore error in removing state } } }); if (fn) { // Run state re-initialization fn(); } StatesToRemove.forEach(function (oldState, key) { // Unsubscribe from an old state oldState.unsubscribe(); // Notify subscribers to a store that a state has been removed if (_this.has(key)) { var newState = _this.getState(key); _this.onStoreUpdate(key, newState.getValue()); } // Rerender all components depending on this state oldState.state.refresh(); }); }; Store.prototype.useState = function (key, config) { if (config === void 0) { config = {}; } var storeStateConfig = config; var stateConfig = config; var state = this.getState(key, storeStateConfig); return state.useState(stateConfig); }; Store.prototype.useReducer = function (reducer, key, config) { if (config === void 0) { config = {}; } var storeStateConfig = config; var stateConfig = config; var state = this.getState(key, storeStateConfig); return state.useReducer(reducer, stateConfig); }; return Store; }()); exports.default = Store; function createStore(storeInitializer) { // Create a store for key based state return new Store(storeInitializer); } exports.createStore = createStore;