src/ReactObservableStore.js
import Store from './Store';
import ObservableStrategy from './ObservableStrategy';
/**
* Ensure singleton instance
* @type {ReactObservableStore}
*/
let instance = null;
/**
* The global state store
* @return {Object} The global state store
*/
class ReactStore {
/**
* Create React Store
*
* @return {ReactStore} The instance
*/
constructor(strategy) {
/**
* Ensure no other instance than singleton
*
* @type {ReactStore}
*/
if (instance) return instance;
/**
* The store
*
* @type {Store}
*/
this.store = new Store();
/**
* Observable trait
*
* @type {ObservableStrategy}
*/
this.strategy = strategy;
/**
* Set singleton
* @type {ReactStore}
*/
instance = this;
return instance;
}
/**
* Initialize the store
*
* @param {Object} data Initial data
* @param {Boolean} [log=false] Logging flag
*/
init(data, log = false) {
this.store.init(data, log);
for (let namespace in data) this.strategy.init(namespace);
}
/**
* Adds namespace after store has been initailized
*
* @param {String} namespace
* @param {Object} data
*/
add(namespace, data) {
this.store.add(namespace, data);
this.strategy.init(namespace);
}
/**
* Updates the store
*
* @param {String} namespace The namespace to update
* @param {Object} data The data
* @param {Boolean} [merge=true] Update strategy
*/
update(namespace, data, merge = true) {
this.store.update(namespace, data, merge);
this.strategy.update(namespace, data);
}
/**
* Get store value
*
* @param {String} key The key of value to get
* @return {Mixed} The value to return
*/
get(key) {
return this.store.get(key);
}
/**
* Set store value
*
* @param {String} key The key to store the value
* @param {Mixed} value The value to be stored
*/
set(key, value) {
this.store.set(key, value);
const segments = key.split('.');
const namespace = segments[0];
this.strategy.update(namespace, this.store.get(namespace));
}
/**
* Subscribe to namespace
*
* @param {String} namespace The namespace to subscribe
* @param {Function} fn The subscription callback
* @return {String} The observer id
*/
subscribe(namespace, fn) {
return this.strategy.subscribe(namespace, fn);
}
/**
* Unsubscribe to namespace
*
* @param {String} namespace The namespace to unsubscribe to
* @param {String} id The observer id got from subsbribe method
*/
unsubscribe(namespace, id) {
return this.strategy.unsubscribe(namespace, id);
}
/**
* Creates a wrapper around the component that will receive the storage data
*
* @param {String} namespace The namespace to subscribe for updates
* @param {Component} WrappedComponent The new component
* @return {Component} The resulting class
*/
withStore(namespace, WrappedComponent) {
return instance.strategy.register(namespace, instance.store, WrappedComponent);
}
}
/**
* Create singleton
*
* @type {ReactObservableStore}
*/
const ReactObservableStore = new ReactStore(new ObservableStrategy());
// Export public API
export const withStore = ReactObservableStore.withStore;
export default ReactObservableStore;