@nemigo/helpers 2.8.3 → 2.10.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/aggregator.d.ts +2 -2
- package/dist/aggregator.js +2 -2
- package/dist/async/index.d.ts +5 -2
- package/dist/async/index.js +6 -3
- package/dist/emitter.js +7 -4
- package/dist/index.d.ts +6 -2
- package/dist/index.js +36 -1
- package/dist/promoter.js +3 -1
- package/dist/types.d.ts +6 -0
- package/package.json +1 -1
package/dist/aggregator.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { CanBePromise } from "./types.js";
|
|
2
|
-
export type AFunc = () => CanBePromise
|
|
1
|
+
import type { CanBeNullable, CanBePromise } from "./types.js";
|
|
2
|
+
export type AFunc = CanBeNullable<() => CanBePromise>;
|
|
3
3
|
/**
|
|
4
4
|
* Aggregator для группового выполнения функций
|
|
5
5
|
*
|
package/dist/aggregator.js
CHANGED
|
@@ -32,12 +32,12 @@ export class Aggregator {
|
|
|
32
32
|
if (promise) {
|
|
33
33
|
return (async () => {
|
|
34
34
|
// oxlint-disable-next-line eslint/require-await
|
|
35
|
-
await Promise.allSettled(this.__calls.map(async (f) => f()));
|
|
35
|
+
await Promise.allSettled(this.__calls.map(async (f) => f?.()));
|
|
36
36
|
this.__calls.length = 0;
|
|
37
37
|
})();
|
|
38
38
|
}
|
|
39
39
|
for (const call of this.__calls)
|
|
40
|
-
void call();
|
|
40
|
+
void call?.();
|
|
41
41
|
this.__calls.length = 0;
|
|
42
42
|
}
|
|
43
43
|
}
|
package/dist/async/index.d.ts
CHANGED
|
@@ -39,12 +39,15 @@ export declare const useStateGuard: <F extends AnyFunc>(func: F, state: IState<b
|
|
|
39
39
|
* * Аргументы обновляются
|
|
40
40
|
* - `"urgent"`:
|
|
41
41
|
* * Первый вызов исполняется сразу
|
|
42
|
-
* * Повторные вызовы возвращают тот же промис в течение `ms`
|
|
42
|
+
* * Повторные вызовы возвращают тот же промис в течение `ms` (задержка до следующего вызова, без учёта времени на выполнение)
|
|
43
43
|
* * Аргументы обновляются, но не влияют, если функция уже выполняется
|
|
44
44
|
*/
|
|
45
45
|
export type ThrottleMode = "urgent" | "delay";
|
|
46
46
|
export interface ThrottleOptions {
|
|
47
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Общее состояние (и выполнение функции и задержка)
|
|
49
|
+
*/
|
|
50
|
+
state?: (v: boolean, step: "start" | "delay" | "running" | "reset") => void;
|
|
48
51
|
/**
|
|
49
52
|
* @default "urgent"
|
|
50
53
|
*/
|
package/dist/async/index.js
CHANGED
|
@@ -74,25 +74,28 @@ export const throttle = (func, { mode = "urgent", ms = 250, state }) => {
|
|
|
74
74
|
const call = async () => await func(..._args);
|
|
75
75
|
const reset = () => {
|
|
76
76
|
_promise = null;
|
|
77
|
-
state?.
|
|
77
|
+
state?.(false, "reset");
|
|
78
78
|
};
|
|
79
79
|
return (...args) => {
|
|
80
80
|
_args = args;
|
|
81
81
|
if (_promise)
|
|
82
82
|
return _promise;
|
|
83
|
-
state?.
|
|
83
|
+
state?.(true, "start");
|
|
84
84
|
const { resolve, reject, promise } = createManualPromise();
|
|
85
85
|
_promise = promise;
|
|
86
86
|
if (mode === "delay") {
|
|
87
|
+
state?.(true, "delay");
|
|
87
88
|
setTimeout(() => {
|
|
89
|
+
state?.(true, "running");
|
|
88
90
|
call().then(resolve).catch(reject).finally(reset);
|
|
89
91
|
}, ms);
|
|
90
92
|
}
|
|
91
93
|
else {
|
|
94
|
+
state?.(true, "running");
|
|
92
95
|
call()
|
|
93
96
|
.then(resolve)
|
|
94
97
|
.catch(reject)
|
|
95
|
-
.finally(() => void delay(ms).then(reset));
|
|
98
|
+
.finally(() => (state?.(true, "delay"), void delay(ms).then(reset)));
|
|
96
99
|
}
|
|
97
100
|
return _promise;
|
|
98
101
|
};
|
package/dist/emitter.js
CHANGED
|
@@ -6,11 +6,14 @@
|
|
|
6
6
|
export class Emitter {
|
|
7
7
|
__listeners = new Map();
|
|
8
8
|
dispatch(event, data) {
|
|
9
|
-
for (const [key, handler] of this.__listeners.entries()) {
|
|
10
|
-
if (
|
|
9
|
+
for (const [key, handler] of Array.from(this.__listeners.entries())) {
|
|
10
|
+
if (!this.__listeners.has(key))
|
|
11
|
+
continue; // мог быть снят другим хендлером
|
|
12
|
+
if (handler.event === event) {
|
|
11
13
|
handler.callback(data);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
if (handler.once)
|
|
15
|
+
this.__listeners.delete(key);
|
|
16
|
+
}
|
|
14
17
|
}
|
|
15
18
|
}
|
|
16
19
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnyFunc } from "./types.js";
|
|
1
|
+
import type { AnyFunc, CanBeNullable, CanBePromise } from "./types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Преобразует число в строку, добавляя ведущие нули для достижения указанной длины
|
|
4
4
|
*
|
|
@@ -14,10 +14,14 @@ export declare const pad: (v: number, l?: number) => string;
|
|
|
14
14
|
* Если значение не `object` - возвращается как есть
|
|
15
15
|
*/
|
|
16
16
|
export declare const parsify: <T>(v: T) => T;
|
|
17
|
+
/**
|
|
18
|
+
* С осознанным игнором undefined и для простых типов
|
|
19
|
+
*/
|
|
20
|
+
export declare const isDataEqual: (a: any, b: any) => boolean;
|
|
17
21
|
/**
|
|
18
22
|
* Агрегация функций в одну
|
|
19
23
|
*/
|
|
20
|
-
export declare const aggregate: (...args: (
|
|
24
|
+
export declare const aggregate: (...args: CanBeNullable<() => CanBePromise>[]) => (() => void);
|
|
21
25
|
/**
|
|
22
26
|
* Проверяет, является ли значение объектом
|
|
23
27
|
*
|
package/dist/index.js
CHANGED
|
@@ -17,12 +17,47 @@ export const parsify = (v) => {
|
|
|
17
17
|
return v;
|
|
18
18
|
return JSON.parse(JSON.stringify(v));
|
|
19
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* С осознанным игнором undefined и для простых типов
|
|
22
|
+
*/
|
|
23
|
+
export const isDataEqual = (a, b) => {
|
|
24
|
+
// oxlint-disable-next-line unicorn/no-abusive-eslint-disable (тут лучше так)
|
|
25
|
+
// oxlint-disable-next-line eslint/eqeqeq eslint/no-eq-null (тут лучше так)
|
|
26
|
+
// eslint-disable-next-line no-eq-null,eqeqeq
|
|
27
|
+
if (a == null || b == null || typeof a !== "object" || typeof b !== "object")
|
|
28
|
+
return false;
|
|
29
|
+
const keysA = Object.keys(a);
|
|
30
|
+
const keysB = Object.keys(b);
|
|
31
|
+
let lenA = 0, lenB = 0;
|
|
32
|
+
// Один проход: считаем defined ключи и сразу проверяем наличие в другом объекте
|
|
33
|
+
for (const k of keysA) {
|
|
34
|
+
if (a[k] !== undefined) {
|
|
35
|
+
lenA++;
|
|
36
|
+
if (!(k in b) || b[k] === undefined)
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
for (const k of keysB) {
|
|
41
|
+
if (b[k] !== undefined) {
|
|
42
|
+
lenB++;
|
|
43
|
+
if (!(k in a) || a[k] === undefined)
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (lenA !== lenB)
|
|
48
|
+
return false;
|
|
49
|
+
// Рекурсия только по подтверждённо существующим defined ключам
|
|
50
|
+
for (const k of keysA)
|
|
51
|
+
if (a[k] !== undefined && !isDataEqual(a[k], b[k]))
|
|
52
|
+
return false;
|
|
53
|
+
return true;
|
|
54
|
+
};
|
|
20
55
|
/**
|
|
21
56
|
* Агрегация функций в одну
|
|
22
57
|
*/
|
|
23
58
|
export const aggregate = (...args) => () => {
|
|
24
59
|
for (const call of args)
|
|
25
|
-
call();
|
|
60
|
+
void call?.();
|
|
26
61
|
};
|
|
27
62
|
//...
|
|
28
63
|
/**
|
package/dist/promoter.js
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
export class Promoter {
|
|
5
5
|
__subs = new Map();
|
|
6
6
|
notify(event) {
|
|
7
|
-
for (const [key, { callback, once }] of this.__subs.entries()) {
|
|
7
|
+
for (const [key, { callback, once }] of Array.from(this.__subs.entries())) {
|
|
8
|
+
if (!this.__subs.has(key))
|
|
9
|
+
continue; // мог быть снят другим хендлером
|
|
8
10
|
callback(event);
|
|
9
11
|
if (once)
|
|
10
12
|
this.__subs.delete(key);
|
package/dist/types.d.ts
CHANGED
|
@@ -152,6 +152,12 @@ export type Exist<T> = Exclude<T, undefined>;
|
|
|
152
152
|
* ```
|
|
153
153
|
*/
|
|
154
154
|
export type KEYS<O> = keyof O extends infer Key ? (Key extends string ? Key : never) : never;
|
|
155
|
+
/**
|
|
156
|
+
* Убирает все never-значения из объекта
|
|
157
|
+
*/
|
|
158
|
+
export type NeverKeysFilterType<T> = {
|
|
159
|
+
[K in keyof T as T[K] extends never ? never : K]: T[K];
|
|
160
|
+
};
|
|
155
161
|
/**
|
|
156
162
|
* Примитив для всех записей с идентификатором
|
|
157
163
|
*/
|