@mirta/basics 0.3.5 → 0.4.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/array/index.d.mts +61 -0
- package/dist/array/index.mjs +67 -0
- package/dist/fuzzy/index.d.mts +170 -0
- package/dist/fuzzy/index.mjs +557 -0
- package/dist/guards.mjs +133 -0
- package/dist/index.d.mts +236 -0
- package/dist/index.mjs +4 -9
- package/dist/object/index.d.mts +161 -0
- package/dist/object/index.mjs +56 -0
- package/package.json +28 -5
- package/dist/index.d.ts +0 -119
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
interface DebounceOptions {
|
|
2
|
+
leading?: boolean;
|
|
3
|
+
trailing?: boolean;
|
|
4
|
+
maxWait?: number;
|
|
5
|
+
}
|
|
6
|
+
interface DebouncedFunc<TArgs extends unknown[]> {
|
|
7
|
+
(...args: TArgs): void;
|
|
8
|
+
cancel(): void;
|
|
9
|
+
flush(): void;
|
|
10
|
+
}
|
|
11
|
+
interface ThrottleOptions {
|
|
12
|
+
leading?: boolean;
|
|
13
|
+
trailing?: boolean;
|
|
14
|
+
}
|
|
15
|
+
interface ThrottledFunc<TArgs extends unknown[]> {
|
|
16
|
+
(...args: TArgs): void;
|
|
17
|
+
cancel(): void;
|
|
18
|
+
flush(): void;
|
|
19
|
+
}
|
|
20
|
+
declare function debounce<TArgs extends unknown[]>(callback: (...args: TArgs) => void, wait: number, options?: DebounceOptions): DebouncedFunc<TArgs>;
|
|
21
|
+
declare function throttle<TArgs extends unknown[]>(callback: (...args: TArgs) => void, wait: number, options?: ThrottleOptions): ThrottledFunc<TArgs>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Проверяет, является ли переданное значение строковым примитивом (`string`).
|
|
25
|
+
*
|
|
26
|
+
* @param value - Значение, которое необходимо проверить.
|
|
27
|
+
* @returns `true`, если значение является строкой (`string`), иначе `false`.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* isString('hello'); // true
|
|
32
|
+
* isString(123); // false
|
|
33
|
+
* ```
|
|
34
|
+
* @since 0.0.2
|
|
35
|
+
*
|
|
36
|
+
**/
|
|
37
|
+
declare const isString: (value: unknown) => value is string;
|
|
38
|
+
/**
|
|
39
|
+
* Проверяет, является ли переданное значение числовым примитивом (`number`), не равным `NaN`.
|
|
40
|
+
*
|
|
41
|
+
* @param value - Значение, которое необходимо проверить.
|
|
42
|
+
* @returns `true`, если значение является числом (`number`) и не является `NaN`, иначе `false`.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* isNumber(42) // true
|
|
47
|
+
* isNumber('42') // false
|
|
48
|
+
* isNumber(NaN) // false
|
|
49
|
+
* ```
|
|
50
|
+
* @since 0.0.2
|
|
51
|
+
*
|
|
52
|
+
**/
|
|
53
|
+
declare const isNumber: (value: unknown) => value is number;
|
|
54
|
+
/**
|
|
55
|
+
* Проверяет, является ли переданное значение булевым примитивом (`boolean`).
|
|
56
|
+
*
|
|
57
|
+
* @param value - Значение, которое необходимо проверить.
|
|
58
|
+
* @returns `true`, если значение является булевым примитивом (`true` или `false`), иначе `false`.
|
|
59
|
+
*
|
|
60
|
+
* @remarks
|
|
61
|
+
* Не возвращает `true` для объектов `Boolean`, даже если они обёрнуты.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
*
|
|
65
|
+
* ```ts
|
|
66
|
+
* isBoolean(true) // true
|
|
67
|
+
* isBoolean(false) // true
|
|
68
|
+
* isBoolean(1) // false
|
|
69
|
+
* isBoolean('true') // false
|
|
70
|
+
* isBoolean(new Boolean(true)) // false (это объект, не примитив)
|
|
71
|
+
* ```
|
|
72
|
+
* @since 0.0.2
|
|
73
|
+
*
|
|
74
|
+
**/
|
|
75
|
+
declare function isBoolean(value: unknown): value is boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Проверяет, является ли переданное значение функцией.
|
|
78
|
+
*
|
|
79
|
+
* @param value - Значение, которое необходимо проверить.
|
|
80
|
+
* @returns `true`, если значение является функцией (включая стрелочные функции, функции-объявления, методы и т.д.), иначе `false`.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* isFunction(() => {}); // true
|
|
85
|
+
* isFunction(function() {}); // true
|
|
86
|
+
* isFunction(Math.max); // true
|
|
87
|
+
* isFunction(class {}); // true (в JS классы — это функции)
|
|
88
|
+
* isFunction({}); // false
|
|
89
|
+
* isFunction('function'); // false
|
|
90
|
+
* ```
|
|
91
|
+
* @since 0.1.0
|
|
92
|
+
*
|
|
93
|
+
**/
|
|
94
|
+
declare const isFunction: (value: unknown) => value is ((...args: unknown[]) => unknown);
|
|
95
|
+
/**
|
|
96
|
+
* Проверяет, является ли значение объектом —
|
|
97
|
+
* имеет тип `object` и не равно `null`.
|
|
98
|
+
*
|
|
99
|
+
* @remarks
|
|
100
|
+
* Проходят массивы и все объектные типы, включая
|
|
101
|
+
* встроенные (`Date`, `Map`, `Set`, `RegExp` и прочие).
|
|
102
|
+
*
|
|
103
|
+
* @param value - Проверяемое значение.
|
|
104
|
+
* @returns `true`, если это объект.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* isObject({}) // true
|
|
109
|
+
* isObject([]) // true
|
|
110
|
+
*
|
|
111
|
+
* isObject(() => {}) // false
|
|
112
|
+
* isObject(null) // false
|
|
113
|
+
* isObject('hello') // false
|
|
114
|
+
* isObject(42) // false
|
|
115
|
+
* ```
|
|
116
|
+
* @since 0.4.0
|
|
117
|
+
*/
|
|
118
|
+
declare const isObject: (value: unknown) => value is object;
|
|
119
|
+
/**
|
|
120
|
+
* Проверяет, является ли значение "обычным объектом" —
|
|
121
|
+
* имеет прототип `Object.prototype` или `null`.
|
|
122
|
+
*
|
|
123
|
+
* @remarks
|
|
124
|
+
* Не проходят массивы и встроенные типы (`Date`, `Map`, `Set`, `RegExp` и прочие).
|
|
125
|
+
*
|
|
126
|
+
* Не пройдёт и `Object.create({})`, т.к. экземпляр _унаследован_ от обычного объекта `{}`.
|
|
127
|
+
*
|
|
128
|
+
* @param value - Проверяемое значение.
|
|
129
|
+
*
|
|
130
|
+
* @returns `true`, если это обычный объект.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* isPlainObject({}) // true
|
|
135
|
+
* isPlainObject({ a: 1, b: 2 }) // true
|
|
136
|
+
* isPlainObject(Object.create(null)) // true
|
|
137
|
+
*
|
|
138
|
+
* isPlainObject(Object.create({})) // false
|
|
139
|
+
* isPlainObject(new Date()) // false
|
|
140
|
+
* isPlainObject(() => {}) // false
|
|
141
|
+
* isPlainObject([]) // false
|
|
142
|
+
* ```
|
|
143
|
+
* @since 0.4.0
|
|
144
|
+
*
|
|
145
|
+
**/
|
|
146
|
+
declare const isPlainObject: (value: unknown) => value is Record<string, unknown>;
|
|
147
|
+
|
|
148
|
+
declare const mqttToBoolean: (value: WbRules.MqttValue) => boolean;
|
|
149
|
+
|
|
150
|
+
type EventHandler = (...args: unknown[]) => void;
|
|
151
|
+
type OnEvent<THandler extends EventHandler> = (handler: THandler) => {
|
|
152
|
+
off: () => void;
|
|
153
|
+
};
|
|
154
|
+
type OnceEvent<THandler extends EventHandler> = (handler: THandler) => void;
|
|
155
|
+
interface Event<THandler extends EventHandler> {
|
|
156
|
+
/**
|
|
157
|
+
* Подписывает на событие, есть возможность отписки.
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* // Событие изменения состояния.
|
|
161
|
+
* const stateChanged = useEvent()
|
|
162
|
+
* // Подписка на прослушивание события.
|
|
163
|
+
* const subscription = stateChanged.on(() => { ... })
|
|
164
|
+
* // Отписка от прослушивания события.
|
|
165
|
+
* subscription.off()
|
|
166
|
+
* ```
|
|
167
|
+
**/
|
|
168
|
+
on: OnEvent<THandler>;
|
|
169
|
+
/**
|
|
170
|
+
* Подписывает на событие, однократное выполнение.
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* // Событие изменения состояния.
|
|
174
|
+
* const stateChanged = useEvent()
|
|
175
|
+
* // Подписка на однократное прослушивание события.
|
|
176
|
+
* stateChanged.once(() => { ... })
|
|
177
|
+
* ```
|
|
178
|
+
**/
|
|
179
|
+
once: OnceEvent<THandler>;
|
|
180
|
+
/**
|
|
181
|
+
* Отписывает указанный обработчик от прослушивания события.
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* // Событие изменения состояния.
|
|
185
|
+
* const stateChanged = useEvent()
|
|
186
|
+
* // Обработчик события.
|
|
187
|
+
* function handler() { ... }
|
|
188
|
+
* // Регистрация обработчика.
|
|
189
|
+
* stateChanged.on(handler)
|
|
190
|
+
* // Прекращение прослушивания.
|
|
191
|
+
* stateChanged.off(handler)
|
|
192
|
+
* ```
|
|
193
|
+
**/
|
|
194
|
+
off: (handler: THandler) => void;
|
|
195
|
+
}
|
|
196
|
+
interface EventRaiser<THandler extends EventHandler> extends Event<THandler> {
|
|
197
|
+
/**
|
|
198
|
+
* Объявляет всем подписчикам о наступлении события.
|
|
199
|
+
* @example
|
|
200
|
+
* ```ts
|
|
201
|
+
* // Событие изменения состояния.
|
|
202
|
+
* const stateChanged = useEvent()
|
|
203
|
+
* // Где-то в коде: объявление о наступлении события.
|
|
204
|
+
* stateChanged.raise()
|
|
205
|
+
* ```
|
|
206
|
+
**/
|
|
207
|
+
raise: (...args: Parameters<THandler>) => void;
|
|
208
|
+
withoutRaise: () => Event<THandler>;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Построитель экземпляра события.
|
|
212
|
+
* @example
|
|
213
|
+
* ```ts
|
|
214
|
+
* // Событие без передачи аргументов.
|
|
215
|
+
* const stateChanged = useEvent()
|
|
216
|
+
* // Регистрация обработчика события.
|
|
217
|
+
* stateChanged.on(() => { ... })
|
|
218
|
+
* // Генерация события.
|
|
219
|
+
* stateChanged.raise()
|
|
220
|
+
* ```
|
|
221
|
+
* @example
|
|
222
|
+
* ```ts
|
|
223
|
+
* // Тип обработчика события.
|
|
224
|
+
* type CountEventHandler = (value: number) => void
|
|
225
|
+
* // Событие с передачей типа обработчика.
|
|
226
|
+
* const countChanged = useEvent<CountEventHandler>()
|
|
227
|
+
* // Регистрация обработчика события.
|
|
228
|
+
* countChanged.on((value) => { ... })
|
|
229
|
+
* // Генерация события.
|
|
230
|
+
* countChanged.raise(100)
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
declare function useEvent<THandler extends EventHandler>(): EventRaiser<THandler>;
|
|
234
|
+
|
|
235
|
+
export { debounce, isBoolean, isFunction, isNumber, isObject, isPlainObject, isString, mqttToBoolean, throttle, useEvent };
|
|
236
|
+
export type { Event, EventHandler, EventRaiser, OnEvent, OnceEvent };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { i as isString, a as isNumber } from './guards.mjs';
|
|
2
|
+
export { b as isBoolean, c as isFunction, d as isObject, e as isPlainObject } from './guards.mjs';
|
|
3
|
+
|
|
1
4
|
const { now } = Date;
|
|
2
5
|
const { min, max } = Math;
|
|
3
6
|
function debounce(callback, wait, options = {}) {
|
|
@@ -91,14 +94,6 @@ function throttle(callback, wait, options = {}) {
|
|
|
91
94
|
});
|
|
92
95
|
}
|
|
93
96
|
|
|
94
|
-
/** Сужает диапазон множества типов до string */
|
|
95
|
-
const isString = (value) => typeof value === 'string';
|
|
96
|
-
/** Сужает диапазон множества типов до number */
|
|
97
|
-
const isNumber = (value) => typeof value === 'number';
|
|
98
|
-
/** Сужает диапазон множества типов до boolean */
|
|
99
|
-
const isBoolean = (value) => typeof value === 'boolean';
|
|
100
|
-
const isFunction = (value) => typeof value === 'function';
|
|
101
|
-
|
|
102
97
|
const mqttToBoolean = (value) => {
|
|
103
98
|
if (isString(value))
|
|
104
99
|
return !['', '0', 'off', 'false'].includes(value);
|
|
@@ -172,4 +167,4 @@ function useEvent() {
|
|
|
172
167
|
};
|
|
173
168
|
}
|
|
174
169
|
|
|
175
|
-
export { debounce,
|
|
170
|
+
export { debounce, isNumber, isString, mqttToBoolean, throttle, useEvent };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Результат рекурсивного объединения `TBase` и `TPatch`.
|
|
3
|
+
* Поля из `TPatch` переопределяют поля из `TBase`.
|
|
4
|
+
* Вложенные объекты объединяются, остальные значения — заменяются.
|
|
5
|
+
*
|
|
6
|
+
* @template TBase - Тип базового объекта.
|
|
7
|
+
* @template TPatch - Тип объекта с изменениями.
|
|
8
|
+
*
|
|
9
|
+
* @since 0.4.0
|
|
10
|
+
*
|
|
11
|
+
**/
|
|
12
|
+
type DeepMerged<TBase, TPatch> = [TBase, TPatch] extends [object, object] ? {
|
|
13
|
+
[K in keyof TBase | keyof TPatch]: K extends keyof TPatch ? TPatch[K] extends object ? K extends keyof TBase ? TBase[K] extends object ? DeepMerged<TBase[K], TPatch[K]> : TPatch[K] : TPatch[K] : TPatch[K] : K extends keyof TBase ? TBase[K] : never;
|
|
14
|
+
} : TBase;
|
|
15
|
+
/**
|
|
16
|
+
* Рекурсивно объединяет базовый объект с патчем.
|
|
17
|
+
*
|
|
18
|
+
* - Вложенные объекты — объединяются,
|
|
19
|
+
* - Массивы, примитивы — заменяются целиком,
|
|
20
|
+
* - Не мутирует аргументы `base` и `patch`,
|
|
21
|
+
* - Если `patch` равен `null` или `undefined`, возвращает копию `base`.
|
|
22
|
+
*
|
|
23
|
+
* Для поверхностного объединения используйте {@link merge}.
|
|
24
|
+
*
|
|
25
|
+
* @param base - Объект, с которого начинается объединение.
|
|
26
|
+
* @param patch - Набор изменений (допускает `null` или `undefined`).
|
|
27
|
+
* @returns Новый объект — результат объединения.
|
|
28
|
+
*
|
|
29
|
+
* @throws {TypeError} Если `base` не является объектом.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* deepMerge({ a: { b: 1 } }, { a: { c: 2 } })
|
|
33
|
+
* // → { a: { b: 1, c: 2 } }
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* deepMerge({ x: 1 }, null)
|
|
37
|
+
* // → { x: 1 }
|
|
38
|
+
*
|
|
39
|
+
* @since 0.4.0
|
|
40
|
+
*
|
|
41
|
+
**/
|
|
42
|
+
declare function deepMerge<TBase extends object, TPatch extends object | null | undefined>(base: TBase, patch: TPatch): DeepMerged<TBase, TPatch>;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Проверяет, является ли тип настоящим объектом (не `null`, не примитив).
|
|
46
|
+
* Фильтрует `null`, так как `null extends object` в TS.
|
|
47
|
+
*
|
|
48
|
+
* @template T - Входной тип.
|
|
49
|
+
*
|
|
50
|
+
* @since 0.4.0
|
|
51
|
+
*
|
|
52
|
+
**/
|
|
53
|
+
type IsObject<TValue> = TValue extends object ? (TValue extends null ? never : TValue) : never;
|
|
54
|
+
/**
|
|
55
|
+
* Заменяет свойства из `TBase` на свойства из `TPatch` по ключам.
|
|
56
|
+
* Оставляет несовпадающие свойства из `TBase`, добавляет новые из `TPatch`.
|
|
57
|
+
*
|
|
58
|
+
* Эквивалент `Omit<TBase, keyof TPatch> & TPatch`, но с `Expand`.
|
|
59
|
+
*
|
|
60
|
+
* @template TBase - Базовый тип.
|
|
61
|
+
* @template TPatch - Тип с переопределяющими полями.
|
|
62
|
+
*
|
|
63
|
+
* @since 0.4.0
|
|
64
|
+
*
|
|
65
|
+
**/
|
|
66
|
+
type Overwrite<TBase, TPatch> = Expand<Omit<TBase, keyof TPatch> & TPatch>;
|
|
67
|
+
/**
|
|
68
|
+
* Рекурсивно вычисляет тип результата слияния кортежа объектов слева направо.
|
|
69
|
+
* Игнорирует `null` и `undefined`, объединяя только объекты.
|
|
70
|
+
* Поля из правых объектов переопределяют поля из левых.
|
|
71
|
+
*
|
|
72
|
+
* @template TList - readonly кортеж из объектов, `null` или `undefined`.
|
|
73
|
+
*
|
|
74
|
+
* @since 0.4.0
|
|
75
|
+
*
|
|
76
|
+
**/
|
|
77
|
+
type MergeList<TList> = TList extends readonly [infer Head, ...infer Tail] ? Head extends IsObject<Head> ? Expand<Overwrite<MergeList<Tail>, Head>> : MergeList<Tail> : {};
|
|
78
|
+
/**
|
|
79
|
+
* Тип результата `merge`: объединение списка объектов с приоритетом правых полей.
|
|
80
|
+
* Поля из последующих объектов переопределяют уже существующие.
|
|
81
|
+
*
|
|
82
|
+
* @template TList - Кортеж аргументов типа `(object | null | undefined)[]`.
|
|
83
|
+
* @returns Итоговый тип после поверхностного слияния.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
*
|
|
87
|
+
* ```ts
|
|
88
|
+
* type Result = Merged<[{ a: 1 }, { a: 2; b: 2 }]>
|
|
89
|
+
* // → { a: 2; b: 2 }
|
|
90
|
+
* ```
|
|
91
|
+
* @since 0.4.0
|
|
92
|
+
*
|
|
93
|
+
**/
|
|
94
|
+
type Merged<TList> = Expand<MergeList<TList>>;
|
|
95
|
+
/**
|
|
96
|
+
* Поверхностно копирует значения всех собственных перечисляемых свойств
|
|
97
|
+
* из одного и более исходных объектов в новый.
|
|
98
|
+
*
|
|
99
|
+
* Поля последующих объектов переопределяют предыдущие.
|
|
100
|
+
*
|
|
101
|
+
* Особенности:
|
|
102
|
+
* - Игнорирует `null` и `undefined` в списке аргументов,
|
|
103
|
+
* - Не мутирует исходные объекты.
|
|
104
|
+
*
|
|
105
|
+
* Для рекурсивного объединения вложенных свойств используйте {@link deepMerge}.
|
|
106
|
+
*
|
|
107
|
+
* @param objects - Список исходных объектов.
|
|
108
|
+
* @returns Новый объект — результат объединения.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
*
|
|
112
|
+
* ```ts
|
|
113
|
+
* const a = { x: 1, y: 2 }
|
|
114
|
+
* const b = null
|
|
115
|
+
* const c = { y: 3, z: 4 }
|
|
116
|
+
*
|
|
117
|
+
* const result = merge(a, b, c)
|
|
118
|
+
* // → { x: 1, y: 3, z: 4 }
|
|
119
|
+
* ```
|
|
120
|
+
* @example
|
|
121
|
+
*
|
|
122
|
+
* ```ts
|
|
123
|
+
* merge({ a: 1 }, { a: 2 }, { a: undefined })
|
|
124
|
+
* // → { a: undefined }
|
|
125
|
+
* ```
|
|
126
|
+
* @example
|
|
127
|
+
*
|
|
128
|
+
* ```ts
|
|
129
|
+
* merge()
|
|
130
|
+
* // → {}
|
|
131
|
+
* ```
|
|
132
|
+
* @since 0.4.0
|
|
133
|
+
*
|
|
134
|
+
**/
|
|
135
|
+
declare function merge<TList extends readonly (object | null | undefined)[]>(...objects: TList): Merged<TList>;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Проверяет, содержит ли объект указанное собственное свойство.
|
|
139
|
+
*
|
|
140
|
+
* Метод обходит цепочку прототипов и возвращает `true` только в том случае,
|
|
141
|
+
* если свойство существует непосредственно в самом объекте, а не унаследовано.
|
|
142
|
+
*
|
|
143
|
+
* @param target - Объект, в котором выполняется проверка.
|
|
144
|
+
* @param key - Имя свойства, которое необходимо проверить.
|
|
145
|
+
* @returns `true`, если объект имеет указанное собственное свойство; иначе `false`.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
*
|
|
149
|
+
* ```ts
|
|
150
|
+
* const obj = { key: 'value' };
|
|
151
|
+
* hasOwn(obj, 'key'); // true
|
|
152
|
+
* hasOwn(obj, 'toString'); // false (унаследованное свойство)
|
|
153
|
+
* ```
|
|
154
|
+
*
|
|
155
|
+
* @since 0.4.0
|
|
156
|
+
*
|
|
157
|
+
**/
|
|
158
|
+
declare function hasOwn(target: object, key: PropertyKey): boolean;
|
|
159
|
+
|
|
160
|
+
export { deepMerge, hasOwn, merge };
|
|
161
|
+
export type { DeepMerged, Merged };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { d as isObject, e as isPlainObject } from '../guards.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Проверяет, содержит ли объект указанное собственное свойство.
|
|
5
|
+
*
|
|
6
|
+
* Метод обходит цепочку прототипов и возвращает `true` только в том случае,
|
|
7
|
+
* если свойство существует непосредственно в самом объекте, а не унаследовано.
|
|
8
|
+
*
|
|
9
|
+
* @param target - Объект, в котором выполняется проверка.
|
|
10
|
+
* @param key - Имя свойства, которое необходимо проверить.
|
|
11
|
+
* @returns `true`, если объект имеет указанное собственное свойство; иначе `false`.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* const obj = { key: 'value' };
|
|
17
|
+
* hasOwn(obj, 'key'); // true
|
|
18
|
+
* hasOwn(obj, 'toString'); // false (унаследованное свойство)
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @since 0.4.0
|
|
22
|
+
*
|
|
23
|
+
**/
|
|
24
|
+
function hasOwn(target, key) {
|
|
25
|
+
return Object.prototype.hasOwnProperty
|
|
26
|
+
.call(target, key);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function deepMerge(base, patch) {
|
|
30
|
+
if (!isObject(base))
|
|
31
|
+
throw new TypeError('[deepMerge] first argument must be an object');
|
|
32
|
+
const output = { ...base };
|
|
33
|
+
if (patch == null || typeof patch !== 'object')
|
|
34
|
+
return output;
|
|
35
|
+
for (const key in patch) {
|
|
36
|
+
if (!hasOwn(patch, key))
|
|
37
|
+
continue;
|
|
38
|
+
const fromBase = output[key];
|
|
39
|
+
const fromPatch = patch[key];
|
|
40
|
+
if (isPlainObject(fromBase) && isPlainObject(fromPatch)) {
|
|
41
|
+
output[key] = deepMerge(fromBase, fromPatch);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
output[key] = fromPatch;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return output;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function merge(...objects) {
|
|
51
|
+
if (objects.length === 0)
|
|
52
|
+
return {};
|
|
53
|
+
return objects.reduce((base, patch) => (patch ? { ...base, ...patch } : base), {});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { deepMerge, hasOwn, merge };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mirta/basics",
|
|
3
|
-
"description": "Utility functions providing core functionality for the Mirta Framework
|
|
4
|
-
"version": "0.
|
|
3
|
+
"description": "Utility functions providing core functionality for the Mirta Framework",
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"license": "Unlicense",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mirta",
|
|
@@ -13,14 +13,38 @@
|
|
|
13
13
|
"LICENSE",
|
|
14
14
|
"README.md"
|
|
15
15
|
],
|
|
16
|
+
"types": "./dist/index.d.mts",
|
|
16
17
|
"exports": {
|
|
17
18
|
".": {
|
|
18
19
|
"import": {
|
|
19
|
-
"types": "./dist/index.d.
|
|
20
|
+
"types": "./dist/index.d.mts",
|
|
20
21
|
"default": "./dist/index.mjs"
|
|
21
22
|
}
|
|
23
|
+
},
|
|
24
|
+
"./fuzzy": {
|
|
25
|
+
"import": {
|
|
26
|
+
"types": "./dist/fuzzy/index.d.mts",
|
|
27
|
+
"default": "./dist/fuzzy/index.mjs"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"./array": {
|
|
31
|
+
"import": {
|
|
32
|
+
"types": "./dist/array/index.d.mts",
|
|
33
|
+
"default": "./dist/array/index.mjs"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"./object": {
|
|
37
|
+
"import": {
|
|
38
|
+
"types": "./dist/object/index.d.mts",
|
|
39
|
+
"default": "./dist/object/index.mjs"
|
|
40
|
+
}
|
|
22
41
|
}
|
|
23
42
|
},
|
|
43
|
+
"imports": {
|
|
44
|
+
"#src/*": "./src/*.js",
|
|
45
|
+
"#src/object/*": "./src/object/*.js",
|
|
46
|
+
"#array/*": "./src/array/*.js"
|
|
47
|
+
},
|
|
24
48
|
"homepage": "https://github.com/wb-mirta/core/tree/latest/packages/mirta-basics#readme",
|
|
25
49
|
"repository": {
|
|
26
50
|
"type": "git",
|
|
@@ -31,7 +55,6 @@
|
|
|
31
55
|
"url": "https://github.com/wb-mirta/core/issues"
|
|
32
56
|
},
|
|
33
57
|
"scripts": {
|
|
34
|
-
"
|
|
35
|
-
"build:mono": "pnpm clean && rollup -c node:@mirta/rollup/config --config-package"
|
|
58
|
+
"build:mono": "rollup -c node:@mirta/rollup/config-package"
|
|
36
59
|
}
|
|
37
60
|
}
|
package/dist/index.d.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
interface DebounceOptions {
|
|
2
|
-
leading?: boolean;
|
|
3
|
-
trailing?: boolean;
|
|
4
|
-
maxWait?: number;
|
|
5
|
-
}
|
|
6
|
-
interface DebouncedFunc<TArgs extends unknown[]> {
|
|
7
|
-
(...args: TArgs): void;
|
|
8
|
-
cancel(): void;
|
|
9
|
-
flush(): void;
|
|
10
|
-
}
|
|
11
|
-
interface ThrottleOptions {
|
|
12
|
-
leading?: boolean;
|
|
13
|
-
trailing?: boolean;
|
|
14
|
-
}
|
|
15
|
-
interface ThrottledFunc<TArgs extends unknown[]> {
|
|
16
|
-
(...args: TArgs): void;
|
|
17
|
-
cancel(): void;
|
|
18
|
-
flush(): void;
|
|
19
|
-
}
|
|
20
|
-
declare function debounce<TArgs extends unknown[]>(callback: (...args: TArgs) => void, wait: number, options?: DebounceOptions): DebouncedFunc<TArgs>;
|
|
21
|
-
declare function throttle<TArgs extends unknown[]>(callback: (...args: TArgs) => void, wait: number, options?: ThrottleOptions): ThrottledFunc<TArgs>;
|
|
22
|
-
|
|
23
|
-
/** Сужает диапазон множества типов до string */
|
|
24
|
-
declare const isString: (value: unknown) => value is string;
|
|
25
|
-
/** Сужает диапазон множества типов до number */
|
|
26
|
-
declare const isNumber: (value: unknown) => value is number;
|
|
27
|
-
/** Сужает диапазон множества типов до boolean */
|
|
28
|
-
declare const isBoolean: (value: unknown) => value is boolean;
|
|
29
|
-
declare const isFunction: (value: unknown) => value is ((...args: unknown[]) => unknown);
|
|
30
|
-
|
|
31
|
-
declare const mqttToBoolean: (value: WbRules.MqttValue) => boolean;
|
|
32
|
-
|
|
33
|
-
type EventHandler = (...args: unknown[]) => void;
|
|
34
|
-
type OnEvent<THandler extends EventHandler> = (handler: THandler) => {
|
|
35
|
-
off: () => void;
|
|
36
|
-
};
|
|
37
|
-
type OnceEvent<THandler extends EventHandler> = (handler: THandler) => void;
|
|
38
|
-
interface Event<THandler extends EventHandler> {
|
|
39
|
-
/**
|
|
40
|
-
* Подписывает на событие, есть возможность отписки.
|
|
41
|
-
* @example
|
|
42
|
-
* ```ts
|
|
43
|
-
* // Событие изменения состояния.
|
|
44
|
-
* const stateChanged = useEvent()
|
|
45
|
-
* // Подписка на прослушивание события.
|
|
46
|
-
* const subscription = stateChanged.on(() => { ... })
|
|
47
|
-
* // Отписка от прослушивания события.
|
|
48
|
-
* subscription.off()
|
|
49
|
-
* ```
|
|
50
|
-
**/
|
|
51
|
-
on: OnEvent<THandler>;
|
|
52
|
-
/**
|
|
53
|
-
* Подписывает на событие, однократное выполнение.
|
|
54
|
-
* @example
|
|
55
|
-
* ```ts
|
|
56
|
-
* // Событие изменения состояния.
|
|
57
|
-
* const stateChanged = useEvent()
|
|
58
|
-
* // Подписка на однократное прослушивание события.
|
|
59
|
-
* stateChanged.once(() => { ... })
|
|
60
|
-
* ```
|
|
61
|
-
**/
|
|
62
|
-
once: OnceEvent<THandler>;
|
|
63
|
-
/**
|
|
64
|
-
* Отписывает указанный обработчик от прослушивания события.
|
|
65
|
-
* @example
|
|
66
|
-
* ```ts
|
|
67
|
-
* // Событие изменения состояния.
|
|
68
|
-
* const stateChanged = useEvent()
|
|
69
|
-
* // Обработчик события.
|
|
70
|
-
* function handler() { ... }
|
|
71
|
-
* // Регистрация обработчика.
|
|
72
|
-
* stateChanged.on(handler)
|
|
73
|
-
* // Прекращение прослушивания.
|
|
74
|
-
* stateChanged.off(handler)
|
|
75
|
-
* ```
|
|
76
|
-
**/
|
|
77
|
-
off: (handler: THandler) => void;
|
|
78
|
-
}
|
|
79
|
-
interface EventRaiser<THandler extends EventHandler> extends Event<THandler> {
|
|
80
|
-
/**
|
|
81
|
-
* Объявляет всем подписчикам о наступлении события.
|
|
82
|
-
* @example
|
|
83
|
-
* ```ts
|
|
84
|
-
* // Событие изменения состояния.
|
|
85
|
-
* const stateChanged = useEvent()
|
|
86
|
-
* // Где-то в коде: объявление о наступлении события.
|
|
87
|
-
* stateChanged.raise()
|
|
88
|
-
* ```
|
|
89
|
-
**/
|
|
90
|
-
raise: (...args: Parameters<THandler>) => void;
|
|
91
|
-
withoutRaise: () => Event<THandler>;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Построитель экземпляра события.
|
|
95
|
-
* @example
|
|
96
|
-
* ```ts
|
|
97
|
-
* // Событие без передачи аргументов.
|
|
98
|
-
* const stateChanged = useEvent()
|
|
99
|
-
* // Регистрация обработчика события.
|
|
100
|
-
* stateChanged.on(() => { ... })
|
|
101
|
-
* // Генерация события.
|
|
102
|
-
* stateChanged.raise()
|
|
103
|
-
* ```
|
|
104
|
-
* @example
|
|
105
|
-
* ```ts
|
|
106
|
-
* // Тип обработчика события.
|
|
107
|
-
* type CountEventHandler = (value: number) => void
|
|
108
|
-
* // Событие с передачей типа обработчика.
|
|
109
|
-
* const countChanged = useEvent<CountEventHandler>()
|
|
110
|
-
* // Регистрация обработчика события.
|
|
111
|
-
* countChanged.on((value) => { ... })
|
|
112
|
-
* // Генерация события.
|
|
113
|
-
* countChanged.raise(100)
|
|
114
|
-
* ```
|
|
115
|
-
*/
|
|
116
|
-
declare function useEvent<THandler extends EventHandler>(): EventRaiser<THandler>;
|
|
117
|
-
|
|
118
|
-
export { debounce, isBoolean, isFunction, isNumber, isString, mqttToBoolean, throttle, useEvent };
|
|
119
|
-
export type { Event, EventHandler, EventRaiser, OnEvent, OnceEvent };
|