@zedux/core
Version:
A high-level, declarative, composable form of Redux
114 lines (113 loc) • 4.67 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.wrapStoreInReducer = exports.hierarchyDescriptorToHierarchy = exports.getHierarchyType = void 0;
const createStore_1 = require("../api/createStore");
const detailedTypeof_1 = require("../api/detailedTypeof");
const is_1 = require("../api/is");
const isPlainObject_1 = require("../api/isPlainObject");
const zeduxTypes_1 = require("../api/zeduxTypes");
const general_1 = require("../utils/general");
/**
* Converts a Branch hierarchy descriptor to a HierarchyNode's children
*
* Really should only be used from `hierarchyDescriptorToHierarchy()`
*/
const branchToHierarchyChildren = (branch, registerSubStore, currentPath) => {
const children = {};
Object.entries(branch).forEach(([key, val]) => {
const newPath = [...currentPath, key];
children[key] = (0, exports.hierarchyDescriptorToHierarchy)(val, registerSubStore, newPath);
});
return children;
};
/**
* Turns a non-branch node from a user-supplied hierarchy descriptor into a
* HierarchyNode object
*/
const nonBranchToHierarchyNode = (type, hierarchy, registerSubStore, currentPath) => {
if (type === general_1.NullNodeType) {
return { type };
}
if (type === general_1.ReducerNodeType) {
return { type, reducer: hierarchy };
}
// It's a Store hierarchy descriptor
return {
type: type,
destroy: registerSubStore(currentPath, hierarchy),
reducer: (0, exports.wrapStoreInReducer)(hierarchy),
store: hierarchy,
};
};
/**
* Determines the HierarchyNodeType of the given hierarchy descriptor.
*
* Throws a TypeError if the descriptor is invalid.
*/
const getHierarchyType = (descriptor) => {
if (typeof descriptor === 'function')
return general_1.ReducerNodeType;
if (descriptor && (0, is_1.is)(descriptor, createStore_1.Store))
return general_1.StoreNodeType;
if ((0, isPlainObject_1.isPlainObject)(descriptor))
return general_1.BranchNodeType;
if (true /* DEV */ && descriptor != null) {
throw new TypeError(`Zedux: store.use() - Hierarchy descriptor nodes must be reducers, stores, plain objects, or null. Received ${(0, detailedTypeof_1.detailedTypeof)(descriptor)}`);
}
return general_1.NullNodeType;
};
exports.getHierarchyType = getHierarchyType;
/**
* Turns a normal, user-supplied hierarchy descriptor into a Hierarchy for easy
* reducer hierarchy creating, diffing, merging, and destroying.
*
* Also figures out the reducer for non-branch nodes.
*/
const hierarchyDescriptorToHierarchy = (hierarchy, registerSubStore, currentPath = []) => {
const type = (0, exports.getHierarchyType)(hierarchy);
if (type !== general_1.BranchNodeType) {
return nonBranchToHierarchyNode(type, hierarchy, registerSubStore, currentPath);
}
// It's a Branch; recursively convert the whole tree. We don't need to supply
// a reducer for this branch 'cause the merge process does that for us
return {
type,
children: branchToHierarchyChildren(hierarchy, registerSubStore, currentPath),
};
};
exports.hierarchyDescriptorToHierarchy = hierarchyDescriptorToHierarchy;
/**
* Creates a reducer that wraps the entry points of the given store.
*
* This reducer will propagate actions down the child store's reducers.
*
* Wraps all actions in the special `inherit` meta node to inform the child
* store's effects subscribers that this action was received from its parent
* store.
*
* Since the parent store also registers an effects subscriber on this child
* store, it will know not to propagate the inherited action from the child
* store. UPDATE: Actually, it doesn't even need to check - the parent store
* knows that it _isDispatching and can ignore child store actions while it is.
*/
const wrapStoreInReducer = (store) => {
const reducer = (state, action) => {
// If this is the special hydrate or partial hydrate action, re-create the
// action's payload using the current state slice
if (action.type === zeduxTypes_1.zeduxTypes.hydrate ||
action.type === zeduxTypes_1.zeduxTypes.merge) {
action = {
type: zeduxTypes_1.zeduxTypes.hydrate,
payload: state,
};
}
// Tell the child store's effect subscribers that this action is inherited
const inheritedAction = {
metaType: zeduxTypes_1.zeduxTypes.inherit,
payload: action,
};
return store.dispatch(inheritedAction);
};
return reducer;
};
exports.wrapStoreInReducer = wrapStoreInReducer;