Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

brownturtle

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

brownturtle - npm Package Compare versions

Comparing version 3.0.1 to 3.2.0

602

lib/index.js
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

@@ -10,571 +8,51 @@

});
exports["default"] = exports.connect = exports.Provider = exports.useMiddleware = exports.useReducer = void 0;
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _react = _interopRequireWildcard(require("react"));
var _redux = require("redux");
var _connect = _interopRequireDefault(require("react-redux/es/connect/connect"));
var _Provider = _interopRequireDefault(require("react-redux/es/components/Provider"));
var _reduxSaga = _interopRequireDefault(require("redux-saga"));
var _effects = require("redux-saga/effects");
var helpers = _interopRequireWildcard(require("./helpers"));
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return (0, _typeof2["default"])(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if ((0, _typeof2["default"])(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if ((0, _typeof2["default"])(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
var combinedInitialState = {};
/* =================================== */
/* STORE
/* =================================== */
var store = {
reducers: {},
sagas: [],
middlewares: [],
create: function create() {
var initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var sagaMiddleware = (0, _reduxSaga["default"])();
var sagaEnhancer = (0, _redux.applyMiddleware)(sagaMiddleware);
var devTools = (0, _redux.compose)(window.devToolsExtension ? window.devToolsExtension() : function (foo) {
return foo;
});
this.middlewares = [].concat((0, _toConsumableArray2["default"])(this.middlewares), [sagaEnhancer, devTools]);
this.storeInstance = (0, _redux.createStore)(this.getRootReducer(initialState), _redux.compose.apply(void 0, (0, _toConsumableArray2["default"])(this.middlewares)));
this.sagas.forEach(function (saga) {
return sagaMiddleware.run(saga);
});
return this.storeInstance;
},
getRootReducer: function getRootReducer() {
var _this = this;
var initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var reducers = _objectSpread({}, this.reducers);
if (Object.keys(reducers).length === 0 || process.env.NODE_ENV === 'test') {
reducers.$_foo = function () {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return state;
}; // default reducer
}
var rootReducer = (0, _redux.combineReducers)(reducers);
return function () {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState;
var action = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
// start updating the state
_this.$updatingState = true; // clear getState calls queue
_this.getStateCallbacks = []; // get the new state object
var newState = rootReducer(state, action); // invoke each getState call in the queue with the new state
_this.$updatingState = false;
while (_this.getStateCallbacks.length) {
_this.getStateCallbacks.shift()(newState);
} // return the new state
return newState;
};
},
getState: function getState(query) {
var _this2 = this;
if (this.$updatingState === false) {
return Promise.resolve(this.queryState(query, this.storeInstance.getState()));
}
return new Promise(function (resolve) {
_this2.getStateCallbacks.push(function (state) {
resolve(_this2.queryState(query, state));
});
});
},
queryState: function queryState(query, state) {
// handle query strings
if (helpers.getObjectType(query) === 'string') {
return helpers.findPropInObject(state, query);
} // handle query objects
if (helpers.getObjectType(query) === 'object') {
return Object.keys(query).reduce(function (prev, next) {
return _objectSpread({}, prev, (0, _defineProperty2["default"])({}, next, helpers.findPropInObject(state, query[next])));
}, {});
}
return state;
Object.defineProperty(exports, "Provider", {
enumerable: true,
get: function get() {
return _reactRedux.Provider;
}
};
});
exports.createStore = void 0;
var useReducer = function useReducer(name, reducer) {
store.reducers[name] = reducer;
};
var _store = _interopRequireDefault(require("./store"));
exports.useReducer = useReducer;
var _reactRedux = require("react-redux");
var useMiddleware = function useMiddleware(middleware) {
store.middlewares.unshift((0, _redux.applyMiddleware)(middleware));
};
/* =================================== */
/**
* Dependency imports.
*/
// import React from 'react';
// import { Provider as ReduxProvider } from 'react-redux';
// import { applyMiddleware } from 'redux';
/* PROVIDER
/* =================================== */
/**
* Local imports.
*/
// import { combinedInitialState } from './connect';
/**
* Re-exports.
*/
// export { default as connect } from './connect';
exports.useMiddleware = useMiddleware;
/**
* Adds a reducer function to be used by the root reducer.
* @param {String} key Reducer unique identifier key
* @param {Function} reducer Reducer function.
*/
// export const useReducer = (name, reducer) => {
// store.reducers[name] = reducer;
// };
var Provider = function Provider(props) {
return _react["default"].createElement(_Provider["default"], (0, _extends2["default"])({
store: store.create(combinedInitialState)
}, props));
/**
* Allows registering middleware functions such as Router and other middlewares.
* @param {Function} middleWare Middleware function to use
*/
// export const useMiddleware = (middleware) => {
// store.middlewares.unshift(applyMiddleware(middleware));
// };
var createStore = function createStore() {
return _store["default"].create({});
};
/* =================================== */
/* MODULE
/* =================================== */
exports.Provider = Provider;
var Module = function Module(config) {
var _this3 = this;
(0, _classCallCheck2["default"])(this, Module);
(0, _defineProperty2["default"])(this, "build", function () {
/* build action creators ---------- */
Object.entries(_this3.config.actions || {}).forEach(function (_ref) {
var _ref2 = (0, _slicedToArray2["default"])(_ref, 2),
name = _ref2[0],
callback = _ref2[1];
var camelCaseName = helpers.toCamelCase(name);
var actionName = helpers.toSnakeCase(camelCaseName).toUpperCase();
var actionType = "@@".concat(_this3.name, "/").concat(actionName);
var argNames = helpers.getArgNames(callback);
_this3.actionCreators[camelCaseName] = function () {
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
// build the payload object
var payload = argNames.reduce(function (prev, next, index) {
return _objectSpread({}, prev, (0, _defineProperty2["default"])({}, next, args[index]));
}, {}); // then use it to build the action object
var actionObject = {
type: actionType,
payload: payload
};
return actionObject;
};
_this3.actionToReducerMap[actionType] = _this3.createSubReducer(actionType, callback, argNames, 'create');
_this3.sagas[actionType] = _this3.createSaga(actionType);
});
/* build handlers ----------------- */
Object.entries(_this3.config.handlers || {}).forEach(function (_ref3) {
var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2),
name = _ref4[0],
callback = _ref4[1];
var actionType = name;
if (/^(.*?)\.(.*?)$/.test(actionType)) {
var _actionType$split = actionType.split('.'),
_actionType$split2 = (0, _slicedToArray2["default"])(_actionType$split, 2),
moduleName = _actionType$split2[0],
camelCaseName = _actionType$split2[1];
var actionName = helpers.toSnakeCase(camelCaseName).toUpperCase();
actionType = "@@".concat(moduleName, "/").concat(actionName);
}
var argNames = helpers.getArgNames(callback);
_this3.actionToReducerMap[actionType] = _this3.createSubReducer(actionType, callback, argNames, 'handle');
_this3.sagas[actionType] = _this3.createSaga(actionType);
});
/* build reducer ------------------ */
_this3.reducer = function () {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var action = arguments.length > 1 ? arguments[1] : undefined;
// the action type might be in normal form, such as: '@@prefix/ACTION_NAME'
// or it may contain a sub action type: '@@prefix/ACTION_NAME/SUB_ACTION_NAME'
var actionType = action.type;
var mainActionType = (actionType.match(/@@(.*?)\/((.*?)(?=\/)|(.*?)$)/) || [])[0] || actionType;
var subActionType = actionType.replace(mainActionType, '').slice(1);
var actionName = mainActionType.replace(/^@@(.*?)\//, '');
var newState = state; // if the sub action is 'update', just update the state with the payload object
if (mainActionType === "@@".concat(_this3.name, "/").concat(actionName) && subActionType === 'UPDATE') {
newState = helpers.mergeObjects(state, action.payload || {});
} // if it's a main action, look for a sub reducer that can handle this action
_this3.getActionTypeMatchers(actionType).forEach(function (matcher) {
if (_this3.actionToReducerMap[matcher]) {
newState = _this3.actionToReducerMap[matcher](newState, action);
}
});
return newState;
};
/* map state to props ------------- */
_this3.mapStateToProps = function (state) {
var _ref5;
var _this3$name = _this3.name,
ownState = state[_this3$name],
globalState = (0, _objectWithoutProperties2["default"])(state, [_this3$name].map(_toPropertyKey));
return _ref5 = {}, (0, _defineProperty2["default"])(_ref5, _this3.stateKey, ownState), (0, _defineProperty2["default"])(_ref5, _this3.globalStateKey, globalState), _ref5;
};
/* map dispatch to props ---------- */
_this3.mapDispatchToProps = function (dispatch) {
return (0, _redux.bindActionCreators)(_this3.actionCreators, dispatch);
};
/* combine props ------------------ */
_this3.combineProps = function (stateProps, dispatchProps, ownProps) {
return _objectSpread({}, ownProps, {}, stateProps, (0, _defineProperty2["default"])({}, _this3.actionsKey, _objectSpread({}, dispatchProps)));
};
});
(0, _defineProperty2["default"])(this, "createSubReducer", function (actionType, callback, argNames, mode) {
return function () {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var action = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var matchers = _this3.getActionTypeMatchers(action.type);
if (matchers.includes(actionType)) {
var callbackResult = _this3.executeCallback(callback, action, argNames, mode);
var callbackResultType = helpers.getObjectType(callbackResult);
var stateFragment = callbackResultType === 'object' ? callbackResult : {}; // the saga handler will be called right after the reducer so instead of the saga
// handler executing the callback again, pass it the cached result
_this3.cachedCallbackResult = _this3.cachedCallbackResult || {};
_this3.cachedCallbackResult[action.type] = callbackResult;
return helpers.mergeObjects(state, stateFragment);
}
return state;
};
});
(0, _defineProperty2["default"])(this, "createSaga", function (actionType) {
return (
/*#__PURE__*/
_regenerator["default"].mark(function saga() {
return _regenerator["default"].wrap(function saga$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
this.workerSagas[actionType] =
/*#__PURE__*/
_regenerator["default"].mark(function workerSaga() {
var result, data, isDone, breakAfter, _loop;
return _regenerator["default"].wrap(function workerSaga$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
result = this.cachedCallbackResult && this.cachedCallbackResult[actionType]; // check if the callback return value is an iterable (usually a generator function)
// if it is an iterable then consume it
if (!(result && typeof result[Symbol.iterator] === 'function')) {
_context2.next = 19;
break;
}
_context2.prev = 2;
// `data` will be assigned to each `next()` call
// `isDone` will be true when `next()` returns done as true
isDone = false; // the while loop will break after a maximum of 50 calls
breakAfter = 50;
_loop =
/*#__PURE__*/
_regenerator["default"].mark(function _loop() {
var next, nextResult;
return _regenerator["default"].wrap(function _loop$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
next = result.next(data);
nextResult = next.value;
isDone = next.done; // if the yielded value is a Promise, resolve it then continue
if (!(nextResult instanceof Promise)) {
_context.next = 9;
break;
}
_context.next = 6;
return (0, _effects.call)(function () {
return nextResult;
});
case 6:
data = _context.sent;
_context.next = 12;
break;
case 9:
if (!(helpers.getObjectType(nextResult) === 'object')) {
_context.next = 12;
break;
}
_context.next = 12;
return (0, _effects.put)({
type: "".concat(actionType, "/UPDATE"),
payload: nextResult
});
case 12:
breakAfter -= 1; // safety break
if (!(breakAfter === 0)) {
_context.next = 15;
break;
}
throw new Error('An async action handler yielded more than 50 values.');
case 15:
case "end":
return _context.stop();
}
}
}, _loop);
});
case 6:
if (isDone) {
_context2.next = 10;
break;
}
return _context2.delegateYield(_loop(), "t0", 8);
case 8:
_context2.next = 6;
break;
case 10:
_context2.next = 12;
return (0, _effects.put)({
type: "".concat(actionType, "/COMPLETE")
});
case 12:
_context2.next = 19;
break;
case 14:
_context2.prev = 14;
_context2.t1 = _context2["catch"](2);
window.console.error(_context2.t1);
_context2.next = 19;
return (0, _effects.put)({
type: "".concat(actionType, "/ERROR"),
message: _context2.t1.message
});
case 19:
case "end":
return _context2.stop();
}
}
}, workerSaga, this, [[2, 14]]);
}).bind(this);
_context3.next = 3;
return (0, _effects.takeLatest)(actionType, this.workerSagas[actionType]);
case 3:
case "end":
return _context3.stop();
}
}
}, saga, this);
}).bind(_this3)
);
});
(0, _defineProperty2["default"])(this, "executeCallback", function (callback, action, argNames, mode) {
var callbackArgs = mode === 'create' ? argNames.map(function (arg) {
return action.payload[arg];
}) : [action];
return callback.apply(_this3.getCallbackContext(), callbackArgs);
});
(0, _defineProperty2["default"])(this, "getCallbackContext", function () {
var self = _this3;
return _objectSpread({}, self.config.actions, {
getState: self.getState,
get state() {
return self.getState();
}
});
});
(0, _defineProperty2["default"])(this, "getState", function _callee(query) {
var state;
return _regenerator["default"].async(function _callee$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_context4.next = 2;
return _regenerator["default"].awrap(store.getState());
case 2:
_context4.t0 = _this3.name;
state = _context4.sent[_context4.t0];
if (!(helpers.getObjectType(query) === 'string')) {
_context4.next = 6;
break;
}
return _context4.abrupt("return", helpers.findPropInObject(state, query));
case 6:
if (!(helpers.getObjectType(query) === 'object')) {
_context4.next = 8;
break;
}
return _context4.abrupt("return", Object.keys(query).reduce(function (prev, next) {
return _objectSpread({}, prev, (0, _defineProperty2["default"])({}, next, helpers.findPropInObject(state, query[next])));
}, {}));
case 8:
return _context4.abrupt("return", state);
case 9:
case "end":
return _context4.stop();
}
}
});
});
(0, _defineProperty2["default"])(this, "getActionTypeMatchers", function (actionType) {
var regex = /@@(.+?)\/(.+)/;
var moduleName = '';
var actionName = actionType;
if (regex.test(actionType)) {
var _actionType$match = actionType.match(regex);
var _actionType$match2 = (0, _slicedToArray2["default"])(_actionType$match, 3);
moduleName = _actionType$match2[1];
actionName = _actionType$match2[2];
}
return [actionType, // exact action
"@@".concat(moduleName), // any action by the module
"@@".concat(moduleName, "/"), // any action by the module (alias)
"@@".concat(moduleName, "/*"), // any action by the module (alias)
"@@*/".concat(actionName), // same action dispatched by any module
"*/".concat(actionName), // same action dispatched by any module (alias)
'*' // any action
];
});
this.config = config;
this.name = config.name;
this.stateKey = config.stateKey || 'state';
this.actionsKey = config.actionsKey || 'actions';
this.globalStateKey = config.globalStateKey || 'globalState';
this.actionCreators = {};
this.actionToReducerMap = {};
this.sagas = {};
this.workerSagas = {};
this.reducer = function (state) {
return state;
};
this.build();
};
/* =================================== */
/* CONNECT
/* =================================== */
var connect = function connect(component) {
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (typeof component !== 'function' && Object.getPrototypeOf(component) !== _react.Component) {
throw new Error('Expected the first parameter to be a pure function or a valid React component class.');
}
if (helpers.getObjectType(config) !== 'object') {
throw new Error('Module configuration must be an object');
}
var moduleConfig = _objectSpread({}, config);
if (!moduleConfig.name) {
moduleConfig.name = helpers.getComponentName(component);
}
if (typeof connect.moduleNames === 'undefined') {
connect.moduleNames = {};
}
if (connect.moduleNames[moduleConfig.name] === true) {
throw new Error("Name '".concat(moduleConfig.name, "' has already been used by another module, please use a different name"));
} else {
connect.moduleNames[moduleConfig.name] = true;
}
var module = new Module(moduleConfig);
combinedInitialState[module.name] = moduleConfig.initialState || moduleConfig.state || {};
store.reducers[module.name] = module.reducer;
var connectedComponent = (0, _connect["default"])(module.mapStateToProps, module.mapDispatchToProps, module.combineProps)(component);
store.sagas = [].concat((0, _toConsumableArray2["default"])(store.sagas), (0, _toConsumableArray2["default"])(Object.values(module.sagas)));
return connectedComponent;
};
exports.connect = connect;
var _default = {};
exports["default"] = _default;
exports.createStore = createStore;

