@etsoo/shared 1.2.76 → 1.2.79
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/.github/workflows/main.yml +3 -3
- package/README.md +0 -1
- package/__tests__/DataTypes.ts +190 -0
- package/__tests__/DomUtils.ts +3 -38
- package/__tests__/Utils.ts +3 -3
- package/lib/cjs/ArrayUtils.js +3 -6
- package/lib/cjs/DataTypes.d.ts +8 -0
- package/lib/cjs/DataTypes.js +58 -0
- package/lib/cjs/StorageUtils.js +3 -3
- package/lib/cjs/Utils.d.ts +4 -11
- package/lib/cjs/Utils.js +7 -34
- package/lib/cjs/index.d.ts +3 -0
- package/lib/cjs/index.js +3 -0
- package/lib/cjs/node/{Storage.d.ts → NodeStorage.d.ts} +1 -1
- package/lib/cjs/test/MockDOMRect.d.ts +15 -0
- package/lib/cjs/test/MockDOMRect.js +31 -0
- package/lib/cjs/test/MockResizeObserver.d.ts +12 -0
- package/lib/cjs/test/MockResizeObserver.js +27 -0
- package/lib/mjs/ArrayUtils.js +3 -3
- package/lib/mjs/DataTypes.d.ts +8 -0
- package/lib/mjs/DataTypes.js +58 -0
- package/lib/mjs/StorageUtils.js +1 -1
- package/lib/mjs/Utils.d.ts +4 -11
- package/lib/mjs/Utils.js +7 -31
- package/lib/mjs/index.d.ts +3 -0
- package/lib/mjs/index.js +3 -0
- package/lib/mjs/node/{Storage.d.ts → NodeStorage.d.ts} +1 -1
- package/lib/mjs/test/MockDOMRect.d.ts +15 -0
- package/lib/mjs/test/MockDOMRect.js +27 -0
- package/lib/mjs/test/MockResizeObserver.d.ts +12 -0
- package/lib/mjs/test/MockResizeObserver.js +23 -0
- package/package.json +6 -10
- package/src/ArrayUtils.ts +4 -4
- package/src/DataTypes.ts +64 -0
- package/src/StorageUtils.ts +1 -1
- package/src/Utils.ts +7 -31
- package/src/index.ts +5 -0
- package/src/node/{Storage.ts → NodeStorage.ts} +1 -1
- package/src/test/MockDOMRect.ts +37 -0
- package/src/test/MockResizeObserver.ts +28 -0
- /package/lib/cjs/node/{Storage.js → NodeStorage.js} +0 -0
- /package/lib/mjs/node/{Storage.js → NodeStorage.js} +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MockResizeObserver = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Mock implementation of ResizeObserver for testing purposes
|
|
6
|
+
*/
|
|
7
|
+
class MockResizeObserver {
|
|
8
|
+
constructor(callback) {
|
|
9
|
+
this.callbacks = [];
|
|
10
|
+
this.elements = [];
|
|
11
|
+
this.callbacks.push(callback);
|
|
12
|
+
}
|
|
13
|
+
observe(element) {
|
|
14
|
+
this.elements.push(element);
|
|
15
|
+
}
|
|
16
|
+
unobserve(element) {
|
|
17
|
+
this.elements = this.elements.filter((el) => el !== element);
|
|
18
|
+
}
|
|
19
|
+
disconnect() {
|
|
20
|
+
this.elements = [];
|
|
21
|
+
}
|
|
22
|
+
// Helper to trigger the callback manually in tests
|
|
23
|
+
trigger(entries) {
|
|
24
|
+
this.callbacks.forEach((cb) => cb(entries));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.MockResizeObserver = MockResizeObserver;
|
package/lib/mjs/ArrayUtils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { DataTypes } from "./DataTypes";
|
|
2
2
|
Array.prototype.different = function (target, round) {
|
|
3
3
|
return ArrayUtils.differences(this, target, round);
|
|
4
4
|
};
|
|
@@ -13,7 +13,7 @@ Array.prototype.toggleItem = function (item, add, idField) {
|
|
|
13
13
|
return i[idField] === item;
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
return
|
|
16
|
+
return DataTypes.isDeepEqual(i, item);
|
|
17
17
|
});
|
|
18
18
|
if (add) {
|
|
19
19
|
if (index < 0) {
|
|
@@ -33,7 +33,7 @@ Array.prototype.toUnique = function () {
|
|
|
33
33
|
return Array.from(new Set(this));
|
|
34
34
|
const newArray = [];
|
|
35
35
|
this.forEach((item) => {
|
|
36
|
-
if (newArray.some((newItem) =>
|
|
36
|
+
if (newArray.some((newItem) => DataTypes.isDeepEqual(item, newItem)))
|
|
37
37
|
return;
|
|
38
38
|
newArray.push(item);
|
|
39
39
|
});
|
package/lib/mjs/DataTypes.d.ts
CHANGED
|
@@ -399,6 +399,14 @@ export declare namespace DataTypes {
|
|
|
399
399
|
* @returns Is basic type
|
|
400
400
|
*/
|
|
401
401
|
function isBasicName(name: string): name is BasicNames;
|
|
402
|
+
/**
|
|
403
|
+
* Check deep equality
|
|
404
|
+
* @param a Input a
|
|
405
|
+
* @param b Input b
|
|
406
|
+
* @param isStrict Strict or not, false: loose equal, undefined === but null equal undefined, NaN equal NaN, true: strict equal
|
|
407
|
+
* @returns Result
|
|
408
|
+
*/
|
|
409
|
+
function isDeepEqual(a: unknown, b: unknown, isStrict?: boolean): boolean;
|
|
402
410
|
/**
|
|
403
411
|
* Is the target a simple object (Type guard)
|
|
404
412
|
* @param input Test data
|
package/lib/mjs/DataTypes.js
CHANGED
|
@@ -452,6 +452,64 @@ export var DataTypes;
|
|
|
452
452
|
return DataTypes.BasicArray.includes(name);
|
|
453
453
|
}
|
|
454
454
|
DataTypes.isBasicName = isBasicName;
|
|
455
|
+
/**
|
|
456
|
+
* Check deep equality
|
|
457
|
+
* @param a Input a
|
|
458
|
+
* @param b Input b
|
|
459
|
+
* @param isStrict Strict or not, false: loose equal, undefined === but null equal undefined, NaN equal NaN, true: strict equal
|
|
460
|
+
* @returns Result
|
|
461
|
+
*/
|
|
462
|
+
function isDeepEqual(a, b, isStrict) {
|
|
463
|
+
// Same object or value
|
|
464
|
+
if (a === b)
|
|
465
|
+
return true;
|
|
466
|
+
// Null and undefined case
|
|
467
|
+
if (a == null || b == null) {
|
|
468
|
+
if (!isStrict && a == b)
|
|
469
|
+
return true;
|
|
470
|
+
return a === b;
|
|
471
|
+
}
|
|
472
|
+
else if (isStrict === false) {
|
|
473
|
+
// Loose equal case
|
|
474
|
+
if (a == b)
|
|
475
|
+
return true;
|
|
476
|
+
}
|
|
477
|
+
// Different type
|
|
478
|
+
if (typeof a !== typeof b)
|
|
479
|
+
return false;
|
|
480
|
+
// NaN case
|
|
481
|
+
if (Number.isNaN(a) && Number.isNaN(b) && !isStrict)
|
|
482
|
+
return true;
|
|
483
|
+
if (typeof a === "object") {
|
|
484
|
+
// Date
|
|
485
|
+
if (a instanceof Date && b instanceof Date) {
|
|
486
|
+
return a.getTime() === b.getTime();
|
|
487
|
+
}
|
|
488
|
+
// Array
|
|
489
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
490
|
+
if (a.length !== b.length)
|
|
491
|
+
return false;
|
|
492
|
+
for (let i = 0; i < a.length; i++) {
|
|
493
|
+
if (!isDeepEqual(a[i], b[i], isStrict))
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
return true;
|
|
497
|
+
}
|
|
498
|
+
// Loop object keys
|
|
499
|
+
const aKeys = Object.keys(a);
|
|
500
|
+
const bKeys = Object.keys(b);
|
|
501
|
+
if (aKeys.length !== bKeys.length && isStrict)
|
|
502
|
+
return false;
|
|
503
|
+
const allKeys = new Set([...aKeys, ...bKeys]);
|
|
504
|
+
for (const key of allKeys) {
|
|
505
|
+
if (!isDeepEqual(Reflect.get(a, key), Reflect.get(b, key), isStrict))
|
|
506
|
+
return false;
|
|
507
|
+
}
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
return isStrict ? a === b : a == b;
|
|
511
|
+
}
|
|
512
|
+
DataTypes.isDeepEqual = isDeepEqual;
|
|
455
513
|
/**
|
|
456
514
|
* Is the target a simple object (Type guard)
|
|
457
515
|
* @param input Test data
|
package/lib/mjs/StorageUtils.js
CHANGED
package/lib/mjs/Utils.d.ts
CHANGED
|
@@ -112,13 +112,6 @@ export declare namespace Utils {
|
|
|
112
112
|
export function correctTypes<T extends object, F extends {
|
|
113
113
|
[P in keyof T]?: DataTypes.BasicNames;
|
|
114
114
|
}>(input: T, fields: F): void;
|
|
115
|
-
/**
|
|
116
|
-
* Two values equal
|
|
117
|
-
* @param v1 Value 1
|
|
118
|
-
* @param v2 Value 2
|
|
119
|
-
* @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
|
|
120
|
-
*/
|
|
121
|
-
export function equals(v1: unknown, v2: unknown, strict?: number): boolean;
|
|
122
115
|
/**
|
|
123
116
|
* Exclude specific items
|
|
124
117
|
* @param items Items
|
|
@@ -231,10 +224,10 @@ export declare namespace Utils {
|
|
|
231
224
|
* @param obj1 Object 1
|
|
232
225
|
* @param obj2 Object 2
|
|
233
226
|
* @param ignoreFields Ignored fields
|
|
234
|
-
* @param
|
|
227
|
+
* @param isStrict Strict or not, false: loose equal, undefined === but null equal undefined, NaN equal NaN, true: strict equal
|
|
235
228
|
* @returns Result
|
|
236
229
|
*/
|
|
237
|
-
export function objectEqual(obj1: object, obj2: object, ignoreFields?: string[],
|
|
230
|
+
export function objectEqual(obj1: object, obj2: object, ignoreFields?: string[], isStrict?: boolean): boolean;
|
|
238
231
|
/**
|
|
239
232
|
* Get two object's unqiue properties
|
|
240
233
|
* @param obj1 Object 1
|
|
@@ -248,10 +241,10 @@ export declare namespace Utils {
|
|
|
248
241
|
* @param objNew New object
|
|
249
242
|
* @param objPre Previous object
|
|
250
243
|
* @param ignoreFields Ignored fields
|
|
251
|
-
* @param
|
|
244
|
+
* @param isStrict Strict or not, false: loose equal, undefined === but null equal undefined, NaN equal NaN, true: strict equal
|
|
252
245
|
* @returns Updated fields
|
|
253
246
|
*/
|
|
254
|
-
export function objectUpdated(objNew: object, objPrev: object, ignoreFields?: string[],
|
|
247
|
+
export function objectUpdated(objNew: object, objPrev: object, ignoreFields?: string[], isStrict?: boolean): string[];
|
|
255
248
|
/**
|
|
256
249
|
* Try to parse JSON input to array
|
|
257
250
|
* @param input JSON input
|
package/lib/mjs/Utils.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { DataTypes } from "./DataTypes";
|
|
2
|
-
import isEqual from "lodash.isequal";
|
|
3
2
|
import { DateUtils } from "./DateUtils";
|
|
4
3
|
String.prototype.addUrlParam = function (name, value, arrayFormat) {
|
|
5
4
|
return this.addUrlParams({ [name]: value }, arrayFormat);
|
|
@@ -180,29 +179,6 @@ export var Utils;
|
|
|
180
179
|
}
|
|
181
180
|
}
|
|
182
181
|
Utils.correctTypes = correctTypes;
|
|
183
|
-
/**
|
|
184
|
-
* Two values equal
|
|
185
|
-
* @param v1 Value 1
|
|
186
|
-
* @param v2 Value 2
|
|
187
|
-
* @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
|
|
188
|
-
*/
|
|
189
|
-
function equals(v1, v2, strict = 1) {
|
|
190
|
-
// Null and undefined case
|
|
191
|
-
if (v1 == null || v2 == null) {
|
|
192
|
-
if (strict <= 1 && v1 == v2)
|
|
193
|
-
return true;
|
|
194
|
-
return v1 === v2;
|
|
195
|
-
}
|
|
196
|
-
// For date, array and object
|
|
197
|
-
if (typeof v1 === "object")
|
|
198
|
-
return isEqual(v1, v2);
|
|
199
|
-
// 1 and '1' case
|
|
200
|
-
if (strict === 0)
|
|
201
|
-
return v1 == v2;
|
|
202
|
-
// Strict equal
|
|
203
|
-
return v1 === v2;
|
|
204
|
-
}
|
|
205
|
-
Utils.equals = equals;
|
|
206
182
|
/**
|
|
207
183
|
* Exclude specific items
|
|
208
184
|
* @param items Items
|
|
@@ -281,7 +257,7 @@ export var Utils;
|
|
|
281
257
|
return;
|
|
282
258
|
}
|
|
283
259
|
const newValue = DataTypes.convert(value, initValue);
|
|
284
|
-
if (
|
|
260
|
+
if (DataTypes.isDeepEqual(newValue, initValue)) {
|
|
285
261
|
Reflect.deleteProperty(input, key);
|
|
286
262
|
return;
|
|
287
263
|
}
|
|
@@ -446,17 +422,17 @@ export var Utils;
|
|
|
446
422
|
* @param obj1 Object 1
|
|
447
423
|
* @param obj2 Object 2
|
|
448
424
|
* @param ignoreFields Ignored fields
|
|
449
|
-
* @param
|
|
425
|
+
* @param isStrict Strict or not, false: loose equal, undefined === but null equal undefined, NaN equal NaN, true: strict equal
|
|
450
426
|
* @returns Result
|
|
451
427
|
*/
|
|
452
|
-
function objectEqual(obj1, obj2, ignoreFields = [],
|
|
428
|
+
function objectEqual(obj1, obj2, ignoreFields = [], isStrict) {
|
|
453
429
|
// Unique keys
|
|
454
430
|
const keys = Utils.objectKeys(obj1, obj2, ignoreFields);
|
|
455
431
|
for (const key of keys) {
|
|
456
432
|
// Values
|
|
457
433
|
const v1 = Reflect.get(obj1, key);
|
|
458
434
|
const v2 = Reflect.get(obj2, key);
|
|
459
|
-
if (!
|
|
435
|
+
if (!DataTypes.isDeepEqual(v1, v2, isStrict))
|
|
460
436
|
return false;
|
|
461
437
|
}
|
|
462
438
|
return true;
|
|
@@ -481,10 +457,10 @@ export var Utils;
|
|
|
481
457
|
* @param objNew New object
|
|
482
458
|
* @param objPre Previous object
|
|
483
459
|
* @param ignoreFields Ignored fields
|
|
484
|
-
* @param
|
|
460
|
+
* @param isStrict Strict or not, false: loose equal, undefined === but null equal undefined, NaN equal NaN, true: strict equal
|
|
485
461
|
* @returns Updated fields
|
|
486
462
|
*/
|
|
487
|
-
function objectUpdated(objNew, objPrev, ignoreFields = [],
|
|
463
|
+
function objectUpdated(objNew, objPrev, ignoreFields = [], isStrict) {
|
|
488
464
|
// Fields
|
|
489
465
|
const fields = [];
|
|
490
466
|
// Unique keys
|
|
@@ -493,7 +469,7 @@ export var Utils;
|
|
|
493
469
|
// Values
|
|
494
470
|
const vNew = Reflect.get(objNew, key);
|
|
495
471
|
const vPrev = Reflect.get(objPrev, key);
|
|
496
|
-
if (!
|
|
472
|
+
if (!DataTypes.isDeepEqual(vNew, vPrev, isStrict)) {
|
|
497
473
|
fields.push(key);
|
|
498
474
|
}
|
|
499
475
|
}
|
package/lib/mjs/index.d.ts
CHANGED
|
@@ -6,8 +6,11 @@ export * from "./types/EHistory";
|
|
|
6
6
|
export * from "./types/ErrorData";
|
|
7
7
|
export * from "./types/EventClass";
|
|
8
8
|
export * from "./types/FormData";
|
|
9
|
+
export * from "./node/NodeStorage";
|
|
9
10
|
export * from "./storage/IStorage";
|
|
10
11
|
export * from "./storage/WindowStorage";
|
|
12
|
+
export * from "./test/MockDOMRect";
|
|
13
|
+
export * from "./test/MockResizeObserver";
|
|
11
14
|
export * from "./ActionResult";
|
|
12
15
|
export * from "./ArrayUtils";
|
|
13
16
|
export * from "./DataTypes";
|
package/lib/mjs/index.js
CHANGED
|
@@ -6,8 +6,11 @@ export * from "./types/EHistory";
|
|
|
6
6
|
export * from "./types/ErrorData";
|
|
7
7
|
export * from "./types/EventClass";
|
|
8
8
|
export * from "./types/FormData";
|
|
9
|
+
export * from "./node/NodeStorage";
|
|
9
10
|
export * from "./storage/IStorage";
|
|
10
11
|
export * from "./storage/WindowStorage";
|
|
12
|
+
export * from "./test/MockDOMRect";
|
|
13
|
+
export * from "./test/MockResizeObserver";
|
|
11
14
|
export * from "./ActionResult";
|
|
12
15
|
export * from "./ArrayUtils";
|
|
13
16
|
export * from "./DataTypes";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A mock implementation of DOMRect for testing purposes
|
|
3
|
+
*/
|
|
4
|
+
export declare class MockDOMRect implements DOMRect {
|
|
5
|
+
readonly bottom: number;
|
|
6
|
+
readonly height: number;
|
|
7
|
+
readonly left: number;
|
|
8
|
+
readonly right: number;
|
|
9
|
+
readonly top: number;
|
|
10
|
+
readonly width: number;
|
|
11
|
+
readonly x: number;
|
|
12
|
+
readonly y: number;
|
|
13
|
+
toJSON(): any;
|
|
14
|
+
constructor(width: number, height: number, x?: number, y?: number);
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A mock implementation of DOMRect for testing purposes
|
|
3
|
+
*/
|
|
4
|
+
export class MockDOMRect {
|
|
5
|
+
toJSON() {
|
|
6
|
+
return JSON.stringify({
|
|
7
|
+
bottom: this.bottom,
|
|
8
|
+
height: this.height,
|
|
9
|
+
left: this.left,
|
|
10
|
+
right: this.right,
|
|
11
|
+
top: this.top,
|
|
12
|
+
width: this.width,
|
|
13
|
+
x: this.x,
|
|
14
|
+
y: this.y
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
constructor(width, height, x = 0, y = 0) {
|
|
18
|
+
this.x = x;
|
|
19
|
+
this.y = y;
|
|
20
|
+
this.width = width;
|
|
21
|
+
this.height = height;
|
|
22
|
+
this.left = x;
|
|
23
|
+
this.top = y;
|
|
24
|
+
this.bottom = this.top + this.height;
|
|
25
|
+
this.right = this.left = this.width;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock implementation of ResizeObserver for testing purposes
|
|
3
|
+
*/
|
|
4
|
+
export declare class MockResizeObserver implements ResizeObserver {
|
|
5
|
+
callbacks: Function[];
|
|
6
|
+
elements: Element[];
|
|
7
|
+
constructor(callback: Function);
|
|
8
|
+
observe(element: Element): void;
|
|
9
|
+
unobserve(element: Element): void;
|
|
10
|
+
disconnect(): void;
|
|
11
|
+
trigger(entries: ResizeObserverEntry[]): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock implementation of ResizeObserver for testing purposes
|
|
3
|
+
*/
|
|
4
|
+
export class MockResizeObserver {
|
|
5
|
+
constructor(callback) {
|
|
6
|
+
this.callbacks = [];
|
|
7
|
+
this.elements = [];
|
|
8
|
+
this.callbacks.push(callback);
|
|
9
|
+
}
|
|
10
|
+
observe(element) {
|
|
11
|
+
this.elements.push(element);
|
|
12
|
+
}
|
|
13
|
+
unobserve(element) {
|
|
14
|
+
this.elements = this.elements.filter((el) => el !== element);
|
|
15
|
+
}
|
|
16
|
+
disconnect() {
|
|
17
|
+
this.elements = [];
|
|
18
|
+
}
|
|
19
|
+
// Helper to trigger the callback manually in tests
|
|
20
|
+
trigger(entries) {
|
|
21
|
+
this.callbacks.forEach((cb) => cb(entries));
|
|
22
|
+
}
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/shared",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.79",
|
|
4
4
|
"description": "TypeScript shared utilities and functions",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/mjs/index.js",
|
|
@@ -36,14 +36,10 @@
|
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://github.com/ETSOO/Shared#readme",
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@types/
|
|
40
|
-
"@
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"vitest": "^3.2.4"
|
|
45
|
-
},
|
|
46
|
-
"dependencies": {
|
|
47
|
-
"lodash.isequal": "^4.5.0"
|
|
39
|
+
"@types/node": "^24.10.0",
|
|
40
|
+
"@vitejs/plugin-react": "^5.1.0",
|
|
41
|
+
"jsdom": "^27.1.0",
|
|
42
|
+
"typescript": "^5.9.3",
|
|
43
|
+
"vitest": "^4.0.7"
|
|
48
44
|
}
|
|
49
45
|
}
|
package/src/ArrayUtils.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { DataTypes, IdType } from "./DataTypes";
|
|
1
|
+
import { DataTypes } from "./DataTypes";
|
|
3
2
|
|
|
4
3
|
declare global {
|
|
5
4
|
interface Array<T> {
|
|
@@ -127,7 +126,7 @@ Array.prototype.toggleItem = function <
|
|
|
127
126
|
return i[idField as keyof T] === item;
|
|
128
127
|
}
|
|
129
128
|
}
|
|
130
|
-
return
|
|
129
|
+
return DataTypes.isDeepEqual(i, item);
|
|
131
130
|
});
|
|
132
131
|
|
|
133
132
|
if (add) {
|
|
@@ -149,7 +148,8 @@ Array.prototype.toUnique = function <T>(this: Array<T>) {
|
|
|
149
148
|
|
|
150
149
|
const newArray: T[] = [];
|
|
151
150
|
this.forEach((item) => {
|
|
152
|
-
if (newArray.some((newItem) =>
|
|
151
|
+
if (newArray.some((newItem) => DataTypes.isDeepEqual(item, newItem)))
|
|
152
|
+
return;
|
|
153
153
|
newArray.push(item);
|
|
154
154
|
});
|
|
155
155
|
return newArray;
|
package/src/DataTypes.ts
CHANGED
|
@@ -741,6 +741,70 @@ export namespace DataTypes {
|
|
|
741
741
|
return BasicArray.includes(<BasicNames>name);
|
|
742
742
|
}
|
|
743
743
|
|
|
744
|
+
/**
|
|
745
|
+
* Check deep equality
|
|
746
|
+
* @param a Input a
|
|
747
|
+
* @param b Input b
|
|
748
|
+
* @param isStrict Strict or not, false: loose equal, undefined === but null equal undefined, NaN equal NaN, true: strict equal
|
|
749
|
+
* @returns Result
|
|
750
|
+
*/
|
|
751
|
+
export function isDeepEqual(
|
|
752
|
+
a: unknown,
|
|
753
|
+
b: unknown,
|
|
754
|
+
isStrict?: boolean
|
|
755
|
+
): boolean {
|
|
756
|
+
// Same object or value
|
|
757
|
+
if (a === b) return true;
|
|
758
|
+
|
|
759
|
+
// Null and undefined case
|
|
760
|
+
if (a == null || b == null) {
|
|
761
|
+
if (!isStrict && a == b) return true;
|
|
762
|
+
return a === b;
|
|
763
|
+
} else if (isStrict === false) {
|
|
764
|
+
// Loose equal case
|
|
765
|
+
if (a == b) return true;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// Different type
|
|
769
|
+
if (typeof a !== typeof b) return false;
|
|
770
|
+
|
|
771
|
+
// NaN case
|
|
772
|
+
if (Number.isNaN(a) && Number.isNaN(b) && !isStrict) return true;
|
|
773
|
+
|
|
774
|
+
if (typeof a === "object") {
|
|
775
|
+
// Date
|
|
776
|
+
if (a instanceof Date && b instanceof Date) {
|
|
777
|
+
return a.getTime() === b.getTime();
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// Array
|
|
781
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
782
|
+
if (a.length !== b.length) return false;
|
|
783
|
+
|
|
784
|
+
for (let i = 0; i < a.length; i++) {
|
|
785
|
+
if (!isDeepEqual(a[i], b[i], isStrict)) return false;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
return true;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// Loop object keys
|
|
792
|
+
const aKeys = Object.keys(a);
|
|
793
|
+
const bKeys = Object.keys(b);
|
|
794
|
+
if (aKeys.length !== bKeys.length && isStrict) return false;
|
|
795
|
+
|
|
796
|
+
const allKeys = new Set<string>([...aKeys, ...bKeys]);
|
|
797
|
+
for (const key of allKeys) {
|
|
798
|
+
if (!isDeepEqual(Reflect.get(a, key), Reflect.get(b, key), isStrict))
|
|
799
|
+
return false;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
return true;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
return isStrict ? a === b : a == b;
|
|
806
|
+
}
|
|
807
|
+
|
|
744
808
|
/**
|
|
745
809
|
* Is the target a simple object (Type guard)
|
|
746
810
|
* @param input Test data
|
package/src/StorageUtils.ts
CHANGED
package/src/Utils.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { DataTypes, IdType } from "./DataTypes";
|
|
2
|
-
import isEqual from "lodash.isequal";
|
|
3
2
|
import { DateUtils } from "./DateUtils";
|
|
4
3
|
import { ParsedPath } from "./types/ParsedPath";
|
|
5
4
|
|
|
@@ -326,29 +325,6 @@ export namespace Utils {
|
|
|
326
325
|
}
|
|
327
326
|
}
|
|
328
327
|
|
|
329
|
-
/**
|
|
330
|
-
* Two values equal
|
|
331
|
-
* @param v1 Value 1
|
|
332
|
-
* @param v2 Value 2
|
|
333
|
-
* @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
|
|
334
|
-
*/
|
|
335
|
-
export function equals(v1: unknown, v2: unknown, strict = 1) {
|
|
336
|
-
// Null and undefined case
|
|
337
|
-
if (v1 == null || v2 == null) {
|
|
338
|
-
if (strict <= 1 && v1 == v2) return true;
|
|
339
|
-
return v1 === v2;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// For date, array and object
|
|
343
|
-
if (typeof v1 === "object") return isEqual(v1, v2);
|
|
344
|
-
|
|
345
|
-
// 1 and '1' case
|
|
346
|
-
if (strict === 0) return v1 == v2;
|
|
347
|
-
|
|
348
|
-
// Strict equal
|
|
349
|
-
return v1 === v2;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
328
|
/**
|
|
353
329
|
* Exclude specific items
|
|
354
330
|
* @param items Items
|
|
@@ -454,7 +430,7 @@ export namespace Utils {
|
|
|
454
430
|
}
|
|
455
431
|
|
|
456
432
|
const newValue = DataTypes.convert(value, initValue);
|
|
457
|
-
if (
|
|
433
|
+
if (DataTypes.isDeepEqual(newValue, initValue)) {
|
|
458
434
|
Reflect.deleteProperty(input, key);
|
|
459
435
|
return;
|
|
460
436
|
}
|
|
@@ -636,14 +612,14 @@ export namespace Utils {
|
|
|
636
612
|
* @param obj1 Object 1
|
|
637
613
|
* @param obj2 Object 2
|
|
638
614
|
* @param ignoreFields Ignored fields
|
|
639
|
-
* @param
|
|
615
|
+
* @param isStrict Strict or not, false: loose equal, undefined === but null equal undefined, NaN equal NaN, true: strict equal
|
|
640
616
|
* @returns Result
|
|
641
617
|
*/
|
|
642
618
|
export function objectEqual(
|
|
643
619
|
obj1: object,
|
|
644
620
|
obj2: object,
|
|
645
621
|
ignoreFields: string[] = [],
|
|
646
|
-
|
|
622
|
+
isStrict?: boolean
|
|
647
623
|
) {
|
|
648
624
|
// Unique keys
|
|
649
625
|
const keys = Utils.objectKeys(obj1, obj2, ignoreFields);
|
|
@@ -653,7 +629,7 @@ export namespace Utils {
|
|
|
653
629
|
const v1 = Reflect.get(obj1, key);
|
|
654
630
|
const v2 = Reflect.get(obj2, key);
|
|
655
631
|
|
|
656
|
-
if (!
|
|
632
|
+
if (!DataTypes.isDeepEqual(v1, v2, isStrict)) return false;
|
|
657
633
|
}
|
|
658
634
|
|
|
659
635
|
return true;
|
|
@@ -685,14 +661,14 @@ export namespace Utils {
|
|
|
685
661
|
* @param objNew New object
|
|
686
662
|
* @param objPre Previous object
|
|
687
663
|
* @param ignoreFields Ignored fields
|
|
688
|
-
* @param
|
|
664
|
+
* @param isStrict Strict or not, false: loose equal, undefined === but null equal undefined, NaN equal NaN, true: strict equal
|
|
689
665
|
* @returns Updated fields
|
|
690
666
|
*/
|
|
691
667
|
export function objectUpdated(
|
|
692
668
|
objNew: object,
|
|
693
669
|
objPrev: object,
|
|
694
670
|
ignoreFields: string[] = [],
|
|
695
|
-
|
|
671
|
+
isStrict?: boolean
|
|
696
672
|
) {
|
|
697
673
|
// Fields
|
|
698
674
|
const fields: string[] = [];
|
|
@@ -705,7 +681,7 @@ export namespace Utils {
|
|
|
705
681
|
const vNew = Reflect.get(objNew, key);
|
|
706
682
|
const vPrev = Reflect.get(objPrev, key);
|
|
707
683
|
|
|
708
|
-
if (!
|
|
684
|
+
if (!DataTypes.isDeepEqual(vNew, vPrev, isStrict)) {
|
|
709
685
|
fields.push(key);
|
|
710
686
|
}
|
|
711
687
|
}
|
package/src/index.ts
CHANGED
|
@@ -7,9 +7,14 @@ export * from "./types/ErrorData";
|
|
|
7
7
|
export * from "./types/EventClass";
|
|
8
8
|
export * from "./types/FormData";
|
|
9
9
|
|
|
10
|
+
export * from "./node/NodeStorage";
|
|
11
|
+
|
|
10
12
|
export * from "./storage/IStorage";
|
|
11
13
|
export * from "./storage/WindowStorage";
|
|
12
14
|
|
|
15
|
+
export * from "./test/MockDOMRect";
|
|
16
|
+
export * from "./test/MockResizeObserver";
|
|
17
|
+
|
|
13
18
|
export * from "./ActionResult";
|
|
14
19
|
export * from "./ArrayUtils";
|
|
15
20
|
export * from "./DataTypes";
|