@valkyriestudios/utils 12.18.0 → 12.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- package/array/dedupe.d.ts +3 -0
- package/deep/freeze.js +2 -2
- package/deep/get.d.ts +14 -13
- package/deep/get.js +38 -16
- package/deep/seal.js +2 -2
- package/equal.js +6 -4
- package/index.d.ts +22 -20
- package/object/merge.d.ts +8 -7
- package/object/merge.js +24 -10
- package/object/pick.d.ts +7 -3
- package/object/pick.js +12 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -851,12 +851,17 @@ Copies the keys passed in the 'keys' array from the passed object to a new objec
|
|
|
851
851
|
pick({a: 1, b: 2, c: 3}, ['a','b']); // {a: 1, b: 2}
|
|
852
852
|
```
|
|
853
853
|
|
|
854
|
-
- **merge(target:Object={},obj:Object={})**
|
|
854
|
+
- **merge(target:Object={},obj:Object|Object[]={}, opts?:{union?:boolean})**
|
|
855
855
|
Merges two objects together, with the preference over the second object.
|
|
856
856
|
```typescript
|
|
857
|
-
merge({a: 1, b: false}, {a: 900, c: 50}); // {a: 900, b: false, c: 50}
|
|
857
|
+
merge({a: 1, b: false}, {a: 900, c: 50}, {union: true}); // {a: 900, b: false, c: 50}
|
|
858
|
+
merge({a: 1, b: false}, {a: 900, c: 50}, {union: false}); // {a: 900, b: false}
|
|
859
|
+
merge({a: 1, c: {bar: 'foo'}}, [{b: 2}, {c: {foo: 'bar'}}], {union: true}); // {a: 1, b: 2, c: {bar: 'foo', foo: 'bar'}}
|
|
858
860
|
```
|
|
859
861
|
|
|
862
|
+
Take Note: The default behavior is to not have union, this means that ONLY the keys in the target object
|
|
863
|
+
are going to be available in the response of this function.
|
|
864
|
+
|
|
860
865
|
- **define(props:Object, obj:Object={})**
|
|
861
866
|
Creates an object with the passed accessors set on it
|
|
862
867
|
```typescript
|
package/array/dedupe.d.ts
CHANGED
package/deep/freeze.js
CHANGED
package/deep/get.d.ts
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
* Get a property's value deep inside the structure of an array/object
|
|
3
3
|
*
|
|
4
4
|
* Example:
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
5
|
+
* const myObj = {
|
|
6
|
+
* a: 2,
|
|
7
|
+
* b: [
|
|
8
|
+
* {price : 2},
|
|
9
|
+
* {price : 4},
|
|
10
|
+
* ],
|
|
11
|
+
* };
|
|
12
|
+
* deepGet(myObj, 'b[0].price');
|
|
13
13
|
* Output:
|
|
14
|
-
*
|
|
14
|
+
* 2
|
|
15
15
|
*
|
|
16
16
|
* @param val - Object/Array to get the value from
|
|
17
17
|
* @param path - Path string to deeply get the value at
|
|
@@ -20,9 +20,10 @@
|
|
|
20
20
|
* @returns Value stored at property or undefined
|
|
21
21
|
* @throws {TypeError}
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
type ObjectType = {
|
|
24
24
|
[key: string]: any;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
}[] |
|
|
25
|
+
};
|
|
26
|
+
type ArrayType = any[];
|
|
27
|
+
type DeepGetResult<T extends ObjectType | ArrayType, P extends string> = P extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? T[Key] extends ObjectType | ArrayType ? DeepGetResult<T[Key], Rest> : undefined : T extends ArrayType ? number extends keyof T ? DeepGetResult<T[number], Rest> : undefined : undefined : P extends `${infer Key}[${infer Index}]` ? Key extends keyof T ? T[Key] extends ArrayType ? Index extends `${number}` ? DeepGetResult<T[Key][number], ''> : undefined : undefined : T extends ArrayType ? number extends keyof T ? DeepGetResult<T[number], `[${Index}]`> : undefined : undefined : P extends keyof T ? T[P] : T extends ArrayType ? number extends keyof T ? T[number] : undefined : undefined;
|
|
28
|
+
declare function deepGet<T extends ObjectType | ArrayType, P extends string>(obj: T, path: P, get_parent?: boolean): DeepGetResult<T, P> | undefined;
|
|
28
29
|
export { deepGet, deepGet as default };
|
package/deep/get.js
CHANGED
|
@@ -9,34 +9,56 @@ function deepGet(obj, path, get_parent = false) {
|
|
|
9
9
|
if (typeof path !== 'string')
|
|
10
10
|
throw new TypeError('No path was given');
|
|
11
11
|
const path_s = path.trim();
|
|
12
|
-
|
|
12
|
+
const path_len = path_s.length;
|
|
13
|
+
if (!path_len)
|
|
13
14
|
throw new TypeError('No path was given');
|
|
14
|
-
const parts =
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
const parts = [];
|
|
16
|
+
let cursor_part = '';
|
|
17
|
+
let in_bracket = false;
|
|
18
|
+
for (let i = 0; i < path_len; i++) {
|
|
19
|
+
const char = path_s[i];
|
|
20
|
+
if (char === '[' || char === ']') {
|
|
21
|
+
in_bracket = !in_bracket;
|
|
22
|
+
if (cursor_part) {
|
|
23
|
+
parts.push(cursor_part);
|
|
24
|
+
cursor_part = '';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else if (char === '.' && !in_bracket) {
|
|
28
|
+
if (cursor_part) {
|
|
29
|
+
parts.push(cursor_part);
|
|
30
|
+
cursor_part = '';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
cursor_part += char;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (cursor_part)
|
|
38
|
+
parts.push(cursor_part);
|
|
39
|
+
let len = parts.length;
|
|
40
|
+
if (!len || (len === 1 && get_parent))
|
|
20
41
|
return obj;
|
|
21
|
-
if (get_parent)
|
|
42
|
+
if (get_parent) {
|
|
22
43
|
parts.pop();
|
|
44
|
+
len -= 1;
|
|
45
|
+
}
|
|
23
46
|
let cursor = obj;
|
|
24
|
-
|
|
47
|
+
for (let i = 0; i < len; i++) {
|
|
25
48
|
if (Array.isArray(cursor)) {
|
|
26
|
-
const ix = parseInt(parts
|
|
27
|
-
if (
|
|
49
|
+
const ix = parseInt(parts[i], 10);
|
|
50
|
+
if (ix < 0 || ix > cursor.length - 1)
|
|
28
51
|
return undefined;
|
|
29
52
|
cursor = cursor[ix];
|
|
30
53
|
}
|
|
31
54
|
else if (Object.prototype.toString.call(cursor) === '[object Object]') {
|
|
32
|
-
|
|
33
|
-
if (cursor
|
|
55
|
+
cursor = cursor[parts[i]];
|
|
56
|
+
if (cursor === undefined)
|
|
34
57
|
return undefined;
|
|
35
|
-
cursor = cursor[key];
|
|
36
58
|
}
|
|
37
|
-
|
|
38
|
-
parts.length)
|
|
59
|
+
else {
|
|
39
60
|
return undefined;
|
|
61
|
+
}
|
|
40
62
|
}
|
|
41
63
|
return cursor;
|
|
42
64
|
}
|
package/deep/seal.js
CHANGED
package/equal.js
CHANGED
|
@@ -4,9 +4,10 @@ exports.equal = equal;
|
|
|
4
4
|
exports.default = equal;
|
|
5
5
|
const isNumericalNaN_1 = require("./number/isNumericalNaN");
|
|
6
6
|
function isArrayEqual(a, b) {
|
|
7
|
-
|
|
7
|
+
const a_len = a.length;
|
|
8
|
+
if (a_len !== b.length)
|
|
8
9
|
return false;
|
|
9
|
-
for (let i =
|
|
10
|
+
for (let i = a_len - 1; i >= 0; i--) {
|
|
10
11
|
if (equal(a[i], b[i]))
|
|
11
12
|
continue;
|
|
12
13
|
return false;
|
|
@@ -15,9 +16,10 @@ function isArrayEqual(a, b) {
|
|
|
15
16
|
}
|
|
16
17
|
function isObjectEqual(a, b) {
|
|
17
18
|
const keys_a = Object.keys(a);
|
|
18
|
-
|
|
19
|
+
const keys_a_len = keys_a.length;
|
|
20
|
+
if (keys_a_len !== Object.keys(b).length)
|
|
19
21
|
return false;
|
|
20
|
-
for (let i =
|
|
22
|
+
for (let i = keys_a_len - 1; i >= 0; i--) {
|
|
21
23
|
if (equal(a[keys_a[i]], b[keys_a[i]]))
|
|
22
24
|
continue;
|
|
23
25
|
return false;
|
package/index.d.ts
CHANGED
|
@@ -272,35 +272,29 @@ declare module "object/define" {
|
|
|
272
272
|
export { define, define as default };
|
|
273
273
|
}
|
|
274
274
|
declare module "object/merge" {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}, source?: {
|
|
278
|
-
[key: string]: any;
|
|
279
|
-
}): {
|
|
280
|
-
[key: string]: any;
|
|
275
|
+
type MergeOptions = {
|
|
276
|
+
union?: boolean;
|
|
281
277
|
};
|
|
278
|
+
function merge(target: Record<string, any>, source?: Record<string, any> | Record<string, any>[], opts?: MergeOptions): Record<string, any>;
|
|
282
279
|
export { merge, merge as default };
|
|
283
280
|
}
|
|
284
281
|
declare module "deep/get" {
|
|
285
|
-
|
|
286
|
-
[key: string]: any;
|
|
287
|
-
} | {
|
|
282
|
+
type ObjectType = {
|
|
288
283
|
[key: string]: any;
|
|
289
|
-
}
|
|
284
|
+
};
|
|
285
|
+
type ArrayType = any[];
|
|
286
|
+
type DeepGetResult<T extends ObjectType | ArrayType, P extends string> = P extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? T[Key] extends ObjectType | ArrayType ? DeepGetResult<T[Key], Rest> : undefined : T extends ArrayType ? number extends keyof T ? DeepGetResult<T[number], Rest> : undefined : undefined : P extends `${infer Key}[${infer Index}]` ? Key extends keyof T ? T[Key] extends ArrayType ? Index extends `${number}` ? DeepGetResult<T[Key][number], ''> : undefined : undefined : T extends ArrayType ? number extends keyof T ? DeepGetResult<T[number], `[${Index}]`> : undefined : undefined : P extends keyof T ? T[P] : T extends ArrayType ? number extends keyof T ? T[number] : undefined : undefined;
|
|
287
|
+
function deepGet<T extends ObjectType | ArrayType, P extends string>(obj: T, path: P, get_parent?: boolean): DeepGetResult<T, P> | undefined;
|
|
290
288
|
export { deepGet, deepGet as default };
|
|
291
289
|
}
|
|
292
|
-
declare module "deep/set" {
|
|
293
|
-
function deepSet(obj: {
|
|
294
|
-
[key: string]: any;
|
|
295
|
-
} | {
|
|
296
|
-
[key: string]: any;
|
|
297
|
-
}[] | any[], path: string, value: any, define?: boolean): boolean;
|
|
298
|
-
export { deepSet, deepSet as default };
|
|
299
|
-
}
|
|
300
290
|
declare module "object/pick" {
|
|
301
|
-
|
|
291
|
+
type ObjectType = {
|
|
302
292
|
[key: string]: any;
|
|
303
|
-
}
|
|
293
|
+
};
|
|
294
|
+
type DottedKeys<T> = (T extends ObjectType ? {
|
|
295
|
+
[K in keyof T & string]: T[K] extends ObjectType ? K | `${K}.${DottedKeys<T[K]>}` : K;
|
|
296
|
+
}[keyof T & string] : string) & string;
|
|
297
|
+
function pick<T extends Record<string, any>, K extends DottedKeys<T>>(obj: T, keys: K[]): {
|
|
304
298
|
[key: string]: any;
|
|
305
299
|
};
|
|
306
300
|
export { pick, pick as default };
|
|
@@ -525,6 +519,14 @@ declare module "deep/seal" {
|
|
|
525
519
|
function deepSeal<T extends deepInput>(obj: T): Sealed<T>;
|
|
526
520
|
export { deepSeal, deepSeal as default };
|
|
527
521
|
}
|
|
522
|
+
declare module "deep/set" {
|
|
523
|
+
function deepSet(obj: {
|
|
524
|
+
[key: string]: any;
|
|
525
|
+
} | {
|
|
526
|
+
[key: string]: any;
|
|
527
|
+
}[] | any[], path: string, value: any, define?: boolean): boolean;
|
|
528
|
+
export { deepSet, deepSet as default };
|
|
529
|
+
}
|
|
528
530
|
declare module "deep/index" {
|
|
529
531
|
import { deepFreeze } from "deep/freeze";
|
|
530
532
|
import { deepGet } from "deep/get";
|
package/object/merge.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
type MergeOptions = {
|
|
2
|
+
/**
|
|
3
|
+
* Defaults to false, when passed as true it ensures all keys from both objects
|
|
4
|
+
* are available in the merged object
|
|
5
|
+
*/
|
|
6
|
+
union?: boolean;
|
|
7
|
+
};
|
|
1
8
|
/**
|
|
2
9
|
* Deep merge two objects together while ensuring nested objects also get merged,
|
|
3
10
|
* take note: this does not merge onto passed objects by reference but instead
|
|
@@ -8,11 +15,5 @@
|
|
|
8
15
|
*
|
|
9
16
|
* @returns Combined target and source objects
|
|
10
17
|
*/
|
|
11
|
-
declare function merge(target:
|
|
12
|
-
[key: string]: any;
|
|
13
|
-
}, source?: {
|
|
14
|
-
[key: string]: any;
|
|
15
|
-
}): {
|
|
16
|
-
[key: string]: any;
|
|
17
|
-
};
|
|
18
|
+
declare function merge(target: Record<string, any>, source?: Record<string, any> | Record<string, any>[], opts?: MergeOptions): Record<string, any>;
|
|
18
19
|
export { merge, merge as default };
|
package/object/merge.js
CHANGED
|
@@ -3,19 +3,33 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.merge = merge;
|
|
4
4
|
exports.default = merge;
|
|
5
5
|
const PROTO_OBJ = '[object Object]';
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
acc[key] = merge(target[key], source[key]);
|
|
6
|
+
function innerMerge(target, source, UNION) {
|
|
7
|
+
const origin = UNION ? source : target;
|
|
8
|
+
for (const key in origin) {
|
|
9
|
+
const t_key = target[key];
|
|
10
|
+
const s_key = source[key];
|
|
11
|
+
if (Object.prototype.toString.call(t_key) === PROTO_OBJ &&
|
|
12
|
+
Object.prototype.toString.call(s_key) === PROTO_OBJ) {
|
|
13
|
+
target[key] = innerMerge({ ...t_key }, s_key, UNION);
|
|
15
14
|
}
|
|
16
15
|
else {
|
|
17
|
-
|
|
16
|
+
target[key] = s_key !== undefined ? s_key : t_key;
|
|
18
17
|
}
|
|
19
18
|
}
|
|
19
|
+
return target;
|
|
20
|
+
}
|
|
21
|
+
function merge(target, source = {}, opts = {}) {
|
|
22
|
+
if (Object.prototype.toString.call(target) !== PROTO_OBJ)
|
|
23
|
+
throw new Error('object/merge: Please ensure valid target/source is passed');
|
|
24
|
+
const union = opts?.union === true;
|
|
25
|
+
const sources = Array.isArray(source) ? source : [source];
|
|
26
|
+
let acc = { ...target };
|
|
27
|
+
for (let i = 0; i < sources.length; i++) {
|
|
28
|
+
const el = sources[i];
|
|
29
|
+
if (Object.prototype.toString.call(el) !== PROTO_OBJ) {
|
|
30
|
+
throw new Error('object/merge: Please ensure valid target/source is passed');
|
|
31
|
+
}
|
|
32
|
+
acc = innerMerge(acc, el, union);
|
|
33
|
+
}
|
|
20
34
|
return acc;
|
|
21
35
|
}
|
package/object/pick.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
type ObjectType = {
|
|
2
|
+
[key: string]: any;
|
|
3
|
+
};
|
|
4
|
+
type DottedKeys<T> = (T extends ObjectType ? {
|
|
5
|
+
[K in keyof T & string]: T[K] extends ObjectType ? K | `${K}.${DottedKeys<T[K]>}` : K;
|
|
6
|
+
}[keyof T & string] : string) & string;
|
|
1
7
|
/**
|
|
2
8
|
* Returns a new object with the keys picked from the passed object
|
|
3
9
|
*
|
|
@@ -6,9 +12,7 @@
|
|
|
6
12
|
*
|
|
7
13
|
* @returns Object containing the picked keys from source object
|
|
8
14
|
*/
|
|
9
|
-
declare function pick(obj: {
|
|
10
|
-
[key: string]: any;
|
|
11
|
-
}, keys: string[]): {
|
|
15
|
+
declare function pick<T extends Record<string, any>, K extends DottedKeys<T>>(obj: T, keys: K[]): {
|
|
12
16
|
[key: string]: any;
|
|
13
17
|
};
|
|
14
18
|
export { pick, pick as default };
|
package/object/pick.js
CHANGED
|
@@ -3,8 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.pick = pick;
|
|
4
4
|
exports.default = pick;
|
|
5
5
|
const get_1 = require("../deep/get");
|
|
6
|
-
const set_1 = require("../deep/set");
|
|
7
|
-
const RGX_DEEP = /(\.|\[)/;
|
|
8
6
|
function pick(obj, keys) {
|
|
9
7
|
if (Object.prototype.toString.call(obj) !== '[object Object]' ||
|
|
10
8
|
!Array.isArray(keys) ||
|
|
@@ -20,11 +18,21 @@ function pick(obj, keys) {
|
|
|
20
18
|
sanitized = key.trim();
|
|
21
19
|
if (!sanitized.length)
|
|
22
20
|
continue;
|
|
23
|
-
if (
|
|
21
|
+
if (sanitized.includes('.')) {
|
|
24
22
|
val = (0, get_1.deepGet)(obj, sanitized);
|
|
25
23
|
if (val === undefined)
|
|
26
24
|
continue;
|
|
27
|
-
|
|
25
|
+
const parts = key.split('.');
|
|
26
|
+
const parts_len = parts.length;
|
|
27
|
+
let cursor = map;
|
|
28
|
+
for (let y = 0; y < parts_len - 1; y++) {
|
|
29
|
+
const part = parts[y].trim();
|
|
30
|
+
if (!cursor[part]) {
|
|
31
|
+
cursor[part] = {};
|
|
32
|
+
}
|
|
33
|
+
cursor = cursor[part];
|
|
34
|
+
}
|
|
35
|
+
cursor[parts[parts_len - 1].trim()] = val;
|
|
28
36
|
}
|
|
29
37
|
else if (obj[sanitized] !== undefined) {
|
|
30
38
|
map[sanitized] = obj[sanitized];
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "name": "@valkyriestudios/utils", "version": "12.
|
|
1
|
+
{ "name": "@valkyriestudios/utils", "version": "12.19.0", "description": "A collection of single-function utilities for common tasks", "author": { "name": "Peter Vermeulen", "url": "https://www.linkedin.com/in/petervermeulen1/" }, "keywords": [ "utility", "library", "javascript", "js", "node", "bun" ], "license": "MIT", "repository": { "type": "git", "url": "git+https://github.com/ValkyrieStudios/utils.git" }, "bugs": { "url": "https://github.com/ValkyrieStudios/utils/issues" }, "homepage": "https://github.com/ValkyrieStudios/utils#readme", "types": "index.d.ts" }
|