UNPKG

@zedux/core

Version:

A high-level, declarative, composable form of Redux

94 lines (75 loc) 2.51 kB
import { Action, ActionChain, ActionMeta } from '../types' import { detailedTypeof } from './detailedTypeof' const assertActionExists = (action: ActionChain) => { if (action) return throw new Error( `Zedux: Invalid action chain. The last node in the chain must be either a valid action object with a non-empty "type" property or an effect with a non-empty "effectType" property. Received ${detailedTypeof( action )}` ) } const getNewRoot = <T extends ActionChain>( currentNode: T, prevNode: T | null, rootNode: T | null ): T => { // If the match is at the top layer, just return the next layer if (!prevNode || !rootNode) return currentNode.payload // If the match is at least one layer deep, swap out the target layer // and return the new root of the action chain prevNode.payload = currentNode.payload return rootNode } /** * Returns the value of the metaData field of the first ActionMeta object in the * chain with the given metaType. */ export const getMetaData = (action: ActionChain, metaType: string) => { while ((action as ActionMeta).metaType) { if ((action as ActionMeta).metaType === metaType) { return (action as ActionMeta).metaData } action = action.payload if (DEV) { assertActionExists(action) } } } /** * Strips all ActionMeta nodes off an ActionChain and returns the wrapped Action */ export const removeAllMeta = (action: ActionChain) => { while ((action as ActionMeta).metaType) { action = action.payload if (DEV) { assertActionExists(action) } } return action as Action } /** * Removes the first found meta node with the given metaType in the given action * chain. * * The metaType does not have to exist in the action chain (though this'll be * pretty inefficient and wasteful if it doesn't). */ export const removeMeta = (action: ActionChain, metaType: string) => { let currentNode = action let prevNode = null let rootNode = null while ((currentNode as ActionMeta).metaType) { if ((currentNode as ActionMeta).metaType === metaType) { return getNewRoot(currentNode, prevNode, rootNode) } // Move down the chain const clonedNode = { ...currentNode } prevNode && (prevNode.payload = clonedNode) prevNode = clonedNode currentNode = currentNode.payload // If this will be the new root, remember it rootNode || (rootNode = prevNode) } // No match found; return the original action chain return action }