|
@@ -129,236 +129,6 @@ composeReducers(
|
|
|
|
|
|
## Redux helpers
|
|
## Redux helpers
|
|
|
|
|
|
-### `deepGetOrNil(key, ...)`
|
|
|
|
-### `deget(key, ...)`
|
|
|
|
-
|
|
|
|
-Creates an accessor function allowing
|
|
|
|
-to get specified key from any object.
|
|
|
|
-
|
|
|
|
-Specify keys by passing a list of keys to `deepGetOrNil`.
|
|
|
|
-Key can be either:
|
|
|
|
- - number
|
|
|
|
- - `keyInMap(obj)`
|
|
|
|
- - array of Keys
|
|
|
|
- - anything else, which is `toString()`ed and dot-split.
|
|
|
|
-
|
|
|
|
-```js
|
|
|
|
-const name = deget("name");
|
|
|
|
-
|
|
|
|
-name({name: "Tom"});
|
|
|
|
-// => "Tom"
|
|
|
|
-
|
|
|
|
-const city = deget("address.city");
|
|
|
|
-const city2 = deget("address", "city");
|
|
|
|
-// and other forms, like:
|
|
|
|
-// const city3 = deget(["address", "city"]);
|
|
|
|
-// const city4 = deget("address", [[], "city"]);
|
|
|
|
-// const city5 = deget([[], "address.city"]);
|
|
|
|
-// etc.
|
|
|
|
-const object = {address: {city: "New York"}};
|
|
|
|
-
|
|
|
|
-city(object);
|
|
|
|
-// => "New York"
|
|
|
|
-city2(object);
|
|
|
|
-// => "New York"
|
|
|
|
-
|
|
|
|
-city(undefined);
|
|
|
|
-// => undefined
|
|
|
|
-city(null);
|
|
|
|
-// => undefined
|
|
|
|
-city({});
|
|
|
|
-// => undefined
|
|
|
|
-city({address: null});
|
|
|
|
-// => undefined
|
|
|
|
-city({address: {}});
|
|
|
|
-// => undefined
|
|
|
|
-city({address: {city: null}});
|
|
|
|
-// => null
|
|
|
|
-```
|
|
|
|
-
|
|
|
|
-If you put a number in a list of keys to use,
|
|
|
|
-an object will be treated as an array.
|
|
|
|
-
|
|
|
|
-If you put a `keyInMap(obj)` in a list of keys to use,
|
|
|
|
-an object will be treated as a `Map`.
|
|
|
|
-
|
|
|
|
-That way you can create eg. `const c = deget("person", 34, "name")`
|
|
|
|
-to access `obj.person[34].name` with `c(obj)`.
|
|
|
|
-
|
|
|
|
-### `deepCopyOnWrite(key, ...)(val)`
|
|
|
|
-### `decow(key, ...)(val)`
|
|
|
|
-
|
|
|
|
-Creates a modifier function allowing
|
|
|
|
-to "set" specified key to any object
|
|
|
|
-in an immutable fashion, eg. creating a modified copy
|
|
|
|
-when actual write happens.
|
|
|
|
-
|
|
|
|
-If properties that are to be parents of a sub-value
|
|
|
|
-are not present, they are created.
|
|
|
|
-
|
|
|
|
-Specify keys by passing a list of keys to `deepCopyOnWrite`.
|
|
|
|
-Key can be either:
|
|
|
|
- - number
|
|
|
|
- - `keyInMap(obj)`
|
|
|
|
- - array of Keys
|
|
|
|
- - anything else, which is `toString()`ed and dot-split.
|
|
|
|
-
|
|
|
|
-In case no change actually happens (same value is set which is
|
|
|
|
-already present), returns the original object.
|
|
|
|
-
|
|
|
|
-```js
|
|
|
|
-const setName = decow("name");
|
|
|
|
-
|
|
|
|
-setName("Jerry")({name: "Tom"});
|
|
|
|
-// => {name: "Jerry"}
|
|
|
|
-
|
|
|
|
-const setCity = decow("address.city");
|
|
|
|
-const setCity2 = decow("address", "city");
|
|
|
|
-// and other forms, like:
|
|
|
|
-// const setCity3 = decow(["address", "city"]);
|
|
|
|
-// const setCity4 = decow("address", [[], "city"]);
|
|
|
|
-// const setCity5 = decow([[], "address.city"]);
|
|
|
|
-// etc.
|
|
|
|
-const object = {address: {city: "New York"}};
|
|
|
|
-
|
|
|
|
-setCity("London")(object);
|
|
|
|
-// => {address: {city: "London"}}
|
|
|
|
-setCity2("London")(object);
|
|
|
|
-// => {address: {city: "London"}}
|
|
|
|
-object;
|
|
|
|
-// => {address: {city: "New York"}}
|
|
|
|
-setCity("New York")(object) === object;
|
|
|
|
-// => true
|
|
|
|
-setCity("New York")(object) === object;
|
|
|
|
-// => true
|
|
|
|
-
|
|
|
|
-const setCityLondon = setCity("London");
|
|
|
|
-
|
|
|
|
-setCityLondon(undefined);
|
|
|
|
-// => {address: {city: "London"}}
|
|
|
|
-setCityLondon(null);
|
|
|
|
-// => {address: {city: "London"}}
|
|
|
|
-setCityLondon({});
|
|
|
|
-// => {address: {city: "London"}}
|
|
|
|
-setCityLondon({address: null});
|
|
|
|
-// => {address: {city: "London"}}
|
|
|
|
-setCityLondon({address: {}});
|
|
|
|
-// => {address: {city: "London"}}
|
|
|
|
-setCityLondon({address: {city: null}});
|
|
|
|
-// => {address: {city: "London"}}
|
|
|
|
-```
|
|
|
|
-
|
|
|
|
-If you put a number in a list of keys to use,
|
|
|
|
-an object will be treated as an array (unlike the default string case,
|
|
|
|
-where it is treated as an object), so copy wil be created
|
|
|
|
-using `[...obj]`, not using `{...obj}`.
|
|
|
|
-
|
|
|
|
-That way you can create eg. `const c = decow("person", 34, "name")`
|
|
|
|
-to "set" `obj.person[34].name` with `c(val)(obj)`.
|
|
|
|
-
|
|
|
|
-If you put a `keyInMap(key)` in a list of keys to use,
|
|
|
|
-an object will be treated as a `Map` (unlike the default string case,
|
|
|
|
-where it is treated as an object), so copy wil be created
|
|
|
|
-using `new Map(obj)`, not using `{...obj}`.
|
|
|
|
-
|
|
|
|
-### `deepCopyOnMap(key, ...)(fn)`
|
|
|
|
-### `decomap(key, ...)(fn)`
|
|
|
|
-
|
|
|
|
-Creates a modifier function allowing
|
|
|
|
-to "map" value at specified key
|
|
|
|
-in an immutable fashion, eg. creating a modified copy
|
|
|
|
-when actual modification happens.
|
|
|
|
-
|
|
|
|
-If properties that are to be parents of a sub-value
|
|
|
|
-are not present, they are _not_ created.
|
|
|
|
-In other words, if the key to modify does not exist,
|
|
|
|
-no change happens.
|
|
|
|
-
|
|
|
|
-Specify keys by passing a list of keys to `deepCopyOnMap`.
|
|
|
|
-Key can be either:
|
|
|
|
- - number
|
|
|
|
- - `keyInMap(obj)`
|
|
|
|
- - array of Keys
|
|
|
|
- - anything else, which is `toString()`ed and dot-split.
|
|
|
|
-
|
|
|
|
-In case no change actually happens (same value is set which is
|
|
|
|
-already present), returns the original object.
|
|
|
|
-
|
|
|
|
-```js
|
|
|
|
-const mapName = decomap("name");
|
|
|
|
-
|
|
|
|
-mapName(x => x.toUpperCase())({name: "Tom"});
|
|
|
|
-// => {name: "TOM"}
|
|
|
|
-
|
|
|
|
-const mapCity = decomap("address.city");
|
|
|
|
-const mapCity2 = decomap("address", "city");
|
|
|
|
-// and other forms, like:
|
|
|
|
-// const mapCity3 = decomap(["address", "city"]);
|
|
|
|
-// const mapCity4 = decomap("address", [[], "city"]);
|
|
|
|
-// const mapCity5 = decomap([[], "address.city"]);
|
|
|
|
-// etc.
|
|
|
|
-const object = {address: {city: "New York"}};
|
|
|
|
-
|
|
|
|
-mapCity(x => "London")(object);
|
|
|
|
-// => {address: {city: "London"}}
|
|
|
|
-mapCity2(x => "London")(object);
|
|
|
|
-// => {address: {city: "London"}}
|
|
|
|
-object;
|
|
|
|
-// => {address: {city: "New York"}}
|
|
|
|
-mapCity(x => "New York")(object) === object;
|
|
|
|
-// => true
|
|
|
|
-mapCity2(x => "New York")(object) === object;
|
|
|
|
-// => true
|
|
|
|
-
|
|
|
|
-const mapCityLondon = mapCity(x => "London");
|
|
|
|
-
|
|
|
|
-mapCityLondon(undefined);
|
|
|
|
-// => undefined
|
|
|
|
-mapCityLondon(null);
|
|
|
|
-// => null
|
|
|
|
-mapCityLondon({});
|
|
|
|
-// => {}
|
|
|
|
-mapCityLondon({address: null});
|
|
|
|
-// => {address: null}
|
|
|
|
-mapCityLondon({address: {}});
|
|
|
|
-// => {address: {}}
|
|
|
|
-mapCityLondon({address: {city: null}});
|
|
|
|
-// => {address: {city: "London"}}
|
|
|
|
-```
|
|
|
|
-
|
|
|
|
-If you put a number in a list of keys to use,
|
|
|
|
-an object will be treated as an array (unlike the default string case,
|
|
|
|
-where it is treated as an object), so copy wil be created
|
|
|
|
-using `[...obj]`, not using `{...obj}`.
|
|
|
|
-
|
|
|
|
-That way you can create eg. `const c = decomap("person", 34, "name")`
|
|
|
|
-to "set" `obj.person[34].name` with `c(fn)(obj)`.
|
|
|
|
-
|
|
|
|
-If you put a `keyInMap(key)` in a list of keys to use,
|
|
|
|
-an object will be treated as a `Map` (unlike the default string case,
|
|
|
|
-where it is treated as an object), so copy wil be created
|
|
|
|
-using `new Map(obj)`, not using `{...obj}`.
|
|
|
|
-
|
|
|
|
-### `keyInMap(obj)`
|
|
|
|
-### `kim(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])`
|
|
### `typedAction(type, [fn])`
|
|
|
|
|
|
This creates an action creator function that amends existing `fn` by:
|
|
This creates an action creator function that amends existing `fn` by:
|
|
@@ -383,44 +153,3 @@ as well as `fooBar` action creator.
|
|
|
|
|
|
|
|
|
|
In case you don't pass the `fn` argument, the action creator only creates `{type}`.
|
|
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
|
|
|
|
-using `deget` and `decow`. The `options` argument can contain these additional fields:
|
|
|
|
- - `result` -- where to put elements (`obj` by default),
|
|
|
|
- - `resultKeys` -- what keys to use to put into `result` (`keys` by default)
|
|
|
|
- - `diff` -- where to put diffing elements (`undefined` by default)
|
|
|
|
-
|
|
|
|
-Function enumerates over keys and performs
|
|
|
|
-"get key from obj, call fn on value, put transformed value into resultKey in result"
|
|
|
|
-operations over them, using `deget` for getting and `decow` for putting.
|
|
|
|
-Additionally, if putting actually resulted in change,
|
|
|
|
-the result key and value is also put into `diff`.
|
|
|
|
-It then returns `{result, diff}` object.
|
|
|
|
-
|
|
|
|
-```js
|
|
|
|
-cowWorkshop(["a", "b.c"])();
|
|
|
|
-// does nothing
|
|
|
|
-// => {result: undefined, diff: undefined}
|
|
|
|
-
|
|
|
|
-cowWorkshop(["a", "b.c"], () => null)();
|
|
|
|
-// sets a and b.c to null
|
|
|
|
-// => {result: {a: null, b: {c: null}}, diff: {a: null, b: {c: null}}}
|
|
|
|
-
|
|
|
|
-const data = {a: 'foo', b: {c: null}};
|
|
|
|
-cowWorkshop(["a", "b.c"], JSON.stringify)(data);
|
|
|
|
-// changes a and b.c to string representation; change to a is noop
|
|
|
|
-// => {result: {a: 'foo', b: {c: 'null'}}, diff: {b: {c: 'null'}}}
|
|
|
|
-
|
|
|
|
-const stored = {ay: 'bar', beecee: 'baz', cee: 'quux'};
|
|
|
|
-const data = {a: 'foo', b: {c: null}};
|
|
|
|
-cowWorkshop(["a", "b.c"])(data, {result: stored, resultKeys: ["ay", "beecee"]});
|
|
|
|
-// "copies" a and b.c into `stored` under different keys
|
|
|
|
-// => {result: {ay: 'foo', beecee: null, cee: 'quux'}, diff: {ay: 'foo', beecee: null}}
|
|
|
|
-
|
|
|
|
-const data = {a: 'foo', b: {c: 'bar'}, c: 'quux'};
|
|
|
|
-cowWorkshop(["a", "b.c"], () => null)(data);
|
|
|
|
-// "nulls" a few fields
|
|
|
|
-// => {result: {a: null, b: {c: null}, c: 'quux'}, diff: {a: null, b: {c: null}}}
|
|
|
|
-```
|
|
|