UNPKG

sententiaregum-flux-container

Version:

The flux implementation of the sententiaregum project based on facebook/flux

205 lines (165 loc) 7.43 kB
/* * This file is part of the Sententiaregum project. * * (c) Maximilian Bosch <maximilian.bosch.27@gmail.com> * (c) Ben Bieler <benjaminbieler2014@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _createStoreRefreshStateHandler = require('./util/createStoreRefreshStateHandler'); var _createStoreRefreshStateHandler2 = _interopRequireDefault(_createStoreRefreshStateHandler); var _events = require('events'); var _events2 = _interopRequireDefault(_events); var _connect = require('./util/connect'); var _connect2 = _interopRequireDefault(_connect); var _connector = require('./connector'); var _connector2 = _interopRequireDefault(_connector); var _invariant = require('invariant'); var _invariant2 = _interopRequireDefault(_invariant); var _parseArrayBrackets = require('./util/parseArrayBrackets'); var _parseArrayBrackets2 = _interopRequireDefault(_parseArrayBrackets); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /** * Creates a flux store. * * @param {Object} subscriptions The configured subscriptions. * @param {*} initialState The initial state or callback handler. * * @returns {{getState:Function,getStateValue:Function,getToken:Function}} */ exports.default = function (subscriptions, initialState) { var state = initialState; var emitter = new _events2.default(); var tokens = connectSubscriptions(subscriptions, []); /** * Factory which creates a function that updates state if something changed. * * @returns {Function} The change handler. */ function getStateSaveHandler() { return function (newState, emitter) { // refresh store internals state = newState; tokens = connectSubscriptions(subscriptions, Object.values(tokens)); // emit change emitter.emit('change'); }; } /** * Connects subscriptions. * * @param {Object} subscriptions The subscriptions to connect with the store. * @param {Array} oldTokens The old event tokens. * * @returns {Object.<String>} The processed subscriptions represented as tokens. */ function connectSubscriptions(subscriptions, oldTokens) { return (0, _connect2.default)(Object.keys(subscriptions).reduce(function (config, eventName) { var subscription = subscriptions[eventName]; return Object.assign({}, config, _defineProperty({}, eventName, { function: (0, _createStoreRefreshStateHandler2.default)(getStateSaveHandler(), emitter, subscription, evaluateState(state)), dependencies: typeof subscription.dependencies === 'undefined' ? subscription.dependencies : [] })); }, {}), oldTokens); } /** * Evaluates a property path written as dot notation. * So "foo.bar.baz" will be evaluated as o['foo']['bar']['baz']. * * @param {Array|Object} state The state to evaluate. * @param {String} path The property path. * * @returns {*} The result of the path evaluation. */ function evaluatePropertyPath(state, path) { (0, _invariant2.default)(Array.isArray(state) || (typeof state === 'undefined' ? 'undefined' : _typeof(state)) === 'object', 'To evaluate a property path, the value must be an object or an array!'); return (0, _parseArrayBrackets2.default)(path).split('.').reduce(function (o, i) { if (typeof o === 'undefined' || typeof o[i] === 'undefined') { return; } return o[i]; }, state); } /** * Evaluates the state inline. * The state might be a lazy callback, so it needs to be checked whether this is true or * the state can be returned as-is. * * @param {*} state The state to evaluate. * * @returns {*} The evaluated state. */ function evaluateState(state) { return typeof state === 'function' ? state() : state; } return new (function () { /** * Constructor. * Instantiates the class and registers the store's instance at the store<>view connector. * * @returns {void} */ function _class() { _classCallCheck(this, _class); (0, _connector2.default)(this).register(emitter); } /** * Getter for the store's internal state. * The state built by an internal handler will be stored as local variable in the store's scope. * A function might be returned which will be executed lazily when the state needs to be received. * * @returns {*} */ _createClass(_class, [{ key: 'getState', value: function getState() { return state = evaluateState(state); } /** * In a lot of cases a single item of the state is needed, nothing more. * To fulfill this use-case this provider returns a single value of the state and provides * a default value if the item can't be received. * * @param {String} path The property path. * @param {*} defaultValue The default value. * * @returns {*} The value of the state to be fetched. */ }, { key: 'getStateValue', value: function getStateValue(path) { var defaultValue = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; var search = evaluatePropertyPath(this.getState(), path); if (typeof search === 'undefined') { return defaultValue; } return search; } /** * Provider for a dispatch token. * The store listens to certain actions published by the dispatcher. Every event handler has its own * ID generated by the dispatcher. To declare proper callback dependencies, this token is needed. * * @param {String} eventName The event name to look for. * * @returns {String} */ }, { key: 'getToken', value: function getToken(eventName) { (0, _invariant2.default)(eventName in tokens, 'A handler for event name "' + eventName + '" must be registered in this store!'); return tokens[eventName]; } }]); return _class; }())(); };