@thi.ng/paths
Advanced tools
Comparing version 5.1.52 to 5.1.53
# Change Log | ||
- **Last updated**: 2023-12-09T19:12:03Z | ||
- **Last updated**: 2023-12-11T10:07:09Z | ||
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub) | ||
@@ -5,0 +5,0 @@ |
import { toPath } from "./path.js"; | ||
import { updateIn } from "./update-in.js"; | ||
/** | ||
* Unchecked version of {@link deleteIn}. Path can be given as string or | ||
* tuple. | ||
* | ||
* @example | ||
* ```ts | ||
* // unchecked | ||
* deleteIn({ a: { b: { c: 23 } } }, "a.b.c"); | ||
* // { a: { b: { } } } | ||
* ``` | ||
* | ||
* @param state - | ||
* @param path - | ||
*/ | ||
export const deleteInUnsafe = (state, path) => deleteIn(state, path); | ||
export function deleteIn(state, path) { | ||
const ks = toPath(path).slice(); | ||
if (ks.length) { | ||
const k = ks.pop(); | ||
return updateIn(state, ks, (x) => ((x = { ...x }), delete x[k], x)); | ||
} | ||
const deleteInUnsafe = (state, path) => deleteIn(state, path); | ||
function deleteIn(state, path) { | ||
const ks = toPath(path).slice(); | ||
if (ks.length) { | ||
const k = ks.pop(); | ||
return updateIn( | ||
state, | ||
ks, | ||
(x) => (x = { ...x }, delete x[k], x) | ||
); | ||
} | ||
} | ||
export { | ||
deleteIn, | ||
deleteInUnsafe | ||
}; |
import { defGetter } from "./getter.js"; | ||
/** | ||
* Unchecked version of {@link getIn}. Returns `undefined` if path is | ||
* invalid. | ||
* | ||
* @remarks | ||
* The type parameter `T` can be used to indicate the type of the nested | ||
* value to be retrieved (default: `any`). | ||
* | ||
* @example | ||
* ```ts | ||
* getInUnsafe({ a: { b: { c: 23 } } }, "a.b.c"); | ||
* // 23 | ||
* ``` | ||
* | ||
* @param state - | ||
* @param path - | ||
*/ | ||
export const getInUnsafe = (state, path) => defGetter(path)(state); | ||
export function getIn(state, path) { | ||
return defGetter(path)(state); | ||
const getInUnsafe = (state, path) => defGetter(path)(state); | ||
function getIn(state, path) { | ||
return defGetter(path)(state); | ||
} | ||
export { | ||
getIn, | ||
getInUnsafe | ||
}; |
import { identity } from "@thi.ng/api/fn"; | ||
import { toPath } from "./path.js"; | ||
/** | ||
* Unchecked version of {@link defGetter}. | ||
* | ||
* @remarks | ||
* The type parameter `T` can be used to indicate the type of the nested | ||
* value to be retrieved (default: `any`). | ||
* | ||
* Also see: {@link getIn}, {@link getInUnsafe} | ||
* | ||
* @example | ||
* ```ts | ||
* const g = defGetterUnsafe("a.b.c"); | ||
* | ||
* g({ a: { b: { c: 23} } }) // 23 | ||
* g({ x: 23 }) // undefined | ||
* g() // undefined | ||
* ``` | ||
* | ||
* @param path - | ||
*/ | ||
export const defGetterUnsafe = (path) => defGetter(path); | ||
export function defGetter(path) { | ||
const ks = toPath(path); | ||
const [a, b, c, d] = ks; | ||
switch (ks.length) { | ||
case 0: | ||
return identity; | ||
case 1: | ||
return (s) => (s != null ? s[a] : undefined); | ||
case 2: | ||
return (s) => s != null ? ((s = s[a]) != null ? s[b] : undefined) : undefined; | ||
case 3: | ||
return (s) => s != null | ||
? (s = s[a]) != null | ||
? (s = s[b]) != null | ||
? s[c] | ||
: undefined | ||
: undefined | ||
: undefined; | ||
case 4: | ||
return (s) => s != null | ||
? (s = s[a]) != null | ||
? (s = s[b]) != null | ||
? (s = s[c]) != null | ||
? s[d] | ||
: undefined | ||
: undefined | ||
: undefined | ||
: undefined; | ||
default: | ||
return (s) => { | ||
const n = ks.length - 1; | ||
let res = s; | ||
for (let i = 0; res != null && i <= n; i++) { | ||
res = res[ks[i]]; | ||
} | ||
return res; | ||
}; | ||
} | ||
const defGetterUnsafe = (path) => defGetter(path); | ||
function defGetter(path) { | ||
const ks = toPath(path); | ||
const [a, b, c, d] = ks; | ||
switch (ks.length) { | ||
case 0: | ||
return identity; | ||
case 1: | ||
return (s) => s != null ? s[a] : void 0; | ||
case 2: | ||
return (s) => s != null ? (s = s[a]) != null ? s[b] : void 0 : void 0; | ||
case 3: | ||
return (s) => s != null ? (s = s[a]) != null ? (s = s[b]) != null ? s[c] : void 0 : void 0 : void 0; | ||
case 4: | ||
return (s) => s != null ? (s = s[a]) != null ? (s = s[b]) != null ? (s = s[c]) != null ? s[d] : void 0 : void 0 : void 0 : void 0; | ||
default: | ||
return (s) => { | ||
const n = ks.length - 1; | ||
let res = s; | ||
for (let i = 0; res != null && i <= n; i++) { | ||
res = res[ks[i]]; | ||
} | ||
return res; | ||
}; | ||
} | ||
} | ||
export { | ||
defGetter, | ||
defGetterUnsafe | ||
}; |
import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; | ||
import { mutIn } from "./mut-in.js"; | ||
export function mutInManyUnsafe(state, ...pairs) { | ||
const n = pairs.length; | ||
n & 1 && illegalArgs(`require even number of args (got ${pairs.length})`); | ||
for (let i = 0; i < n && state; i += 2) { | ||
state = mutIn(state, pairs[i], pairs[i + 1]); | ||
} | ||
return state; | ||
function mutInManyUnsafe(state, ...pairs) { | ||
const n = pairs.length; | ||
n & 1 && illegalArgs(`require even number of args (got ${pairs.length})`); | ||
for (let i = 0; i < n && state; i += 2) { | ||
state = mutIn(state, pairs[i], pairs[i + 1]); | ||
} | ||
return state; | ||
} | ||
export { | ||
mutInManyUnsafe | ||
}; |
import { defMutator } from "./mutator.js"; | ||
/** | ||
* Unchecked version of {@link mutIn}. | ||
* | ||
* @remarks | ||
* The type parameter `T` can be used to indicate the type of the nested | ||
* value to be mutated (default: `any`). | ||
* | ||
* @example | ||
* ```ts | ||
* mutIn({ a: { b: [10, 20] } }, "a.b.1", 23); | ||
* // { a: { b: [ 10, 23 ] } } | ||
* | ||
* // fails (see `mutator` docs) | ||
* mutIn({}, "a.b.c", 23); | ||
* // undefined | ||
* ``` | ||
* | ||
* @param state - | ||
* @param path - | ||
* @param val - | ||
*/ | ||
export const mutInUnsafe = (state, path, val) => defMutator(path)(state, val); | ||
export function mutIn(state, path, val) { | ||
return defMutator(path)(state, val); | ||
const mutInUnsafe = (state, path, val) => defMutator(path)(state, val); | ||
function mutIn(state, path, val) { | ||
return defMutator(path)(state, val); | ||
} | ||
export { | ||
mutIn, | ||
mutInUnsafe | ||
}; |
105
mutator.js
import { disallowProtoPath, toPath } from "./path.js"; | ||
/** | ||
* Unchecked version of {@link defMutator}. | ||
* | ||
* @remarks | ||
* The type parameter `T` can be used to indicate the type of the nested | ||
* value to be mutated (default: `any`). | ||
* | ||
* @param path - | ||
*/ | ||
export const defMutatorUnsafe = (path) => defMutator(path); | ||
export function defMutator(path) { | ||
const ks = toPath(path); | ||
disallowProtoPath(ks); | ||
let [a, b, c, d] = ks; | ||
switch (ks.length) { | ||
case 0: | ||
return (_, x) => x; | ||
case 1: | ||
return (s, x) => (s ? ((s[a] = x), s) : undefined); | ||
case 2: | ||
return (s, x) => { | ||
let t; | ||
return s | ||
? (t = s[a]) | ||
? ((t[b] = x), s) | ||
: undefined | ||
: undefined; | ||
}; | ||
case 3: | ||
return (s, x) => { | ||
let t; | ||
return s | ||
? (t = s[a]) | ||
? (t = t[b]) | ||
? ((t[c] = x), s) | ||
: undefined | ||
: undefined | ||
: undefined; | ||
}; | ||
case 4: | ||
return (s, x) => { | ||
let t; | ||
return s | ||
? (t = s[a]) | ||
? (t = t[b]) | ||
? (t = t[c]) | ||
? ((t[d] = x), s) | ||
: undefined | ||
: undefined | ||
: undefined | ||
: undefined; | ||
}; | ||
default: | ||
return (s, x) => { | ||
let t = s; | ||
const n = ks.length - 1; | ||
for (let k = 0; k < n; k++) { | ||
if (!(t = t[ks[k]])) | ||
return; | ||
} | ||
t[ks[n]] = x; | ||
return s; | ||
}; | ||
} | ||
const defMutatorUnsafe = (path) => defMutator(path); | ||
function defMutator(path) { | ||
const ks = toPath(path); | ||
disallowProtoPath(ks); | ||
let [a, b, c, d] = ks; | ||
switch (ks.length) { | ||
case 0: | ||
return (_, x) => x; | ||
case 1: | ||
return (s, x) => s ? (s[a] = x, s) : void 0; | ||
case 2: | ||
return (s, x) => { | ||
let t; | ||
return s ? (t = s[a]) ? (t[b] = x, s) : void 0 : void 0; | ||
}; | ||
case 3: | ||
return (s, x) => { | ||
let t; | ||
return s ? (t = s[a]) ? (t = t[b]) ? (t[c] = x, s) : void 0 : void 0 : void 0; | ||
}; | ||
case 4: | ||
return (s, x) => { | ||
let t; | ||
return s ? (t = s[a]) ? (t = t[b]) ? (t = t[c]) ? (t[d] = x, s) : void 0 : void 0 : void 0 : void 0; | ||
}; | ||
default: | ||
return (s, x) => { | ||
let t = s; | ||
const n = ks.length - 1; | ||
for (let k = 0; k < n; k++) { | ||
if (!(t = t[ks[k]])) | ||
return; | ||
} | ||
t[ks[n]] = x; | ||
return s; | ||
}; | ||
} | ||
} | ||
export { | ||
defMutator, | ||
defMutatorUnsafe | ||
}; |
{ | ||
"name": "@thi.ng/paths", | ||
"version": "5.1.52", | ||
"version": "5.1.53", | ||
"description": "Immutable, optimized and optionally typed path-based object property / array accessors with structural sharing", | ||
@@ -27,3 +27,5 @@ "type": "module", | ||
"scripts": { | ||
"build": "yarn clean && tsc --declaration", | ||
"build": "yarn build:esbuild && yarn build:decl", | ||
"build:decl": "tsc --declaration --emitDeclarationOnly", | ||
"build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts", | ||
"clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc", | ||
@@ -37,8 +39,9 @@ "doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts", | ||
"dependencies": { | ||
"@thi.ng/api": "^8.9.11", | ||
"@thi.ng/checks": "^3.4.11", | ||
"@thi.ng/errors": "^2.4.5" | ||
"@thi.ng/api": "^8.9.12", | ||
"@thi.ng/checks": "^3.4.12", | ||
"@thi.ng/errors": "^2.4.6" | ||
}, | ||
"devDependencies": { | ||
"@microsoft/api-extractor": "^7.38.3", | ||
"esbuild": "^0.19.8", | ||
"rimraf": "^5.0.5", | ||
@@ -126,3 +129,3 @@ "tools": "^0.0.1", | ||
}, | ||
"gitHead": "25f2ac8ff795a432a930119661b364d4d93b59a0\n" | ||
"gitHead": "5e7bafedfc3d53bc131469a28de31dd8e5b4a3ff\n" | ||
} |
85
path.js
@@ -5,68 +5,25 @@ import { isArray } from "@thi.ng/checks/is-array"; | ||
import { assert } from "@thi.ng/errors/assert"; | ||
/** | ||
* Converts the given key path to canonical form (array). | ||
* | ||
* ``` | ||
* toPath("a.b.c"); | ||
* // ["a", "b", "c"] | ||
* | ||
* toPath(0) | ||
* // [0] | ||
* | ||
* toPath(["a", "b", "c"]) | ||
* // ["a", "b", "c"] | ||
* ``` | ||
* | ||
* @param path - | ||
*/ | ||
export const toPath = (path) => isArray(path) | ||
? path | ||
: isString(path) | ||
? path.length > 0 | ||
? path.split(".") | ||
: [] | ||
: path != null | ||
? [path] | ||
: []; | ||
/** | ||
* Takes an arbitrary object and lookup path. Descends into object along | ||
* path and returns true if the full path exists (even if final leaf | ||
* value is `null` or `undefined`). Checks are performed using | ||
* `hasOwnProperty()`. | ||
* | ||
* @param obj - | ||
* @param path - | ||
*/ | ||
export const exists = (obj, path) => { | ||
if (obj == null) { | ||
return false; | ||
const toPath = (path) => isArray(path) ? path : isString(path) ? path.length > 0 ? path.split(".") : [] : path != null ? [path] : []; | ||
const exists = (obj, path) => { | ||
if (obj == null) { | ||
return false; | ||
} | ||
path = toPath(path); | ||
for (let n = path.length - 1, i = 0; i <= n; i++) { | ||
const k = path[i]; | ||
if (!obj.hasOwnProperty(k)) { | ||
return false; | ||
} | ||
path = toPath(path); | ||
for (let n = path.length - 1, i = 0; i <= n; i++) { | ||
const k = path[i]; | ||
if (!obj.hasOwnProperty(k)) { | ||
return false; | ||
} | ||
obj = obj[k]; | ||
if (obj == null && i < n) { | ||
return false; | ||
} | ||
obj = obj[k]; | ||
if (obj == null && i < n) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
return true; | ||
}; | ||
/** | ||
* Helper function to analyze given `path` using | ||
* [`isProtoPath()`](https://docs.thi.ng/umbrella/checks/functions/isProtoPath.html). | ||
* Throws an error if path contains any property which might lead to prototype | ||
* poisoning. | ||
* | ||
* @remarks | ||
* The following properties are considered illegal. | ||
* | ||
* - `__proto__` | ||
* - `prototype` | ||
* - `constructor` | ||
* | ||
* @param path - | ||
*/ | ||
export const disallowProtoPath = (path) => (assert(!isProtoPath(path), `unsafe path: '${path}'`), path); | ||
const disallowProtoPath = (path) => (assert(!isProtoPath(path), `unsafe path: '${path}'`), path); | ||
export { | ||
disallowProtoPath, | ||
exists, | ||
toPath | ||
}; |
import { illegalArgs } from "@thi.ng/errors/illegal-arguments"; | ||
import { setIn } from "./set-in.js"; | ||
export function setInManyUnsafe(state, ...pairs) { | ||
const n = pairs.length; | ||
n & 1 && | ||
illegalArgs(`require even number of KV args (got ${pairs.length})`); | ||
for (let i = 0; i < n; i += 2) { | ||
state = setIn(state, pairs[i], pairs[i + 1]); | ||
} | ||
return state; | ||
function setInManyUnsafe(state, ...pairs) { | ||
const n = pairs.length; | ||
n & 1 && illegalArgs(`require even number of KV args (got ${pairs.length})`); | ||
for (let i = 0; i < n; i += 2) { | ||
state = setIn(state, pairs[i], pairs[i + 1]); | ||
} | ||
return state; | ||
} | ||
export { | ||
setInManyUnsafe | ||
}; |
import { defSetter } from "./setter.js"; | ||
/** | ||
* Unchecked version of {@link setIn}. | ||
* | ||
* @remarks | ||
* The type parameter `T` can be used to indicate the type of the nested | ||
* value to be set (default: `any`). | ||
* | ||
* @example | ||
* ```ts | ||
* setInUnsafe({}, "a.b.c", 23); | ||
* // { a: { b: { c: 23} } } | ||
* ``` | ||
* | ||
* @param state - | ||
* @param path - | ||
*/ | ||
export const setInUnsafe = (state, path, val) => defSetter(path)(state, val); | ||
export function setIn(state, path, val) { | ||
return defSetter(path)(state, val); | ||
const setInUnsafe = (state, path, val) => defSetter(path)(state, val); | ||
function setIn(state, path, val) { | ||
return defSetter(path)(state, val); | ||
} | ||
export { | ||
setIn, | ||
setInUnsafe | ||
}; |
170
setter.js
import { isArray } from "@thi.ng/checks/is-array"; | ||
import { isTypedArray } from "@thi.ng/checks/is-typedarray"; | ||
import { toPath } from "./path.js"; | ||
/** | ||
* Composes a setter function for given nested update path. Optimized | ||
* fast execution paths are provided for path lengths less up to 4. | ||
* | ||
* @remarks | ||
* Supports both arrays and objects and creates intermediate shallow | ||
* copies at each level of the path. Thus provides structural sharing | ||
* with the original data for any branches not being updated by the | ||
* setter. | ||
* | ||
* The type parameter `T` can be used to indicate the type of the nested | ||
* value to be updated (default: `any`). | ||
* | ||
* If `path` is given as string, it will be split using `.`. Returns | ||
* function which accepts single object and when called, **immutably** | ||
* updates value at given path, i.e. produces a partial deep copy of obj | ||
* up until given path. | ||
* | ||
* If any intermediate key is not present in the given obj, creates a | ||
* plain empty object for that key and descends further. | ||
* | ||
* If `path` is an empty string or array, the returned setter will | ||
* simply return the new value. | ||
* | ||
* Only keys in the path will be modified, all other keys present in the | ||
* given object retain their original values to provide efficient | ||
* structural sharing / re-use. | ||
* | ||
* @example | ||
* ```ts | ||
* s = defSetterUnsafe("a.b.c"); | ||
* // or | ||
* s = defSetterUnsafe(["a", "b", "c"]); | ||
* | ||
* s({ a: { b: { c: 23} } }, 24) | ||
* // { a: { b: { c: 24} } } | ||
* | ||
* s({ x: 23 }, 24) | ||
* // { x: 23, a: { b: { c: 24 } } } | ||
* | ||
* s(null, 24) | ||
* // { a: { b: { c: 24 } } } | ||
* ``` | ||
* | ||
* @example | ||
* ```ts | ||
* s = defSetterUnsafe("a.b.c"); | ||
* | ||
* a = { x: { y: { z: 1 } } }; | ||
* b = s(a, 2); | ||
* // { x: { y: { z: 1 } }, a: { b: { c: 2 } } } | ||
* | ||
* a.x === b.x // true | ||
* a.x.y === b.x.y // true | ||
* ``` | ||
* | ||
* @param path - | ||
*/ | ||
export const defSetterUnsafe = (path) => defSetter(path); | ||
export function defSetter(path) { | ||
const ks = toPath(path); | ||
const [a, b, c, d] = ks; | ||
switch (ks.length) { | ||
case 0: | ||
return (_, v) => v; | ||
case 1: | ||
return (s, v) => ((s = copy(s)), (s[a] = v), s); | ||
case 2: | ||
return (s, v) => { | ||
let x; | ||
s = copy(s); | ||
s[a] = x = copy(s[a]); | ||
x[b] = v; | ||
return s; | ||
}; | ||
case 3: | ||
return (s, v) => { | ||
let x, y; | ||
s = copy(s); | ||
s[a] = x = copy(s[a]); | ||
x[b] = y = copy(x[b]); | ||
y[c] = v; | ||
return s; | ||
}; | ||
case 4: | ||
return (s, v) => { | ||
let x, y, z; | ||
s = copy(s); | ||
s[a] = x = copy(s[a]); | ||
x[b] = y = copy(x[b]); | ||
y[c] = z = copy(y[c]); | ||
z[d] = v; | ||
return s; | ||
}; | ||
default: | ||
let f; | ||
for (let i = ks.length; i-- > 0;) { | ||
f = compS(ks[i], f); | ||
} | ||
return f; | ||
} | ||
const defSetterUnsafe = (path) => defSetter(path); | ||
function defSetter(path) { | ||
const ks = toPath(path); | ||
const [a, b, c, d] = ks; | ||
switch (ks.length) { | ||
case 0: | ||
return (_, v) => v; | ||
case 1: | ||
return (s, v) => (s = copy(s), s[a] = v, s); | ||
case 2: | ||
return (s, v) => { | ||
let x; | ||
s = copy(s); | ||
s[a] = x = copy(s[a]); | ||
x[b] = v; | ||
return s; | ||
}; | ||
case 3: | ||
return (s, v) => { | ||
let x, y; | ||
s = copy(s); | ||
s[a] = x = copy(s[a]); | ||
x[b] = y = copy(x[b]); | ||
y[c] = v; | ||
return s; | ||
}; | ||
case 4: | ||
return (s, v) => { | ||
let x, y, z; | ||
s = copy(s); | ||
s[a] = x = copy(s[a]); | ||
x[b] = y = copy(x[b]); | ||
y[c] = z = copy(y[c]); | ||
z[d] = v; | ||
return s; | ||
}; | ||
default: | ||
let f; | ||
for (let i = ks.length; i-- > 0; ) { | ||
f = compS(ks[i], f); | ||
} | ||
return f; | ||
} | ||
} | ||
/** | ||
* Creates a shallow copy of given array, typed array or plain object. | ||
* | ||
* @param x - | ||
*/ | ||
export const copy = (x) => isArray(x) || isTypedArray(x) ? x.slice() : { ...x }; | ||
/** | ||
* Helper for {@link defSetter}. Returns setter for a single step. | ||
* | ||
* @param k - | ||
* @param f - | ||
* | ||
* @internal | ||
*/ | ||
const copy = (x) => isArray(x) || isTypedArray(x) ? x.slice() : { ...x }; | ||
const compS = (k, f) => (s, v) => { | ||
s = copy(s); | ||
s[k] = f ? f(s[k], v) : v; | ||
return s; | ||
s = copy(s); | ||
s[k] = f ? f(s[k], v) : v; | ||
return s; | ||
}; | ||
export { | ||
copy, | ||
defSetter, | ||
defSetterUnsafe | ||
}; |
import { defGetter } from "./getter.js"; | ||
import { defSetter } from "./setter.js"; | ||
/** | ||
* Similar to {@link setInUnsafe}, but applies given function to current | ||
* path value (incl. any additional/optional arguments passed to | ||
* `updateIn`) and uses result as new value. Does not modify original | ||
* state. | ||
* | ||
* @remarks | ||
* Unchecked version of {@link updateIn}. The type parameter `T` can be | ||
* used to indicate the type of the nested value to be updated (default: | ||
* `any`). | ||
* | ||
* @example | ||
* ```ts | ||
* add = (x: number, y: number) => x + y; | ||
* updateInUnsafe({ a: { b: { c: 23 } } }, "a.b.c", add, 10); | ||
* // { a: { b: { c: 33 } } } | ||
* | ||
* // type checked | ||
* updateIn({ a: { b: { c: 23 } } }, ["a","b","c"], add, 10); | ||
* // { a: { b: { c: 33 } } } | ||
* | ||
* // type error (value at "a.b" is not a number) | ||
* updateIn({ a: { b: { c: 23 } } }, ["a","b"], add, 10); | ||
* ``` | ||
* | ||
* @param state - state to update | ||
* @param path - update path | ||
* @param fn - update function | ||
* @param args - optional args for `fn` | ||
*/ | ||
export const updateInUnsafe = (state, path, fn, ...args) => | ||
// @ts-ignore | ||
updateIn(state, path, fn, ...args); | ||
export function updateIn(state, path, fn, ...args) { | ||
return defSetter(path)(state, | ||
const updateInUnsafe = (state, path, fn, ...args) => ( | ||
// @ts-ignore | ||
updateIn(state, path, fn, ...args) | ||
); | ||
function updateIn(state, path, fn, ...args) { | ||
return defSetter(path)( | ||
state, | ||
// @ts-ignore | ||
fn.apply(null, (args.unshift(defGetter(path)(state)), args))); | ||
fn.apply(null, (args.unshift(defGetter(path)(state)), args)) | ||
); | ||
} | ||
export { | ||
updateIn, | ||
updateInUnsafe | ||
}; |
import { defGetter } from "./getter.js"; | ||
import { defSetter } from "./setter.js"; | ||
/** | ||
* Similar to {@link defSetterUnsafe}, returns a function to update | ||
* values at given `path` using provided update `fn`. Paths and the | ||
* arguments given to the returned function are NOT type checked. | ||
* | ||
* @remarks | ||
* The returned function accepts a single object / array and applies | ||
* `fn` to given path value (incl. any additional / optional arguments | ||
* passed) and uses result as new value. Does not modify original state. | ||
* | ||
* The type parameter `T` can be used to indicate the type of the nested | ||
* value to be updated (default: `any`). | ||
* | ||
* @example | ||
* ```ts | ||
* const incB = defUpdaterUnsafe("a.b", (x, n) => x + n); | ||
* // or | ||
* const incB = defUpdaterUnsafe(["a", "b"], (x, n) => x + n); | ||
* | ||
* incB({ a: { b: 10 } }, 13); | ||
* // { a: { b: 23 } } | ||
* ``` | ||
* | ||
* @param path - | ||
* @param fn - | ||
*/ | ||
export const defUpdaterUnsafe = (path, fn) => defUpdater(path, fn); | ||
export function defUpdater(path, fn) { | ||
const g = defGetter(path); | ||
const s = defSetter(path); | ||
return (state, ...args) => s(state, fn.apply(null, (args.unshift(g(state)), args))); | ||
const defUpdaterUnsafe = (path, fn) => defUpdater(path, fn); | ||
function defUpdater(path, fn) { | ||
const g = defGetter(path); | ||
const s = defSetter(path); | ||
return (state, ...args) => s(state, fn.apply(null, (args.unshift(g(state)), args))); | ||
} | ||
export { | ||
defUpdater, | ||
defUpdaterUnsafe | ||
}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
75678
6
908
Updated@thi.ng/api@^8.9.12
Updated@thi.ng/checks@^3.4.12
Updated@thi.ng/errors@^2.4.6