@yaasl/utils 0.14.0 → 0.15.0-alpha.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/dist/@types/deep-compare.d.ts +1 -0
- package/dist/@types/index.d.ts +1 -0
- package/dist/@types/memoize-function.d.ts +4 -0
- package/dist/cjs/deep-compare.js +92 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/memoize-function.js +32 -0
- package/dist/esm/deep-compare.js +87 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/memoize-function.js +27 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const deepCompare: (a: unknown, b: unknown, seen?: WeakMap<object, WeakSet<object>>) => boolean;
|
package/dist/@types/index.d.ts
CHANGED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const memoizeFunction: <TArgs extends unknown[], TResult>(resultFn: (...args: TArgs) => TResult, compareResult?: (before: TResult, after: TResult) => boolean) => ((...args: TArgs) => TResult) & {
|
|
2
|
+
resultFn: (...args: TArgs) => TResult;
|
|
3
|
+
compareResult: ((before: TResult, after: TResult) => boolean) | undefined;
|
|
4
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deepCompare = void 0;
|
|
4
|
+
const isIterable = (value) => Symbol.iterator in value && typeof value[Symbol.iterator] === "function";
|
|
5
|
+
const isPureObject = (value) => value.constructor === Object;
|
|
6
|
+
const getType = (value) => {
|
|
7
|
+
if (typeof value === "object") {
|
|
8
|
+
if (value === null)
|
|
9
|
+
return "null";
|
|
10
|
+
if (isIterable(value))
|
|
11
|
+
return "iterable";
|
|
12
|
+
if (isPureObject(value))
|
|
13
|
+
return "pure-object";
|
|
14
|
+
return "class-object";
|
|
15
|
+
}
|
|
16
|
+
if (typeof value === "function") {
|
|
17
|
+
return "function";
|
|
18
|
+
}
|
|
19
|
+
return "primitive";
|
|
20
|
+
};
|
|
21
|
+
const comparePureObject = (a, b, compareValue) => {
|
|
22
|
+
const keysA = Object.keys(a);
|
|
23
|
+
const keysB = Object.keys(b);
|
|
24
|
+
if (keysA.length !== keysB.length)
|
|
25
|
+
return false;
|
|
26
|
+
return keysA.every(key => key in b &&
|
|
27
|
+
compareValue(a[key], b[key]));
|
|
28
|
+
};
|
|
29
|
+
const compareIterable = (a, b, compareValue) => {
|
|
30
|
+
try {
|
|
31
|
+
const arrA = [...a];
|
|
32
|
+
const arrB = [...b];
|
|
33
|
+
if (arrA.length !== arrB.length)
|
|
34
|
+
return false;
|
|
35
|
+
return (arrA.length === arrB.length &&
|
|
36
|
+
arrA.every((item, index) => compareValue(item, arrB[index])));
|
|
37
|
+
}
|
|
38
|
+
catch (_a) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const compareClass = (a, b) => {
|
|
43
|
+
if (a.constructor !== b.constructor)
|
|
44
|
+
return false;
|
|
45
|
+
if (a.valueOf !== Object.prototype.valueOf) {
|
|
46
|
+
return a.valueOf() === b.valueOf();
|
|
47
|
+
}
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
49
|
+
if (a.toString() !== Object.prototype.toString()) {
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
51
|
+
return a.toString() === b.toString();
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
};
|
|
55
|
+
const hasBeenSeen = (a, b, seen) => {
|
|
56
|
+
var _a;
|
|
57
|
+
if (typeof a !== "object" || typeof b !== "object" || a == null || b == null)
|
|
58
|
+
return false;
|
|
59
|
+
const seenPairs = (_a = seen.get(a)) !== null && _a !== void 0 ? _a : new WeakSet();
|
|
60
|
+
if (seenPairs.has(b))
|
|
61
|
+
return true;
|
|
62
|
+
seenPairs.add(b);
|
|
63
|
+
seen.set(a, seenPairs);
|
|
64
|
+
return false;
|
|
65
|
+
};
|
|
66
|
+
const deepCompare = (a, b, seen = new WeakMap()
|
|
67
|
+
// eslint-disable-next-line complexity
|
|
68
|
+
) => {
|
|
69
|
+
if (a === b)
|
|
70
|
+
return true;
|
|
71
|
+
const typeA = getType(a);
|
|
72
|
+
const typeB = getType(b);
|
|
73
|
+
if (typeA !== typeB)
|
|
74
|
+
return false;
|
|
75
|
+
if (hasBeenSeen(a, b, seen))
|
|
76
|
+
return true;
|
|
77
|
+
const compareValue = (a, b) => (0, exports.deepCompare)(a, b, seen);
|
|
78
|
+
switch (typeA) {
|
|
79
|
+
case "primitive":
|
|
80
|
+
case "null":
|
|
81
|
+
return a === b;
|
|
82
|
+
case "function":
|
|
83
|
+
return String(a) === String(b);
|
|
84
|
+
case "iterable":
|
|
85
|
+
return compareIterable(a, b, compareValue);
|
|
86
|
+
case "pure-object":
|
|
87
|
+
return comparePureObject(a, b, compareValue);
|
|
88
|
+
case "class-object":
|
|
89
|
+
return compareClass(a, b);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
exports.deepCompare = deepCompare;
|
package/dist/cjs/index.js
CHANGED
|
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./get-window"), exports);
|
|
18
18
|
__exportStar(require("./is-promise-like"), exports);
|
|
19
19
|
__exportStar(require("./log"), exports);
|
|
20
|
+
__exportStar(require("./memoize-function"), exports);
|
|
20
21
|
__exportStar(require("./sleep"), exports);
|
|
21
22
|
__exportStar(require("./thenable"), exports);
|
|
22
23
|
__exportStar(require("./to-void"), exports);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.memoizeFunction = void 0;
|
|
4
|
+
const deep_compare_1 = require("./deep-compare");
|
|
5
|
+
const compareDeps = (a, b) => a.length === b.length && a.every((arg, index) => arg === b[index]);
|
|
6
|
+
const memoizeFunction = (resultFn, compareResult) => {
|
|
7
|
+
let lastDeps = [resultFn, compareResult, ...[]];
|
|
8
|
+
let lastResult = undefined;
|
|
9
|
+
const memo = Object.assign((...args) => {
|
|
10
|
+
var _a;
|
|
11
|
+
const newDeps = [memo.resultFn, memo.compareResult, ...args];
|
|
12
|
+
if (compareDeps(lastDeps, newDeps)) {
|
|
13
|
+
return lastResult;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
lastDeps = newDeps;
|
|
17
|
+
}
|
|
18
|
+
const value = memo.resultFn(...args);
|
|
19
|
+
if (((_a = memo.compareResult) !== null && _a !== void 0 ? _a : deep_compare_1.deepCompare)(lastResult, value)) {
|
|
20
|
+
return lastResult;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
lastResult = value;
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
}, {
|
|
27
|
+
resultFn,
|
|
28
|
+
compareResult,
|
|
29
|
+
});
|
|
30
|
+
return memo;
|
|
31
|
+
};
|
|
32
|
+
exports.memoizeFunction = memoizeFunction;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const isIterable = (value) => Symbol.iterator in value && typeof value[Symbol.iterator] === "function";
|
|
2
|
+
const isPureObject = (value) => value.constructor === Object;
|
|
3
|
+
const getType = (value) => {
|
|
4
|
+
if (typeof value === "object") {
|
|
5
|
+
if (value === null)
|
|
6
|
+
return "null";
|
|
7
|
+
if (isIterable(value))
|
|
8
|
+
return "iterable";
|
|
9
|
+
if (isPureObject(value))
|
|
10
|
+
return "pure-object";
|
|
11
|
+
return "class-object";
|
|
12
|
+
}
|
|
13
|
+
if (typeof value === "function") {
|
|
14
|
+
return "function";
|
|
15
|
+
}
|
|
16
|
+
return "primitive";
|
|
17
|
+
};
|
|
18
|
+
const comparePureObject = (a, b, compareValue) => {
|
|
19
|
+
const keysA = Object.keys(a);
|
|
20
|
+
const keysB = Object.keys(b);
|
|
21
|
+
if (keysA.length !== keysB.length)
|
|
22
|
+
return false;
|
|
23
|
+
return keysA.every(key => key in b &&
|
|
24
|
+
compareValue(a[key], b[key]));
|
|
25
|
+
};
|
|
26
|
+
const compareIterable = (a, b, compareValue) => {
|
|
27
|
+
try {
|
|
28
|
+
const arrA = [...a];
|
|
29
|
+
const arrB = [...b];
|
|
30
|
+
if (arrA.length !== arrB.length)
|
|
31
|
+
return false;
|
|
32
|
+
return (arrA.length === arrB.length &&
|
|
33
|
+
arrA.every((item, index) => compareValue(item, arrB[index])));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const compareClass = (a, b) => {
|
|
40
|
+
if (a.constructor !== b.constructor)
|
|
41
|
+
return false;
|
|
42
|
+
if (a.valueOf !== Object.prototype.valueOf) {
|
|
43
|
+
return a.valueOf() === b.valueOf();
|
|
44
|
+
}
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
46
|
+
if (a.toString() !== Object.prototype.toString()) {
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
48
|
+
return a.toString() === b.toString();
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
};
|
|
52
|
+
const hasBeenSeen = (a, b, seen) => {
|
|
53
|
+
if (typeof a !== "object" || typeof b !== "object" || a == null || b == null)
|
|
54
|
+
return false;
|
|
55
|
+
const seenPairs = seen.get(a) ?? new WeakSet();
|
|
56
|
+
if (seenPairs.has(b))
|
|
57
|
+
return true;
|
|
58
|
+
seenPairs.add(b);
|
|
59
|
+
seen.set(a, seenPairs);
|
|
60
|
+
return false;
|
|
61
|
+
};
|
|
62
|
+
export const deepCompare = (a, b, seen = new WeakMap()
|
|
63
|
+
// eslint-disable-next-line complexity
|
|
64
|
+
) => {
|
|
65
|
+
if (a === b)
|
|
66
|
+
return true;
|
|
67
|
+
const typeA = getType(a);
|
|
68
|
+
const typeB = getType(b);
|
|
69
|
+
if (typeA !== typeB)
|
|
70
|
+
return false;
|
|
71
|
+
if (hasBeenSeen(a, b, seen))
|
|
72
|
+
return true;
|
|
73
|
+
const compareValue = (a, b) => deepCompare(a, b, seen);
|
|
74
|
+
switch (typeA) {
|
|
75
|
+
case "primitive":
|
|
76
|
+
case "null":
|
|
77
|
+
return a === b;
|
|
78
|
+
case "function":
|
|
79
|
+
return String(a) === String(b);
|
|
80
|
+
case "iterable":
|
|
81
|
+
return compareIterable(a, b, compareValue);
|
|
82
|
+
case "pure-object":
|
|
83
|
+
return comparePureObject(a, b, compareValue);
|
|
84
|
+
case "class-object":
|
|
85
|
+
return compareClass(a, b);
|
|
86
|
+
}
|
|
87
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { deepCompare } from "./deep-compare";
|
|
2
|
+
const compareDeps = (a, b) => a.length === b.length && a.every((arg, index) => arg === b[index]);
|
|
3
|
+
export const memoizeFunction = (resultFn, compareResult) => {
|
|
4
|
+
let lastDeps = [resultFn, compareResult, ...[]];
|
|
5
|
+
let lastResult = undefined;
|
|
6
|
+
const memo = Object.assign((...args) => {
|
|
7
|
+
const newDeps = [memo.resultFn, memo.compareResult, ...args];
|
|
8
|
+
if (compareDeps(lastDeps, newDeps)) {
|
|
9
|
+
return lastResult;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
lastDeps = newDeps;
|
|
13
|
+
}
|
|
14
|
+
const value = memo.resultFn(...args);
|
|
15
|
+
if ((memo.compareResult ?? deepCompare)(lastResult, value)) {
|
|
16
|
+
return lastResult;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
lastResult = value;
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
}, {
|
|
23
|
+
resultFn,
|
|
24
|
+
compareResult,
|
|
25
|
+
});
|
|
26
|
+
return memo;
|
|
27
|
+
};
|