178

lib/store.js
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {

@@ -8,25 +12,173 @@ value: true

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _redux = require("redux");
var _reduxSaga = _interopRequireDefault(require("redux-saga"));
var helpers = _interopRequireWildcard(require("./helpers"));
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
/**
* Dependency imports.
* Creates the saga middleware function.
* @type {Function}
*/
var getRootReducer = function getRootReducer(initialState) {
return function () {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState;
var action = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var sagaMiddleware = (0, _reduxSaga["default"])();
/**
* Creates the saga store enhancer.
* @type {Function}
*/
if (action) {
console.log(action);
var sagaEnhancer = (0, _redux.applyMiddleware)(sagaMiddleware);
/**
* Creates a middleware function that is used to enable Redux devTools.
* in the browser.
* @type {Function}
*/
var devTools = (0, _redux.compose)(window.devToolsExtension ? window.devToolsExtension() : function (foo) {
return foo;
});
/**
* This is not the actual store object. This is a wrapper object
* that manages the Redux store instance. Use `store.getInstance()`
* to get a reference to the Redux store.
*/
var store = {
/**
* An object that is used as a map to store references to registered
* reducers. This object is used by `getRootReducer()` to create the
* root reducer for the store.
* @type {Object}
*/
reducers: {},
sagas: [],
/**
* An array of middlewares to use when creating the store.
* Use exported method `useMiddleware()` to add other middleware
* functions to this list.
* @type {Array}
*/
middlewares: [sagaEnhancer, devTools],
/**
* Creates a new Redux store instance and updates the reference.
*/
create: function create() {
var initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
if (this.storeInstance) return this.storeInstance;
this.storeInstance = (0, _redux.createStore)(this.getRootReducer(initialState), _redux.compose.apply(void 0, (0, _toConsumableArray2["default"])(this.middlewares)));
this.sagas.forEach(function (saga) {
return sagaMiddleware.run(saga);
});
return this.storeInstance;
},
/**
* Combines all registered reducers and returns a single reducer function.
* @param {Object} initialState The initial state for the app
*/
getRootReducer: function getRootReducer() {
var _this = this;
var initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var reducers = _objectSpread({}, this.reducers);
if (Object.keys(reducers).length === 0 || process.env.NODE_ENV === 'test') {
reducers.$_foo = function () {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return state;
}; // default reducer
}
var rootReducer = (0, _redux.combineReducers)(reducers);
return function () {
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState;
var action = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
// start updating the state
_this.$updatingState = true; // clear getState calls queue
_this.getStateCallbacks = []; // get the new state object
var newState = rootReducer(state, action); // invoke each getState call in the queue with the new state
_this.$updatingState = false;
while (_this.getStateCallbacks.length) {
_this.getStateCallbacks.shift()(newState);
} // return the new state
return newState;
};
},
/**
* Returns the complete state object or part of it based on a given query. If the
* query parameter is a string that uses dot notation, it will return the resolved
* value of the given key. If the query is an object, it will return an object that
* has the same structure but contains the resolved values. If the query parameter
* is not provided, the complete state object will be returned.
* @param {String|Object} query A query string or a query object that represents
* part of the state object that needs to be fetched.
* This parameter is not required.
* @return {Promise} A promise that eventually resolves with the state
* object, part of it or a value in the state object.
*/
getState: function getState(query) {
var _this2 = this;
if (this.$updatingState === false) {
return Promise.resolve(this.getStateSync(query));
}
return new Promise(function (resolve) {
_this2.getStateCallbacks.push(function (state) {
resolve(_this2.queryState(query, state));
});
});
},
getStateSync: function getStateSync(query) {
return this.queryState(query, this.storeInstance.getState());
},
/**
* Queries a state object for a specific value.
* @param {String} query Query string.
* @param {Object} state State object to query.
* @return {Object} The state object, part of it or a value in the state object.
*/
queryState: function queryState(query, state) {
// handle query strings
if (helpers.getObjectType(query) === 'string') {
return helpers.findPropInObject(state, query);
} // handle query objects
if (helpers.getObjectType(query) === 'object') {
return Object.keys(query).reduce(function (prev, next) {
return _objectSpread({}, prev, (0, _defineProperty2["default"])({}, next, helpers.findPropInObject(state, query[next])));
}, {});
}
return state;
};
};
},
var _default = function _default() {
var initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return (0, _redux.createStore)(getRootReducer(initialState));
/**
* Returns an reference to the Redux store instance.
*/
getInstance: function getInstance() {
return this.storeInstance;
}
};
var _default = store;
exports["default"] = _default;
{
"name": "brownturtle",
"version": "3.0.1",
"description": "An opinionated state management library based on Redux.",
"version": "3.2.0",
"description": "",
"main": "lib/index.js",

@@ -16,9 +16,7 @@ "scripts": {

"posttest": "npm run lint",
"prepublishOnly": "npm test && npm run build",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
"prepublishOnly": "npm test && npm run build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/teefouad/brownturtle.git"
"url": "git+https://github.com/teefouad/speedux.git"
},

@@ -30,18 +28,8 @@ "files": [

],
"keywords": [
"react",
"reactjs",
"flux",
"redux",
"action",
"reducer",
"javascript",
"nodejs"
],
"author": "Mostafa <tee.fouad@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/teefouad/brownturtle/issues"
"url": "https://github.com/teefouad/speedux/issues"
},
"homepage": "https://github.com/teefouad/brownturtle#readme",
"homepage": "https://github.com/teefouad/speedux#readme",
"devDependencies": {

@@ -53,12 +41,4 @@ "@babel/cli": "^7.2.3",

"@babel/preset-env": "^7.3.4",
"@babel/preset-react": "^7.7.0",
"@storybook/addon-actions": "^5.2.6",
"@storybook/addon-links": "^5.2.6",
"@storybook/addons": "^5.2.6",
"@storybook/cli": "^5.2.6",
"@storybook/react": "^5.2.6",
"@types/node": "^12.12.7",
"babel-eslint": "^10.0.1",
"babel-jest": "^24.4.0",
"babel-loader": "^8.0.6",
"coveralls": "^3.0.3",

@@ -72,12 +52,13 @@ "cross-env": "^5.2.0",

"jest": "^24.4.0",
"uglifyjs-webpack-plugin": "^2.2.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.1.3",
"redux": "^4.0.4",
"redux-saga": "^1.1.3",
"webpack": "^4.29.6",
"webpack-cli": "^3.2.3"
},
"dependencies": {
"react": "^16.11.0",
"react-redux": "^7.1.3",
"redux": "^4.0.4",
"redux-saga": "^1.1.3"
"peerDependencies": {
"react": "^16.8.3"
}
}
# speedux
An opinionated state management library based on Redux.
[![Version](https://img.shields.io/npm/v/speedux.svg?style=flat-square)](https://www.npmjs.com/package/speedux)

@@ -5,0 +5,0 @@ [![License](https://img.shields.io/npm/l/speedux.svg?style=flat-square)](https://www.npmjs.com/package/speedux)

@@ -1,416 +0,37 @@

import React, { Component } from 'react';
import {
createStore as createReduxStore,
bindActionCreators,
applyMiddleware,
compose,
combineReducers,
} from 'redux';
import reduxConnect from 'react-redux/es/connect/connect';
import ReduxProvider from 'react-redux/es/components/Provider';
import createSagaMiddleware from 'redux-saga';
import {
takeLatest,
put,
call,
} from 'redux-saga/effects';
import * as helpers from './helpers';
/**
* Dependency imports.
*/
// import React from 'react';
// import { Provider as ReduxProvider } from 'react-redux';
// import { applyMiddleware } from 'redux';
const combinedInitialState = {};
/**
* Local imports.
*/
import store from './store';
// import { combinedInitialState } from './connect';
/* =================================== */
/* STORE
/* =================================== */
/**
* Re-exports.
*/
export { Provider } from 'react-redux';
// export { default as connect } from './connect';
const store = {
reducers: {},
sagas: [],
middlewares: [],
/**
* Adds a reducer function to be used by the root reducer.
* @param {String} key Reducer unique identifier key
* @param {Function} reducer Reducer function.
*/
// export const useReducer = (name, reducer) => {
// store.reducers[name] = reducer;
// };
create(initialState = {}) {
const sagaMiddleware = createSagaMiddleware();
const sagaEnhancer = applyMiddleware(sagaMiddleware);
const devTools = compose(window.devToolsExtension ? window.devToolsExtension() : foo => foo);
/**
* Allows registering middleware functions such as Router and other middlewares.
* @param {Function} middleWare Middleware function to use
*/
// export const useMiddleware = (middleware) => {
// store.middlewares.unshift(applyMiddleware(middleware));
// };
this.middlewares = [...this.middlewares, sagaEnhancer, devTools];
this.storeInstance = createReduxStore(
this.getRootReducer(initialState),
compose(...this.middlewares),
);
this.sagas.forEach(saga => sagaMiddleware.run(saga));
return this.storeInstance;
},
getRootReducer(initialState = {}) {
const reducers = { ...this.reducers };
if (Object.keys(reducers).length === 0 || process.env.NODE_ENV === 'test') {
reducers.$_foo = (state = {}) => state; // default reducer
}
const rootReducer = combineReducers(reducers);
return (state = initialState, action = null) => {
// start updating the state
this.$updatingState = true;
// clear getState calls queue
this.getStateCallbacks = [];
// get the new state object
const newState = rootReducer(state, action);
// invoke each getState call in the queue with the new state
this.$updatingState = false;
while (this.getStateCallbacks.length) this.getStateCallbacks.shift()(newState);
// return the new state
return newState;
};
},
getState(query) {
if (this.$updatingState === false) {
return Promise.resolve(this.queryState(query, this.storeInstance.getState()));
}
return new Promise((resolve) => {
this.getStateCallbacks.push((state) => {
resolve(this.queryState(query, state));
});
});
},
queryState(query, state) {
// handle query strings
if (helpers.getObjectType(query) === 'string') {
return helpers.findPropInObject(state, query);
}
// handle query objects
if (helpers.getObjectType(query) === 'object') {
return Object.keys(query).reduce((prev, next) => ({
...prev,
[next]: helpers.findPropInObject(state, query[next]),
}), {});
}
return state;
},
};
export const useReducer = (name, reducer) => {
store.reducers[name] = reducer;
};
export const useMiddleware = (middleware) => {
store.middlewares.unshift(applyMiddleware(middleware));
};
/* =================================== */
/* PROVIDER
/* =================================== */
export const Provider = props => (
<ReduxProvider
store={store.create(combinedInitialState)}
{...props}
/>
);
/* =================================== */
/* MODULE
/* =================================== */
class Module {
constructor(config) {
this.config = config;
this.name = config.name;
this.stateKey = config.stateKey || 'state';
this.actionsKey = config.actionsKey || 'actions';
this.globalStateKey = config.globalStateKey || 'globalState';
this.actionCreators = {};
this.actionToReducerMap = {};
this.sagas = {};
this.workerSagas = {};
this.reducer = state => state;
this.build();
}
build = () => {
/* build action creators ---------- */
Object.entries(this.config.actions || {}).forEach(([name, callback]) => {
const camelCaseName = helpers.toCamelCase(name);
const actionName = helpers.toSnakeCase(camelCaseName).toUpperCase();
const actionType = `@@${this.name}/${actionName}`;
const argNames = helpers.getArgNames(callback);
this.actionCreators[camelCaseName] = (...args) => {
// build the payload object
const payload = argNames.reduce((prev, next, index) => ({
...prev,
[next]: args[index],
}), {});
// then use it to build the action object
const actionObject = {
type: actionType,
payload,
};
return actionObject;
};
this.actionToReducerMap[actionType] = this.createSubReducer(actionType, callback, argNames, 'create');
this.sagas[actionType] = this.createSaga(actionType);
});
/* build handlers ----------------- */
Object.entries(this.config.handlers || {}).forEach(([name, callback]) => {
let actionType = name;
if (/^(.*?)\.(.*?)$/.test(actionType)) {
const [moduleName, camelCaseName] = actionType.split('.');
const actionName = helpers.toSnakeCase(camelCaseName).toUpperCase();
actionType = `@@${moduleName}/${actionName}`;
}
const argNames = helpers.getArgNames(callback);
this.actionToReducerMap[actionType] = this.createSubReducer(actionType, callback, argNames, 'handle');
this.sagas[actionType] = this.createSaga(actionType);
});
/* build reducer ------------------ */
this.reducer = (state = {}, action) => {
// the action type might be in normal form, such as: '@@prefix/ACTION_NAME'
// or it may contain a sub action type: '@@prefix/ACTION_NAME/SUB_ACTION_NAME'
const actionType = action.type;
const mainActionType = (actionType.match(/@@(.*?)\/((.*?)(?=\/)|(.*?)$)/) || [])[0] || actionType;
const subActionType = actionType.replace(mainActionType, '').slice(1);
const actionName = mainActionType.replace(/^@@(.*?)\//, '');
let newState = state;
// if the sub action is 'update', just update the state with the payload object
if (mainActionType === `@@${this.name}/${actionName}` && subActionType === 'UPDATE') {
newState = helpers.mergeObjects(state, action.payload || {});
}
// if it's a main action, look for a sub reducer that can handle this action
this.getActionTypeMatchers(actionType).forEach((matcher) => {
if (this.actionToReducerMap[matcher]) {
newState = this.actionToReducerMap[matcher](newState, action);
}
});
return newState;
};
/* map state to props ------------- */
this.mapStateToProps = (state) => {
const { [this.name]: ownState, ...globalState } = state;
return {
[this.stateKey]: ownState,
[this.globalStateKey]: globalState,
};
};
/* map dispatch to props ---------- */
this.mapDispatchToProps = dispatch => bindActionCreators(this.actionCreators, dispatch);
/* combine props ------------------ */
this.combineProps = (stateProps, dispatchProps, ownProps) => ({
...ownProps,
...stateProps,
[this.actionsKey]: { ...dispatchProps },
});
}
createSubReducer = (actionType, callback, argNames, mode) => (state = {}, action = null) => {
const matchers = this.getActionTypeMatchers(action.type);
if (matchers.includes(actionType)) {
const callbackResult = this.executeCallback(callback, action, argNames, mode);
const callbackResultType = helpers.getObjectType(callbackResult);
const stateFragment = (callbackResultType === 'object' ? callbackResult : {});
// the saga handler will be called right after the reducer so instead of the saga
// handler executing the callback again, pass it the cached result
this.cachedCallbackResult = this.cachedCallbackResult || {};
this.cachedCallbackResult[action.type] = callbackResult;
return helpers.mergeObjects(state, stateFragment);
}
return state;
};
createSaga = actionType => function* saga() {
this.workerSagas[actionType] = function* workerSaga() {
const result = this.cachedCallbackResult && this.cachedCallbackResult[actionType];
// check if the callback return value is an iterable (usually a generator function)
// if it is an iterable then consume it
if (result && typeof result[Symbol.iterator] === 'function') {
try {
// `data` will be assigned to each `next()` call
let data;
// `isDone` will be true when `next()` returns done as true
let isDone = false;
// the while loop will break after a maximum of 50 calls
let breakAfter = 50;
while (!isDone) {
const next = result.next(data);
const nextResult = next.value;
isDone = next.done;
// if the yielded value is a Promise, resolve it then continue
if (nextResult instanceof Promise) {
data = yield call(() => nextResult);
} else
// if the yielded value is an object, use it to update the state
if (helpers.getObjectType(nextResult) === 'object') {
yield put({
type: `${actionType}/UPDATE`,
payload: nextResult,
});
}
breakAfter -= 1;
// safety break
if (breakAfter === 0) {
throw new Error('An async action handler yielded more than 50 values.');
}
}
// indicate that the async action has completed by dispatching
// a COMPLETE sub action
yield put({
type: `${actionType}/COMPLETE`,
});
} catch (e) {
window.console.error(e);
yield put({
type: `${actionType}/ERROR`,
message: e.message,
});
}
}
}.bind(this);
yield takeLatest(actionType, this.workerSagas[actionType]);
}.bind(this);
executeCallback = (callback, action, argNames, mode) => {
const callbackArgs = mode === 'create' ? argNames.map(arg => action.payload[arg]) : [action];
return callback.apply(this.getCallbackContext(), callbackArgs);
}
getCallbackContext = () => {
const self = this;
return {
...self.config.actions,
getState: self.getState,
get state() { return self.getState(); },
};
}
getState = async (query) => {
const state = (await store.getState())[this.name];
// handle query strings
if (helpers.getObjectType(query) === 'string') {
return helpers.findPropInObject(state, query);
}
// handle query objects
if (helpers.getObjectType(query) === 'object') {
return Object.keys(query).reduce((prev, next) => ({
...prev,
[next]: helpers.findPropInObject(state, query[next]),
}), {});
}
return state;
}
getActionTypeMatchers = (actionType) => {
const regex = /@@(.+?)\/(.+)/;
let moduleName = '';
let actionName = actionType;
if (regex.test(actionType)) {
[, moduleName, actionName] = actionType.match(regex);
}
return [
actionType, // exact action
`@@${moduleName}`, // any action by the module
`@@${moduleName}/`, // any action by the module (alias)
`@@${moduleName}/*`, // any action by the module (alias)
`@@*/${actionName}`, // same action dispatched by any module
`*/${actionName}`, // same action dispatched by any module (alias)
'*', // any action
];
}
}
/* =================================== */
/* CONNECT
/* =================================== */
export const connect = (component, config = {}) => {
if (typeof component !== 'function' && Object.getPrototypeOf(component) !== Component) {
throw new Error('Expected the first parameter to be a pure function or a valid React component class.');
}
if (helpers.getObjectType(config) !== 'object') {
throw new Error('Module configuration must be an object');
}
const moduleConfig = { ...config };
if (!moduleConfig.name) {
moduleConfig.name = helpers.getComponentName(component);
}
if (typeof connect.moduleNames === 'undefined') {
connect.moduleNames = {};
}
if (connect.moduleNames[moduleConfig.name] === true) {
throw new Error(`Name '${moduleConfig.name}' has already been used by another module, please use a different name`);
} else {
connect.moduleNames[moduleConfig.name] = true;
}
const module = new Module(moduleConfig);
combinedInitialState[module.name] = moduleConfig.initialState || moduleConfig.state || {};
store.reducers[module.name] = module.reducer;
const connectedComponent = reduxConnect(
module.mapStateToProps,
module.mapDispatchToProps,
module.combineProps,
)(component);
store.sagas = [
...store.sagas,
...Object.values(module.sagas),
];
return connectedComponent;
};
export default {};
export const createStore = () => store.create({});

@@ -6,15 +6,164 @@ /**

createStore as createReduxStore,
// combineReducers,
// applyMiddleware,
// compose,
applyMiddleware,
compose,
combineReducers,
} from 'redux';
import createSagaMiddleware from 'redux-saga';
const getRootReducer = initialState => (state = initialState, action = null) => {
if (action) {
console.log(action);
}
/**
* Local imports.
*/
import * as helpers from './helpers';
return state;
/**
* Creates the saga middleware function.
* @type {Function}
*/
const sagaMiddleware = createSagaMiddleware();
/**
* Creates the saga store enhancer.
* @type {Function}
*/
const sagaEnhancer = applyMiddleware(sagaMiddleware);
/**
* Creates a middleware function that is used to enable Redux devTools.
* in the browser.
* @type {Function}
*/
const devTools = compose(window.devToolsExtension ? window.devToolsExtension() : foo => foo);
/**
* This is not the actual store object. This is a wrapper object
* that manages the Redux store instance. Use `store.getInstance()`
* to get a reference to the Redux store.
*/
const store = {
/**
* An object that is used as a map to store references to registered
* reducers. This object is used by `getRootReducer()` to create the
* root reducer for the store.
* @type {Object}
*/
reducers: {},
sagas: [],
/**
* An array of middlewares to use when creating the store.
* Use exported method `useMiddleware()` to add other middleware
* functions to this list.
* @type {Array}
*/
middlewares: [sagaEnhancer, devTools],
/**
* Creates a new Redux store instance and updates the reference.
*/
create(initialState = {}) {
if (this.storeInstance) return this.storeInstance;
this.storeInstance = createReduxStore(
this.getRootReducer(initialState),
compose(...this.middlewares),
);
this.sagas.forEach(saga => sagaMiddleware.run(saga));
return this.storeInstance;
},
/**
* Combines all registered reducers and returns a single reducer function.
* @param {Object} initialState The initial state for the app
*/
getRootReducer(initialState = {}) {
const reducers = { ...this.reducers };
if (Object.keys(reducers).length === 0 || process.env.NODE_ENV === 'test') {
reducers.$_foo = (state = {}) => state; // default reducer
}
const rootReducer = combineReducers(reducers);
return (state = initialState, action = null) => {
// start updating the state
this.$updatingState = true;
// clear getState calls queue
this.getStateCallbacks = [];
// get the new state object
const newState = rootReducer(state, action);
// invoke each getState call in the queue with the new state
this.$updatingState = false;
while (this.getStateCallbacks.length) this.getStateCallbacks.shift()(newState);
// return the new state
return newState;
};
},
/**
* Returns the complete state object or part of it based on a given query. If the
* query parameter is a string that uses dot notation, it will return the resolved
* value of the given key. If the query is an object, it will return an object that
* has the same structure but contains the resolved values. If the query parameter
* is not provided, the complete state object will be returned.
* @param {String|Object} query A query string or a query object that represents
* part of the state object that needs to be fetched.
* This parameter is not required.
* @return {Promise} A promise that eventually resolves with the state
* object, part of it or a value in the state object.
*/
getState(query) {
if (this.$updatingState === false) {
return Promise.resolve(this.getStateSync(query));
}
return new Promise((resolve) => {
this.getStateCallbacks.push((state) => {
resolve(this.queryState(query, state));
});
});
},
getStateSync(query) {
return this.queryState(query, this.storeInstance.getState());
},
/**
* Queries a state object for a specific value.
* @param {String} query Query string.
* @param {Object} state State object to query.
* @return {Object} The state object, part of it or a value in the state object.
*/
queryState(query, state) {
// handle query strings
if (helpers.getObjectType(query) === 'string') {
return helpers.findPropInObject(state, query);
}
// handle query objects
if (helpers.getObjectType(query) === 'object') {
return Object.keys(query).reduce((prev, next) => ({
...prev,
[next]: helpers.findPropInObject(state, query[next]),
}), {});
}
return state;
},
/**
* Returns an reference to the Redux store instance.
*/
getInstance() {
return this.storeInstance;
},
};
export default (initialState = {}) => createReduxStore(getRootReducer(initialState));
export default store;

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc