Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@thi.ng/paths

Package Overview
Dependencies
Maintainers
1
Versions
199
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@thi.ng/paths - npm Package Compare versions

Comparing version 5.1.52 to 5.1.53

2

CHANGELOG.md
# 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
};
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"
}

@@ -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
};
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
};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc