|  | @@ -1,133 +1,6 @@
 | 
	
		
			
				|  |  | -# redux-sac
 | 
	
		
			
				|  |  | +# atpath
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -## Slice redux objects (reducers, middleware, ...)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -### `subReducer(key, reducer, additionalKey, ...)`
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Creates a wrapper reducer that calls `reducer`
 | 
	
		
			
				|  |  | -on the sub-state specified by `key`.
 | 
	
		
			
				|  |  | -Key can go in different formats, see `deepGetOrNil` below.
 | 
	
		
			
				|  |  | -Rest of the state is left untouched.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -```js
 | 
	
		
			
				|  |  | -const r = subReducer("persons", personReducer);
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -r({persons: ["John", "Jill"], cars: ["Honda"]}, action);
 | 
	
		
			
				|  |  | -// => {
 | 
	
		
			
				|  |  | -//   persons: personReducer(["John", "Jill"], action), 
 | 
	
		
			
				|  |  | -//   cars: ["Honda"]
 | 
	
		
			
				|  |  | -// }
 | 
	
		
			
				|  |  | -```
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Respects redux convention that if no change was made,
 | 
	
		
			
				|  |  | -the identical object should be returned. So in previous case,
 | 
	
		
			
				|  |  | -if `personReducer` would return the identical array,
 | 
	
		
			
				|  |  | -`r` would return the state object it was passed in.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -If persons were deeper in hierarchy, it could have been created as
 | 
	
		
			
				|  |  | -`const r = subReducer("files.persons", personReducer);` for example.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -You may pass additional keys
 | 
	
		
			
				|  |  | -as addition arguments. In that case, additional parts of state
 | 
	
		
			
				|  |  | -will be fetched and passed to a sub-reducer:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -```js
 | 
	
		
			
				|  |  | -const r = subReducer("persons", personReducer, "assets.cars");
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -r({persons: ["John", "Jill"], assets: {cars: ["Honda"]}}, action);
 | 
	
		
			
				|  |  | -// => {
 | 
	
		
			
				|  |  | -//   persons: personReducer(["John", "Jill"], action, ["Honda"]), 
 | 
	
		
			
				|  |  | -//   assets: {cars: ["Honda"]}
 | 
	
		
			
				|  |  | -// }
 | 
	
		
			
				|  |  | -```
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -This technique is mentioned in Redux docs, in "Beyond combineReducers" page.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -### `subMiddleware(key | selectorFn, middleware)`
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Creates a wrapper middleware
 | 
	
		
			
				|  |  | -on the sub-state specified by `key`
 | 
	
		
			
				|  |  | -or the selector function `selectorFn`
 | 
	
		
			
				|  |  | -by decorating `getState` part of the passed arg.
 | 
	
		
			
				|  |  | -The `key` can have different format, see `deepGetOrNil` below.
 | 
	
		
			
				|  |  | -Rest of the passed arg is left untouched.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -```js
 | 
	
		
			
				|  |  | -const r = subMiddleware("persons", ({getState}) => next => action => {
 | 
	
		
			
				|  |  | -  console.log(JSON.stringify(getState()));
 | 
	
		
			
				|  |  | -  return next(action);
 | 
	
		
			
				|  |  | -});
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -const altR = subMiddleware(state => state.persons, ({getState}) => next => action => {
 | 
	
		
			
				|  |  | -  console.log(JSON.stringify(getState()));
 | 
	
		
			
				|  |  | -  return next(action);
 | 
	
		
			
				|  |  | -});
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -// use r or altR in creation of store
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -store.getState();
 | 
	
		
			
				|  |  | -// => {persons: ["John", "Jill"], cars: ["Honda"]}
 | 
	
		
			
				|  |  | -store.dispatch({type: "any"});
 | 
	
		
			
				|  |  | -// console => ["John","Jill"] 
 | 
	
		
			
				|  |  | -```
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -If persons were deeper in hierarchy, it could have been created as
 | 
	
		
			
				|  |  | -`const r = subMiddleware("files.persons", ...);` for example.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -You can use `subMiddleware` to sub-state anything
 | 
	
		
			
				|  |  | -getting one parameter in which
 | 
	
		
			
				|  |  | -one of the properties passed is `getState` function;
 | 
	
		
			
				|  |  | -it is not special-case for middleware.
 | 
	
		
			
				|  |  | -For example, it is usable for wrapping `redux-effex` effect function.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -### `subEffex(key | selectorFn, effects)`
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Creates a wrapper around each element
 | 
	
		
			
				|  |  | -of the effects array
 | 
	
		
			
				|  |  | -on the sub-state specified by `key`
 | 
	
		
			
				|  |  | -or by selector function `selectorFn`
 | 
	
		
			
				|  |  | -by decorating `effect` function with `subMiddleware`
 | 
	
		
			
				|  |  | -and returns the array of the wrapped effects.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -```js
 | 
	
		
			
				|  |  | -const effects = [{
 | 
	
		
			
				|  |  | -  action: "foo",
 | 
	
		
			
				|  |  | -  effect: ({getState}) => {
 | 
	
		
			
				|  |  | -    console.log(JSON.stringify(getState()));
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -}];
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -const e = subEffex("persons", effects);
 | 
	
		
			
				|  |  | -const altE = subEffex(state => state.persons, effects);
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -// use e or altE in creation of store
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -store.getState();
 | 
	
		
			
				|  |  | -// => {persons: ["John", "Jill"], cars: ["Honda"]}
 | 
	
		
			
				|  |  | -store.dispatch({type: "foo"});
 | 
	
		
			
				|  |  | -// console => ["John","Jill"] 
 | 
	
		
			
				|  |  | -```
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -## Compose
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -### `composeReducers(reducer1, reducer2, ...)`
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Creates a wrapper reducer that calls passed reducers
 | 
	
		
			
				|  |  | -one after another, passing intermediate states.
 | 
	
		
			
				|  |  | -and returning the result of the last one.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Useful to "concatenate" a few `subReducer`s. like:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -```js
 | 
	
		
			
				|  |  | -composeReducers(
 | 
	
		
			
				|  |  | -  subReducer("files.persons", personReducer, "assets.swag"),
 | 
	
		
			
				|  |  | -  subReducer("files.clients", clientReducer, "news"),
 | 
	
		
			
				|  |  | -  subReducer("assets", assetReducer),
 | 
	
		
			
				|  |  | -  baseReducer
 | 
	
		
			
				|  |  | -)
 | 
	
		
			
				|  |  | -```
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -## Redux helpers
 | 
	
		
			
				|  |  | +Access and copy-on-modify JavaScript objects, including maps, using deep paths.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  ### `deepGetOrNil(key, ...)`
 | 
	
		
			
				|  |  |  ### `deget(key, ...)`
 | 
	
	
		
			
				|  | @@ -344,46 +217,6 @@ using `new Map(obj)`, not using `{...obj}`.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  Creates "`obj` as an index in a map".
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -### `cowValueModel(key, ...)`
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Deprecated.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -Creates an overloaded function allowing
 | 
	
		
			
				|  |  | -to set or get specified key from any object.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -It gets when one arg passed (works as `deget(key, ...)`),
 | 
	
		
			
				|  |  | -sets when two args (obj, val) passed (works as `decow(key, ...)(val)(obj)`),
 | 
	
		
			
				|  |  | -with a caveat: setting `undefined` ends up as plain get
 | 
	
		
			
				|  |  | -(ES2015 default arguments semantics),
 | 
	
		
			
				|  |  | -so props are not created when not present
 | 
	
		
			
				|  |  | -if setting `undefined`; other values including `null` are ok
 | 
	
		
			
				|  |  | -and create nonpresent props.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -### `typedAction(type, [fn])`
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -This creates an action creator function that amends existing `fn` by:
 | 
	
		
			
				|  |  | -  - adding a `type` property to the result, as well as
 | 
	
		
			
				|  |  | -  - adding a `TYPE` property to action creator itself.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -So for example:
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -```js
 | 
	
		
			
				|  |  | -export const answerQuestion =
 | 
	
		
			
				|  |  | -  typedAction("answer question", (index, answer) => ({
 | 
	
		
			
				|  |  | -    payload: {index, answer}
 | 
	
		
			
				|  |  | -  }));
 | 
	
		
			
				|  |  | -```
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -allows you to call `answerQuestion(2, "Albert Einstein")` to create
 | 
	
		
			
				|  |  | -`{type: "answer question", payload: {index: 2, answer: "Albert Einstein"}}`;
 | 
	
		
			
				|  |  | -but it also allows you to use `case answerQuestion.TYPE:` in your reducer,
 | 
	
		
			
				|  |  | -since `answerQuestion.TYPE === "answer question"`.
 | 
	
		
			
				|  |  | -IOW, this removes the two-space problem of having `const FOO_BAR_TYPE`
 | 
	
		
			
				|  |  | -as well as `fooBar` action creator.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -In case you don't pass the `fn` argument, the action creator only creates `{type}`.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  ### `cowWorkshop(keys, fn = x => x)(obj, [options])`
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  This is multipurpose enumerate-and-act function to manipulate objects
 |