@valkyriestudios/utils 12.17.2 → 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 +14 -3
- package/array/dedupe.d.ts +3 -0
- package/array/dedupe.js +40 -22
- package/array/groupBy.js +4 -3
- package/array/mapKey.js +8 -5
- package/array/sort.js +18 -13
- 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/function/debounce.d.ts +25 -0
- package/function/debounce.js +42 -0
- package/function/index.d.ts +2 -1
- package/function/index.js +3 -1
- package/index.d.ts +46 -36
- 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/string/shorten.d.ts +5 -4
- package/string/shorten.js +14 -2
package/README.md
CHANGED
|
@@ -633,6 +633,9 @@ equal(new RegExp(/ab+c/, 'i'), /ab+c/i); // TRUE
|
|
|
633
633
|
```
|
|
634
634
|
|
|
635
635
|
### function
|
|
636
|
+
- **debounce(val:Fn, wait:number)**
|
|
637
|
+
Wrap a function in a debounce proxy that waits for X uninterrupted milliseconds before running callback function
|
|
638
|
+
|
|
636
639
|
- **isFunction(val:unknown)**
|
|
637
640
|
Check if a variable is a Function
|
|
638
641
|
|
|
@@ -848,12 +851,17 @@ Copies the keys passed in the 'keys' array from the passed object to a new objec
|
|
|
848
851
|
pick({a: 1, b: 2, c: 3}, ['a','b']); // {a: 1, b: 2}
|
|
849
852
|
```
|
|
850
853
|
|
|
851
|
-
- **merge(target:Object={},obj:Object={})**
|
|
854
|
+
- **merge(target:Object={},obj:Object|Object[]={}, opts?:{union?:boolean})**
|
|
852
855
|
Merges two objects together, with the preference over the second object.
|
|
853
856
|
```typescript
|
|
854
|
-
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'}}
|
|
855
860
|
```
|
|
856
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
|
+
|
|
857
865
|
- **define(props:Object, obj:Object={})**
|
|
858
866
|
Creates an object with the passed accessors set on it
|
|
859
867
|
```typescript
|
|
@@ -923,13 +931,16 @@ isNotEmptyString(' ', false); // TRUE
|
|
|
923
931
|
isNotEmptyString('Hi'); // TRUE
|
|
924
932
|
```
|
|
925
933
|
|
|
926
|
-
- **shorten(val:any, length:integer, postfix:string
|
|
934
|
+
- **shorten(val:any, length:integer, postfix:string=..., truncate_words=true)**
|
|
927
935
|
Shorten a string and add a postfix if string went over length
|
|
928
936
|
```typescript
|
|
929
937
|
shorten('To the moon and beyond', 11, '..'); // 'To the moon..'
|
|
930
938
|
shorten('Hi', 250); // 'Hi'
|
|
931
939
|
shorten('To the moon and beyond'); // 'To the moon...'
|
|
932
940
|
shorten('To the moon and beyond', 11, ' '); // 'To the moon '
|
|
941
|
+
|
|
942
|
+
/* For when you don't want words to be truncated mid-word */
|
|
943
|
+
shorten('To the moon and beyond', 11, '...', false);
|
|
933
944
|
```
|
|
934
945
|
|
|
935
946
|
- **humanizeBytes(val:number|string)**
|
package/array/dedupe.d.ts
CHANGED
package/array/dedupe.js
CHANGED
|
@@ -2,35 +2,53 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.dedupe = dedupe;
|
|
4
4
|
exports.default = dedupe;
|
|
5
|
-
const
|
|
5
|
+
const REPL_NAN = 'nan';
|
|
6
|
+
const REPL_TRUE = 'true';
|
|
7
|
+
const REPL_FALSE = 'false';
|
|
8
|
+
const REPL_UNDEF = 'undefined';
|
|
9
|
+
const REPL_NULL = 'null';
|
|
10
|
+
function getTypeString(el) {
|
|
11
|
+
switch (typeof el) {
|
|
12
|
+
case 'string':
|
|
13
|
+
return el;
|
|
14
|
+
case 'number':
|
|
15
|
+
return Number.isNaN(el) || !Number.isFinite(el) ? REPL_NAN : String(el);
|
|
16
|
+
case 'boolean':
|
|
17
|
+
return el ? REPL_TRUE : REPL_FALSE;
|
|
18
|
+
case 'undefined':
|
|
19
|
+
return REPL_UNDEF;
|
|
20
|
+
case 'object':
|
|
21
|
+
if (el === null) {
|
|
22
|
+
return REPL_NULL;
|
|
23
|
+
}
|
|
24
|
+
else if (Array.isArray(el) || el.toString() === '[object Object]') {
|
|
25
|
+
return JSON.stringify(el);
|
|
26
|
+
}
|
|
27
|
+
else if (el instanceof RegExp) {
|
|
28
|
+
return el.toString();
|
|
29
|
+
}
|
|
30
|
+
else if (el instanceof Date) {
|
|
31
|
+
return String(el.getTime());
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
6
36
|
function dedupe(val, opts) {
|
|
7
37
|
if (!Array.isArray(val))
|
|
8
38
|
return [];
|
|
9
|
-
const FILTER_FN =
|
|
39
|
+
const FILTER_FN = opts?.filter_fn;
|
|
10
40
|
const set = new Set();
|
|
11
41
|
const acc = [];
|
|
12
42
|
let hash;
|
|
13
43
|
const len = val.length;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
acc.push(el);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
for (let i = 0; i < len; i++) {
|
|
28
|
-
const el = val[i];
|
|
29
|
-
hash = (0, fnv1A_1.fnv1A)(el);
|
|
30
|
-
if (!set.has(hash)) {
|
|
31
|
-
set.add(hash);
|
|
32
|
-
acc.push(el);
|
|
33
|
-
}
|
|
44
|
+
for (let i = 0; i < len; i++) {
|
|
45
|
+
const el = val[i];
|
|
46
|
+
if (FILTER_FN && !FILTER_FN(el))
|
|
47
|
+
continue;
|
|
48
|
+
hash = getTypeString(el);
|
|
49
|
+
if (!set.has(hash)) {
|
|
50
|
+
set.add(hash);
|
|
51
|
+
acc.push(el);
|
|
34
52
|
}
|
|
35
53
|
}
|
|
36
54
|
return acc;
|
package/array/groupBy.js
CHANGED
|
@@ -23,11 +23,12 @@ function groupBy(arr, handler) {
|
|
|
23
23
|
key = n_handler(el);
|
|
24
24
|
if (key === undefined || (typeof key === 'string' && !key.length))
|
|
25
25
|
key = FALLBACK;
|
|
26
|
-
if (
|
|
26
|
+
if (!acc[key]) {
|
|
27
|
+
acc[key] = [el];
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
27
30
|
acc[key].push(el);
|
|
28
|
-
continue;
|
|
29
31
|
}
|
|
30
|
-
acc[key] = [el];
|
|
31
32
|
}
|
|
32
33
|
return acc;
|
|
33
34
|
}
|
package/array/mapKey.js
CHANGED
|
@@ -3,19 +3,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.mapKey = mapKey;
|
|
4
4
|
exports.default = mapKey;
|
|
5
5
|
function mapKey(arr, key, opts) {
|
|
6
|
-
if (
|
|
7
|
-
typeof key !== 'string')
|
|
6
|
+
if (!Array.isArray(arr) || typeof key !== 'string')
|
|
8
7
|
return {};
|
|
9
8
|
const key_s = key.trim();
|
|
10
9
|
if (!key_s.length)
|
|
11
10
|
return {};
|
|
11
|
+
const len = arr.length;
|
|
12
|
+
if (!len)
|
|
13
|
+
return {};
|
|
12
14
|
const MERGE = opts?.merge === true;
|
|
13
15
|
const map = {};
|
|
14
|
-
for (let i = 0; i <
|
|
16
|
+
for (let i = 0; i < len; i++) {
|
|
15
17
|
const el = arr[i];
|
|
16
|
-
|
|
18
|
+
const el_key = el?.[key_s];
|
|
19
|
+
if (el_key === undefined)
|
|
17
20
|
continue;
|
|
18
|
-
map[
|
|
21
|
+
map[el_key] = MERGE && el_key in map ? { ...map[el_key], ...el } : el;
|
|
19
22
|
}
|
|
20
23
|
return map;
|
|
21
24
|
}
|
package/array/sort.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.sort = sort;
|
|
4
4
|
exports.default = sort;
|
|
5
|
-
const
|
|
5
|
+
const is_1 = require("../object/is");
|
|
6
6
|
const INSERTION_SORT_THRESHOLD = 10;
|
|
7
7
|
function partition(arr, low, high) {
|
|
8
8
|
const pivot = arr[(low + high) >> 1][0];
|
|
@@ -24,9 +24,9 @@ function partition(arr, low, high) {
|
|
|
24
24
|
return i;
|
|
25
25
|
}
|
|
26
26
|
function quickSort(arr) {
|
|
27
|
-
const stack = [
|
|
27
|
+
const stack = [[0, arr.length - 1]];
|
|
28
28
|
while (stack.length) {
|
|
29
|
-
const
|
|
29
|
+
const [low, high] = stack.pop();
|
|
30
30
|
if (high - low <= INSERTION_SORT_THRESHOLD) {
|
|
31
31
|
for (let i = low + 1; i <= high; i++) {
|
|
32
32
|
const key = arr[i];
|
|
@@ -41,22 +41,24 @@ function quickSort(arr) {
|
|
|
41
41
|
else {
|
|
42
42
|
const p = partition(arr, low, high);
|
|
43
43
|
if (p - 1 > low)
|
|
44
|
-
stack.push(
|
|
44
|
+
stack.push([low, p - 1]);
|
|
45
45
|
if (p < high)
|
|
46
|
-
stack.push(
|
|
46
|
+
stack.push([p, high]);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
return arr;
|
|
50
49
|
}
|
|
51
50
|
function sort(arr, by, dir = 'asc', opts) {
|
|
52
|
-
if (!Array.isArray(arr)
|
|
51
|
+
if (!Array.isArray(arr))
|
|
52
|
+
return [];
|
|
53
|
+
const len = arr.length;
|
|
54
|
+
if (!len)
|
|
53
55
|
return [];
|
|
54
56
|
const NOKEY_HIDE = opts?.nokey_hide === true;
|
|
55
57
|
const NOKEY_AT_END = opts?.nokey_atend !== false;
|
|
56
|
-
let FILTER_FN =
|
|
58
|
+
let FILTER_FN = is_1.isObject;
|
|
57
59
|
if (typeof opts?.filter_fn === 'function') {
|
|
58
60
|
const fn = opts.filter_fn;
|
|
59
|
-
FILTER_FN = (el => (0,
|
|
61
|
+
FILTER_FN = (el => (0, is_1.isObject)(el) && fn(el));
|
|
60
62
|
}
|
|
61
63
|
const prepared_arr = [];
|
|
62
64
|
const nokey_arr = [];
|
|
@@ -64,19 +66,22 @@ function sort(arr, by, dir = 'asc', opts) {
|
|
|
64
66
|
const by_s = by.trim();
|
|
65
67
|
if (!by_s.length)
|
|
66
68
|
throw new Error('Sort by as string should contain content');
|
|
67
|
-
for (
|
|
69
|
+
for (let i = 0; i < len; i++) {
|
|
70
|
+
const el = arr[i];
|
|
68
71
|
if (!FILTER_FN(el))
|
|
69
72
|
continue;
|
|
70
|
-
|
|
73
|
+
const key = el?.[by_s];
|
|
74
|
+
if (key === undefined) {
|
|
71
75
|
nokey_arr.push(el);
|
|
72
76
|
}
|
|
73
77
|
else {
|
|
74
|
-
prepared_arr.push([
|
|
78
|
+
prepared_arr.push([key, el]);
|
|
75
79
|
}
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
else if (typeof by === 'function') {
|
|
79
|
-
for (
|
|
83
|
+
for (let i = 0; i < len; i++) {
|
|
84
|
+
const el = arr[i];
|
|
80
85
|
if (!FILTER_FN(el))
|
|
81
86
|
continue;
|
|
82
87
|
const key = by(el);
|
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;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debounce a function
|
|
3
|
+
*
|
|
4
|
+
* Take Note, the debounced function also contains a "cancel" and "flush" method
|
|
5
|
+
* "cancel": Allows clearing the timeout
|
|
6
|
+
* "flush": Allows immediately executing the debounced function if pending
|
|
7
|
+
*
|
|
8
|
+
* Example Usage:
|
|
9
|
+
*
|
|
10
|
+
* const log = (message: string) => console.log(message);
|
|
11
|
+
*
|
|
12
|
+
* const debouncedLog = debounce(log, 2000);
|
|
13
|
+
*
|
|
14
|
+
* debouncedLog("Hello, World!");
|
|
15
|
+
* debouncedLog.cancel();
|
|
16
|
+
* debouncedLog.flush();
|
|
17
|
+
*
|
|
18
|
+
* @param {Function} fn - Function to debounce
|
|
19
|
+
* @param {number} wait - Amount of time to debounce the function for
|
|
20
|
+
*/
|
|
21
|
+
declare function debounce<T extends (...args: any[]) => any>(fn: T, wait: number): T & {
|
|
22
|
+
cancel: () => void;
|
|
23
|
+
flush: () => void;
|
|
24
|
+
};
|
|
25
|
+
export { debounce, debounce as default };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.debounce = debounce;
|
|
4
|
+
exports.default = debounce;
|
|
5
|
+
const is_1 = require("./is");
|
|
6
|
+
const isIntegerAbove_1 = require("../number/isIntegerAbove");
|
|
7
|
+
function debounce(fn, wait) {
|
|
8
|
+
if (!(0, is_1.isFunction)(fn))
|
|
9
|
+
throw new Error('functions/debounce: Expected a function');
|
|
10
|
+
if (!(0, isIntegerAbove_1.isIntegerAbove)(wait, 0))
|
|
11
|
+
throw new Error('functions/debounce: Wait should be an integer above 0');
|
|
12
|
+
let timeout;
|
|
13
|
+
let self;
|
|
14
|
+
let current_args;
|
|
15
|
+
let current_rslt;
|
|
16
|
+
const clear = () => {
|
|
17
|
+
if (!timeout)
|
|
18
|
+
return;
|
|
19
|
+
clearTimeout(timeout);
|
|
20
|
+
timeout = null;
|
|
21
|
+
};
|
|
22
|
+
const flush = () => {
|
|
23
|
+
if (!timeout)
|
|
24
|
+
return;
|
|
25
|
+
current_rslt = fn.apply(self, current_args);
|
|
26
|
+
clearTimeout(timeout);
|
|
27
|
+
timeout = null;
|
|
28
|
+
};
|
|
29
|
+
const debouncedFn = function (...args) {
|
|
30
|
+
self = this;
|
|
31
|
+
current_args = args;
|
|
32
|
+
clear();
|
|
33
|
+
timeout = setTimeout(() => {
|
|
34
|
+
timeout = null;
|
|
35
|
+
current_rslt = fn.apply(self, current_args);
|
|
36
|
+
}, wait);
|
|
37
|
+
return current_rslt;
|
|
38
|
+
};
|
|
39
|
+
debouncedFn.cancel = clear;
|
|
40
|
+
debouncedFn.flush = flush;
|
|
41
|
+
return debouncedFn;
|
|
42
|
+
}
|
package/function/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { debounce } from './debounce';
|
|
1
2
|
import { isFunction } from './is';
|
|
2
3
|
import { isAsyncFunction } from './isAsync';
|
|
3
4
|
import { noop } from './noop';
|
|
4
5
|
import { noopresolve } from './noopresolve';
|
|
5
6
|
import { noopreturn } from './noopreturn';
|
|
6
7
|
import { sleep } from './sleep';
|
|
7
|
-
export { isFunction, isFunction as is, isFunction as isFn, isAsyncFunction, isAsyncFunction as isAsync, isAsyncFunction as isAsyncFn, noop, noopresolve, noopreturn, sleep };
|
|
8
|
+
export { debounce, isFunction, isFunction as is, isFunction as isFn, isAsyncFunction, isAsyncFunction as isAsync, isAsyncFunction as isAsyncFn, noop, noopresolve, noopreturn, sleep };
|
package/function/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.sleep = exports.noopreturn = exports.noopresolve = exports.noop = exports.isAsyncFn = exports.isAsync = exports.isAsyncFunction = exports.isFn = exports.is = exports.isFunction = void 0;
|
|
3
|
+
exports.sleep = exports.noopreturn = exports.noopresolve = exports.noop = exports.isAsyncFn = exports.isAsync = exports.isAsyncFunction = exports.isFn = exports.is = exports.isFunction = exports.debounce = void 0;
|
|
4
|
+
const debounce_1 = require("./debounce");
|
|
5
|
+
Object.defineProperty(exports, "debounce", { enumerable: true, get: function () { return debounce_1.debounce; } });
|
|
4
6
|
const is_1 = require("./is");
|
|
5
7
|
Object.defineProperty(exports, "isFunction", { enumerable: true, get: function () { return is_1.isFunction; } });
|
|
6
8
|
Object.defineProperty(exports, "is", { enumerable: true, get: function () { return is_1.isFunction; } });
|
package/index.d.ts
CHANGED
|
@@ -6,10 +6,6 @@ declare module "equal" {
|
|
|
6
6
|
function equal(a: any, b: any): boolean;
|
|
7
7
|
export { equal, equal as default };
|
|
8
8
|
}
|
|
9
|
-
declare module "hash/fnv1A" {
|
|
10
|
-
function fnv1A(data: unknown, offset?: number): number;
|
|
11
|
-
export { fnv1A, fnv1A as default };
|
|
12
|
-
}
|
|
13
9
|
declare module "array/dedupe" {
|
|
14
10
|
type DedupeOptions<T> = {
|
|
15
11
|
filter_fn?: (el: T) => boolean;
|
|
@@ -91,6 +87,12 @@ declare module "array/split" {
|
|
|
91
87
|
function split<T>(arr: T[], size: number, opts?: SplitOptions<T>): T[][];
|
|
92
88
|
export { split, split as default };
|
|
93
89
|
}
|
|
90
|
+
declare module "object/is" {
|
|
91
|
+
function isObject(val: unknown): val is {
|
|
92
|
+
[key: string]: any;
|
|
93
|
+
};
|
|
94
|
+
export { isObject, isObject as default };
|
|
95
|
+
}
|
|
94
96
|
declare module "array/sort" {
|
|
95
97
|
type sortOptions<T> = {
|
|
96
98
|
filter_fn?: (el: T) => boolean;
|
|
@@ -205,6 +207,17 @@ declare module "function/is" {
|
|
|
205
207
|
function isFunction(val: unknown): val is (...args: unknown[]) => unknown;
|
|
206
208
|
export { isFunction, isFunction as default };
|
|
207
209
|
}
|
|
210
|
+
declare module "number/isIntegerAbove" {
|
|
211
|
+
function isIntegerAbove(val: unknown, ref: number): val is number;
|
|
212
|
+
export { isIntegerAbove, isIntegerAbove as default };
|
|
213
|
+
}
|
|
214
|
+
declare module "function/debounce" {
|
|
215
|
+
function debounce<T extends (...args: any[]) => any>(fn: T, wait: number): T & {
|
|
216
|
+
cancel: () => void;
|
|
217
|
+
flush: () => void;
|
|
218
|
+
};
|
|
219
|
+
export { debounce, debounce as default };
|
|
220
|
+
}
|
|
208
221
|
declare module "function/isAsync" {
|
|
209
222
|
function isAsyncFunction(val: unknown): val is (...args: unknown[]) => Promise<unknown>;
|
|
210
223
|
export { isAsyncFunction, isAsyncFunction as default };
|
|
@@ -226,13 +239,14 @@ declare module "function/sleep" {
|
|
|
226
239
|
export { sleep, sleep as default };
|
|
227
240
|
}
|
|
228
241
|
declare module "function/index" {
|
|
242
|
+
import { debounce } from "function/debounce";
|
|
229
243
|
import { isFunction } from "function/is";
|
|
230
244
|
import { isAsyncFunction } from "function/isAsync";
|
|
231
245
|
import { noop } from "function/noop";
|
|
232
246
|
import { noopresolve } from "function/noopresolve";
|
|
233
247
|
import { noopreturn } from "function/noopreturn";
|
|
234
248
|
import { sleep } from "function/sleep";
|
|
235
|
-
export { isFunction, isFunction as is, isFunction as isFn, isAsyncFunction, isAsyncFunction as isAsync, isAsyncFunction as isAsyncFn, noop, noopresolve, noopreturn, sleep };
|
|
249
|
+
export { debounce, isFunction, isFunction as is, isFunction as isFn, isAsyncFunction, isAsyncFunction as isAsync, isAsyncFunction as isAsyncFn, noop, noopresolve, noopreturn, sleep };
|
|
236
250
|
}
|
|
237
251
|
declare module "regexp/is" {
|
|
238
252
|
function isRegExp(val: unknown): val is RegExp;
|
|
@@ -257,42 +271,30 @@ declare module "object/define" {
|
|
|
257
271
|
};
|
|
258
272
|
export { define, define as default };
|
|
259
273
|
}
|
|
260
|
-
declare module "object/is" {
|
|
261
|
-
function isObject(val: unknown): val is {
|
|
262
|
-
[key: string]: any;
|
|
263
|
-
};
|
|
264
|
-
export { isObject, isObject as default };
|
|
265
|
-
}
|
|
266
274
|
declare module "object/merge" {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}, source?: {
|
|
270
|
-
[key: string]: any;
|
|
271
|
-
}): {
|
|
272
|
-
[key: string]: any;
|
|
275
|
+
type MergeOptions = {
|
|
276
|
+
union?: boolean;
|
|
273
277
|
};
|
|
278
|
+
function merge(target: Record<string, any>, source?: Record<string, any> | Record<string, any>[], opts?: MergeOptions): Record<string, any>;
|
|
274
279
|
export { merge, merge as default };
|
|
275
280
|
}
|
|
276
281
|
declare module "deep/get" {
|
|
277
|
-
|
|
278
|
-
[key: string]: any;
|
|
279
|
-
} | {
|
|
282
|
+
type ObjectType = {
|
|
280
283
|
[key: string]: any;
|
|
281
|
-
}
|
|
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;
|
|
282
288
|
export { deepGet, deepGet as default };
|
|
283
289
|
}
|
|
284
|
-
declare module "deep/set" {
|
|
285
|
-
function deepSet(obj: {
|
|
286
|
-
[key: string]: any;
|
|
287
|
-
} | {
|
|
288
|
-
[key: string]: any;
|
|
289
|
-
}[] | any[], path: string, value: any, define?: boolean): boolean;
|
|
290
|
-
export { deepSet, deepSet as default };
|
|
291
|
-
}
|
|
292
290
|
declare module "object/pick" {
|
|
293
|
-
|
|
291
|
+
type ObjectType = {
|
|
294
292
|
[key: string]: any;
|
|
295
|
-
}
|
|
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[]): {
|
|
296
298
|
[key: string]: any;
|
|
297
299
|
};
|
|
298
300
|
export { pick, pick as default };
|
|
@@ -333,10 +335,6 @@ declare module "number/isInteger" {
|
|
|
333
335
|
function isInteger(val: unknown): val is number;
|
|
334
336
|
export { isInteger, isInteger as default };
|
|
335
337
|
}
|
|
336
|
-
declare module "number/isIntegerAbove" {
|
|
337
|
-
function isIntegerAbove(val: unknown, ref: number): val is number;
|
|
338
|
-
export { isIntegerAbove, isIntegerAbove as default };
|
|
339
|
-
}
|
|
340
338
|
declare module "number/isIntegerBelow" {
|
|
341
339
|
function isIntegerBelow(val: unknown, ref: number): val is number;
|
|
342
340
|
export { isIntegerBelow, isIntegerBelow as default };
|
|
@@ -412,7 +410,7 @@ declare module "string/isBetween" {
|
|
|
412
410
|
export { isStringBetween, isStringBetween as default };
|
|
413
411
|
}
|
|
414
412
|
declare module "string/shorten" {
|
|
415
|
-
function shorten(val: string, length: number, postfix?: string): string;
|
|
413
|
+
function shorten(val: string, length: number, postfix?: string, truncate_words?: boolean): string;
|
|
416
414
|
export { shorten, shorten as default };
|
|
417
415
|
}
|
|
418
416
|
declare module "string/index" {
|
|
@@ -521,6 +519,14 @@ declare module "deep/seal" {
|
|
|
521
519
|
function deepSeal<T extends deepInput>(obj: T): Sealed<T>;
|
|
522
520
|
export { deepSeal, deepSeal as default };
|
|
523
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
|
+
}
|
|
524
530
|
declare module "deep/index" {
|
|
525
531
|
import { deepFreeze } from "deep/freeze";
|
|
526
532
|
import { deepGet } from "deep/get";
|
|
@@ -528,6 +534,10 @@ declare module "deep/index" {
|
|
|
528
534
|
import { deepSet } from "deep/set";
|
|
529
535
|
export { deepFreeze as freeze, deepFreeze, deepGet as get, deepGet, deepSeal as seal, deepSeal, deepSet as set, deepSet };
|
|
530
536
|
}
|
|
537
|
+
declare module "hash/fnv1A" {
|
|
538
|
+
function fnv1A(data: unknown, offset?: number): number;
|
|
539
|
+
export { fnv1A, fnv1A as default };
|
|
540
|
+
}
|
|
531
541
|
declare module "hash/guid" {
|
|
532
542
|
function guid(): string;
|
|
533
543
|
export { guid, guid as default };
|
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" }
|
package/string/shorten.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shorten a string and add a postfix if it goes over a specific length, will autotrim value.
|
|
3
3
|
*
|
|
4
|
-
* @param val - String value to shorten
|
|
5
|
-
* @param length - Length to shorten it to
|
|
6
|
-
* @param postfix - (default
|
|
4
|
+
* @param {string} val - String value to shorten
|
|
5
|
+
* @param {number} length - Length to shorten it to
|
|
6
|
+
* @param {string} postfix - (default:'...') Postfix to use in case the string got shortened
|
|
7
|
+
* @param {boolean?} truncate_words - (default:true) Truncate words or not
|
|
7
8
|
*
|
|
8
9
|
* @returns Shortened string
|
|
9
10
|
*/
|
|
10
|
-
declare function shorten(val: string, length: number, postfix?: string): string;
|
|
11
|
+
declare function shorten(val: string, length: number, postfix?: string, truncate_words?: boolean): string;
|
|
11
12
|
export { shorten, shorten as default };
|
package/string/shorten.js
CHANGED
|
@@ -2,11 +2,23 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.shorten = shorten;
|
|
4
4
|
exports.default = shorten;
|
|
5
|
-
function shorten(val, length, postfix = '...') {
|
|
5
|
+
function shorten(val, length, postfix = '...', truncate_words = true) {
|
|
6
6
|
if (typeof val !== 'string')
|
|
7
7
|
return '';
|
|
8
8
|
if (typeof postfix !== 'string' || !Number.isInteger(length) || length <= 0)
|
|
9
9
|
return val;
|
|
10
10
|
const sanitized = val.trim();
|
|
11
|
-
|
|
11
|
+
if (sanitized.length <= length)
|
|
12
|
+
return sanitized;
|
|
13
|
+
const truncated = sanitized.substring(0, length);
|
|
14
|
+
if (truncate_words)
|
|
15
|
+
return truncated + postfix;
|
|
16
|
+
let end = length;
|
|
17
|
+
while (end > 0 && sanitized[end] !== ' ' && sanitized[end - 1] !== ' ') {
|
|
18
|
+
end--;
|
|
19
|
+
}
|
|
20
|
+
if (end === 0) {
|
|
21
|
+
return sanitized.substring(0, length) + postfix;
|
|
22
|
+
}
|
|
23
|
+
return sanitized.substring(0, end).trim() + postfix;
|
|
12
24
|
}
|