@nemigo/helpers 0.3.3 → 0.4.1
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/cookie.d.ts +60 -0
- package/dist/cookie.js +48 -0
- package/dist/datetime.js +1 -3
- package/dist/emitter.d.ts +28 -0
- package/dist/emitter.js +33 -0
- package/dist/explorer.d.ts +66 -0
- package/dist/explorer.js +63 -1
- package/dist/files.d.ts +13 -0
- package/dist/files.js +35 -0
- package/dist/future.d.ts +50 -0
- package/dist/future.js +59 -0
- package/dist/html.d.ts +25 -0
- package/dist/html.js +31 -0
- package/dist/humanly.d.ts +4 -0
- package/dist/humanly.js +47 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +18 -0
- package/dist/lru.d.ts +77 -0
- package/dist/lru.js +128 -0
- package/dist/omitter.d.ts +86 -0
- package/dist/omitter.js +92 -0
- package/dist/phymath.d.ts +10 -0
- package/dist/phymath.js +11 -0
- package/dist/phymath.types.d.ts +34 -0
- package/dist/phymath.types.js +1 -0
- package/dist/promoter.d.ts +22 -0
- package/dist/promoter.js +33 -0
- package/dist/types.d.ts +3 -0
- package/dist/zipper.d.ts +12 -0
- package/dist/zipper.js +19 -0
- package/package.json +33 -1
package/dist/lru.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { RID } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* LRU (Least Recently Used) кэш с поддержкой TTL (time-to-live)
|
|
4
|
+
*
|
|
5
|
+
* Элементы кэша удаляются при превышении максимального размера либо по истечении заданного TTL.
|
|
6
|
+
* TTL для каждого элемента можно задать как глобально при создании кэша, так и индивидуально при установке
|
|
7
|
+
*
|
|
8
|
+
* @template V - Тип значения для кэша
|
|
9
|
+
* @template K - Тип ключа для кэша
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const lruCache = new LRU<string, number>(2, 5); // Глобальный TTL 5 минут
|
|
13
|
+
* lruCache.set('one', 1);
|
|
14
|
+
* lruCache.set('two', 2);
|
|
15
|
+
* lruCache.set('three', 3); // Если кэш переполнен, удалится наименее недавно использованный или устаревший элемент
|
|
16
|
+
* console.log(lruCache.get('one')); // undefined, если значение устарело или удалено
|
|
17
|
+
* console.log(lruCache.get('two')); // 2
|
|
18
|
+
*/
|
|
19
|
+
export declare class LRU<V = unknown, K extends RID = string> {
|
|
20
|
+
/**
|
|
21
|
+
* Максимальное количество элементов в кэше
|
|
22
|
+
*/
|
|
23
|
+
private readonly max;
|
|
24
|
+
/**
|
|
25
|
+
* Глобальный TTL (time-to-live) для каждого элемента в {@link Timestamp}.
|
|
26
|
+
* Если не задан (`undefined`), элементы не устаревают глобально
|
|
27
|
+
*/
|
|
28
|
+
private readonly ttl?;
|
|
29
|
+
/**
|
|
30
|
+
* Внутреннее хранилище кэша.
|
|
31
|
+
* Хранит значения вместе с информацией о времени истечения срока их действия
|
|
32
|
+
*/
|
|
33
|
+
private readonly cache;
|
|
34
|
+
/**
|
|
35
|
+
* @param [max=200] - Максимальное количество элементов в кэше
|
|
36
|
+
* @param ttl - Глобальный TTL (time-to-live) для каждого элемента в **минутах**
|
|
37
|
+
* Если не задан, элементы не устаревают глобально
|
|
38
|
+
*/
|
|
39
|
+
constructor(max?: number, ttl?: number);
|
|
40
|
+
/**
|
|
41
|
+
* Перевод минут в {@link Timestamp}
|
|
42
|
+
*/
|
|
43
|
+
private toTimeStamp;
|
|
44
|
+
/**
|
|
45
|
+
* Проверяет, устарел ли элемент кэша
|
|
46
|
+
*
|
|
47
|
+
* @param entry - Элемент кэша для проверки
|
|
48
|
+
* @returns `true`, если элемент устарел, иначе `false`
|
|
49
|
+
*/
|
|
50
|
+
private isExpired;
|
|
51
|
+
/**
|
|
52
|
+
* Получает значение из кэша по ключу
|
|
53
|
+
*
|
|
54
|
+
* - Если элемент найден и не устарел, он перемещается в конец кэша (обновляется порядок использования)
|
|
55
|
+
* - Если элемент устарел, он удаляется, и возвращается `undefined`
|
|
56
|
+
*
|
|
57
|
+
* @param key - Ключ для получения значения
|
|
58
|
+
* @returns Значение из кэша или `undefined`, если ключ отсутствует или значение устарело
|
|
59
|
+
*/
|
|
60
|
+
get(key: K): V | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Устанавливает значение в кэш
|
|
63
|
+
*
|
|
64
|
+
* - Если ключ уже существует, его значение обновляется и перемещается в конец
|
|
65
|
+
* - Если размер кэша превышает максимальное значение, производится очистка устаревших элементов
|
|
66
|
+
* - Если после очистки кэш все еще переполнен, удаляется наименее недавно использованный элемент
|
|
67
|
+
*
|
|
68
|
+
* @param key - Ключ для установки значения
|
|
69
|
+
* @param value - Значение для установки в кэш
|
|
70
|
+
* @param ttl - Индивидуальный TTL для данного элемента в **минутах**. Если не задан, используется TTL экземпляра, если он установлен
|
|
71
|
+
*/
|
|
72
|
+
set(key: K, value: V, ttl?: number): void;
|
|
73
|
+
/**
|
|
74
|
+
* Очищает кэш
|
|
75
|
+
*/
|
|
76
|
+
clear(key?: K): void;
|
|
77
|
+
}
|
package/dist/lru.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LRU (Least Recently Used) кэш с поддержкой TTL (time-to-live)
|
|
3
|
+
*
|
|
4
|
+
* Элементы кэша удаляются при превышении максимального размера либо по истечении заданного TTL.
|
|
5
|
+
* TTL для каждого элемента можно задать как глобально при создании кэша, так и индивидуально при установке
|
|
6
|
+
*
|
|
7
|
+
* @template V - Тип значения для кэша
|
|
8
|
+
* @template K - Тип ключа для кэша
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const lruCache = new LRU<string, number>(2, 5); // Глобальный TTL 5 минут
|
|
12
|
+
* lruCache.set('one', 1);
|
|
13
|
+
* lruCache.set('two', 2);
|
|
14
|
+
* lruCache.set('three', 3); // Если кэш переполнен, удалится наименее недавно использованный или устаревший элемент
|
|
15
|
+
* console.log(lruCache.get('one')); // undefined, если значение устарело или удалено
|
|
16
|
+
* console.log(lruCache.get('two')); // 2
|
|
17
|
+
*/
|
|
18
|
+
export class LRU {
|
|
19
|
+
/**
|
|
20
|
+
* Максимальное количество элементов в кэше
|
|
21
|
+
*/
|
|
22
|
+
max;
|
|
23
|
+
/**
|
|
24
|
+
* Глобальный TTL (time-to-live) для каждого элемента в {@link Timestamp}.
|
|
25
|
+
* Если не задан (`undefined`), элементы не устаревают глобально
|
|
26
|
+
*/
|
|
27
|
+
ttl;
|
|
28
|
+
/**
|
|
29
|
+
* Внутреннее хранилище кэша.
|
|
30
|
+
* Хранит значения вместе с информацией о времени истечения срока их действия
|
|
31
|
+
*/
|
|
32
|
+
cache;
|
|
33
|
+
/**
|
|
34
|
+
* @param [max=200] - Максимальное количество элементов в кэше
|
|
35
|
+
* @param ttl - Глобальный TTL (time-to-live) для каждого элемента в **минутах**
|
|
36
|
+
* Если не задан, элементы не устаревают глобально
|
|
37
|
+
*/
|
|
38
|
+
constructor(max = 200, ttl) {
|
|
39
|
+
this.max = max;
|
|
40
|
+
if (ttl)
|
|
41
|
+
this.ttl = this.toTimeStamp(ttl);
|
|
42
|
+
this.cache = new Map();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Перевод минут в {@link Timestamp}
|
|
46
|
+
*/
|
|
47
|
+
toTimeStamp(min) {
|
|
48
|
+
return min * 60 * 1000;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Проверяет, устарел ли элемент кэша
|
|
52
|
+
*
|
|
53
|
+
* @param entry - Элемент кэша для проверки
|
|
54
|
+
* @returns `true`, если элемент устарел, иначе `false`
|
|
55
|
+
*/
|
|
56
|
+
isExpired(entry) {
|
|
57
|
+
return Boolean(entry.expired && Date.now() > entry.expired);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Получает значение из кэша по ключу
|
|
61
|
+
*
|
|
62
|
+
* - Если элемент найден и не устарел, он перемещается в конец кэша (обновляется порядок использования)
|
|
63
|
+
* - Если элемент устарел, он удаляется, и возвращается `undefined`
|
|
64
|
+
*
|
|
65
|
+
* @param key - Ключ для получения значения
|
|
66
|
+
* @returns Значение из кэша или `undefined`, если ключ отсутствует или значение устарело
|
|
67
|
+
*/
|
|
68
|
+
get(key) {
|
|
69
|
+
const entry = this.cache.get(key);
|
|
70
|
+
if (!entry)
|
|
71
|
+
return undefined;
|
|
72
|
+
// Если элемент устарел, удаляем его и возвращаем undefined
|
|
73
|
+
if (this.isExpired(entry)) {
|
|
74
|
+
this.cache.delete(key);
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
// Обновляем порядок использования: удаляем и добавляем элемент в конец
|
|
78
|
+
this.cache.delete(key);
|
|
79
|
+
this.cache.set(key, entry);
|
|
80
|
+
return entry.value;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Устанавливает значение в кэш
|
|
84
|
+
*
|
|
85
|
+
* - Если ключ уже существует, его значение обновляется и перемещается в конец
|
|
86
|
+
* - Если размер кэша превышает максимальное значение, производится очистка устаревших элементов
|
|
87
|
+
* - Если после очистки кэш все еще переполнен, удаляется наименее недавно использованный элемент
|
|
88
|
+
*
|
|
89
|
+
* @param key - Ключ для установки значения
|
|
90
|
+
* @param value - Значение для установки в кэш
|
|
91
|
+
* @param ttl - Индивидуальный TTL для данного элемента в **минутах**. Если не задан, используется TTL экземпляра, если он установлен
|
|
92
|
+
*/
|
|
93
|
+
set(key, value, ttl) {
|
|
94
|
+
// Если ключ уже существует, удаляем его для обновления порядка использования
|
|
95
|
+
if (this.cache.has(key))
|
|
96
|
+
this.cache.delete(key);
|
|
97
|
+
else {
|
|
98
|
+
if (this.cache.size >= this.max) {
|
|
99
|
+
// Если кэш достиг максимального размера, пробегаем по ключам и удаляем устаревшие элементы
|
|
100
|
+
for (const key of this.cache.keys()) {
|
|
101
|
+
const entry = this.cache.get(key);
|
|
102
|
+
if (!entry || this.isExpired(entry)) {
|
|
103
|
+
this.cache.delete(key);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Если после очистки устаревших значений кэш все еще переполнен, удаляем первый (наименее недавно использованный) элемент
|
|
107
|
+
if (this.cache.size >= this.max) {
|
|
108
|
+
const first = this.cache.keys().next().value;
|
|
109
|
+
if (first !== undefined)
|
|
110
|
+
this.cache.delete(first);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Вычисляем время истечения для данного элемента
|
|
115
|
+
// prettier-ignore
|
|
116
|
+
const expired = ttl ? (Date.now() + this.toTimeStamp(ttl)) : (this.ttl ? (Date.now() + this.ttl) : undefined);
|
|
117
|
+
this.cache.set(key, { value, expired });
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Очищает кэш
|
|
121
|
+
*/
|
|
122
|
+
clear(key) {
|
|
123
|
+
if (key)
|
|
124
|
+
this.cache.delete(key);
|
|
125
|
+
else
|
|
126
|
+
this.cache.clear();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { DeepPartial, KEYS } from "./types.js";
|
|
2
|
+
import type { ZIP } from "./zipper.js";
|
|
3
|
+
/**
|
|
4
|
+
* Исключает ключи из объекта `Source`, которые присутствуют в объекте `Target`.
|
|
5
|
+
* Если значение ключа в `Source` и `Target` является объектом, рекурсивно применяет `OmitKEYS` к этим объектам
|
|
6
|
+
*
|
|
7
|
+
* @template Source - Исходный объект, из которого нужно исключить ключи
|
|
8
|
+
* @template Target - Объект, ключи которого нужно исключить из `Source`
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* type Source = { a: number; b: { c: string; d: boolean }; e: string };
|
|
12
|
+
* type Target = { b: { c: string }; e: string };
|
|
13
|
+
* type Result = ExtractOmitSchema<Source, Target>; // { a: number; b: { d: boolean } }
|
|
14
|
+
*/
|
|
15
|
+
export type ExtractOmitSchema<Source, Target extends DeepPartial<Source>> = {
|
|
16
|
+
[K in keyof Source as K extends keyof Target ? Source[K] extends Record<string, unknown> ? Target[K] extends Record<string, unknown> ? K : never : never : K]: K extends keyof Target ? Source[K] extends Record<string, unknown> ? Target[K] extends Record<string, unknown> & DeepPartial<Source[K]> ? ExtractOmitSchema<Source[K], Target[K]> : never : never : null;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Вычисляет тип Target на основе исходного типа Source и схемы удаления OmitSchema.
|
|
20
|
+
* Удаляет ключи, помеченные в схеме как null, и рекурсивно обрабатывает вложенные объекты
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* type Source = { a: number; b: { c: string; d: boolean }; e: string };
|
|
24
|
+
* type OmitSchema = { a: null; b: { c: null } };
|
|
25
|
+
* type Result = ExtractOmitTarget<Source, OmitSchema>; // { b: { d: boolean }; e: string }
|
|
26
|
+
*/
|
|
27
|
+
export type ExtractOmitTarget<Source, OmitSchema> = {
|
|
28
|
+
[K in keyof Source as K extends keyof OmitSchema ? (OmitSchema[K] extends Record<string, unknown> ? K : never) : K]: K extends keyof OmitSchema ? OmitSchema[K] extends Record<string, unknown> ? ExtractOmitTarget<Source[K], OmitSchema[K]> : never : Source[K];
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Рекурсивно объединяет две схемы удаления ключей.
|
|
32
|
+
* Если ключ присутствует в обеих схемах:
|
|
33
|
+
* - Если оба значения являются объектами — объединяет вложенные схемы
|
|
34
|
+
* - Если хотя бы одно значение null — результат null (приоритет удаления)
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
*
|
|
38
|
+
* type SchemaA = { a: null; b: { c: null } };
|
|
39
|
+
* type SchemaB = { b: { d: null }; e: null };
|
|
40
|
+
*
|
|
41
|
+
* type MergedSchema = MergeOmitSchemas<SchemaA, SchemaB>;
|
|
42
|
+
* // Результат: { a: null; b: { c: null; d: null }; e: null }
|
|
43
|
+
*
|
|
44
|
+
* type ConflictSchema = MergeOmitSchemas<
|
|
45
|
+
* { user: { name: null } },
|
|
46
|
+
* { user: null }
|
|
47
|
+
* >;
|
|
48
|
+
* // Результат: { user: null } (приоритет удаления)
|
|
49
|
+
*/
|
|
50
|
+
export type MergeOmitSchemas<S1, S2> = {
|
|
51
|
+
[K in keyof (S1 & S2)]: K extends keyof S1 ? K extends keyof S2 ? S1[K] extends Record<string, unknown> ? S2[K] extends Record<string, unknown> ? MergeOmitSchemas<S1[K], S2[K]> : null : null : S1[K] : K extends keyof S2 ? S2[K] : never;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Класс для удаления указанных ключей из объекта на основе схемы
|
|
55
|
+
*
|
|
56
|
+
* @template Source - Исходный объект, из которого нужно удалить ключи
|
|
57
|
+
* @template OmitSchema - Схема удаления
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* const source = { a: 1, b: { c: 2, d: 3 }, e: 4 };
|
|
61
|
+
* const schema = { b: { c: null } };
|
|
62
|
+
* const omitter = new Omitter(schema);
|
|
63
|
+
* const result = omitter.run(source); // { a: 1, b: { d: 3 }, e: 4 }
|
|
64
|
+
*/
|
|
65
|
+
export declare class Omitter<Source, OmitSchema> {
|
|
66
|
+
#private;
|
|
67
|
+
private readonly structure;
|
|
68
|
+
readonly schema: OmitSchema;
|
|
69
|
+
readonly zip: ZIP;
|
|
70
|
+
constructor(schema: OmitSchema);
|
|
71
|
+
/**
|
|
72
|
+
* Получение хэша вложенного эмиттера
|
|
73
|
+
*/
|
|
74
|
+
into(key: KEYS<Source>): ZIP | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Проверяет, останется ли ключ в итоговом объекте
|
|
77
|
+
*/
|
|
78
|
+
left(key: KEYS<Source>): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Удаление ключей из объекта
|
|
81
|
+
*
|
|
82
|
+
* @param source - Исходный объект
|
|
83
|
+
* @returns Объект с удалёнными ключами
|
|
84
|
+
*/
|
|
85
|
+
run(source: Source): ExtractOmitTarget<Source, OmitSchema>;
|
|
86
|
+
}
|
package/dist/omitter.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { zipper } from "./zipper.js";
|
|
2
|
+
/**
|
|
3
|
+
* Класс для удаления указанных ключей из объекта на основе схемы
|
|
4
|
+
*
|
|
5
|
+
* @template Source - Исходный объект, из которого нужно удалить ключи
|
|
6
|
+
* @template OmitSchema - Схема удаления
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const source = { a: 1, b: { c: 2, d: 3 }, e: 4 };
|
|
10
|
+
* const schema = { b: { c: null } };
|
|
11
|
+
* const omitter = new Omitter(schema);
|
|
12
|
+
* const result = omitter.run(source); // { a: 1, b: { d: 3 }, e: 4 }
|
|
13
|
+
*/
|
|
14
|
+
export class Omitter {
|
|
15
|
+
structure;
|
|
16
|
+
schema;
|
|
17
|
+
zip;
|
|
18
|
+
constructor(schema) {
|
|
19
|
+
this.zip = zipper(schema);
|
|
20
|
+
this.schema = schema;
|
|
21
|
+
const nested = new Map();
|
|
22
|
+
const keys = new Set(Object.keys(schema).filter((key) => {
|
|
23
|
+
const value = schema[key];
|
|
24
|
+
if (value && typeof value === "object") {
|
|
25
|
+
nested.set(key, new Omitter(value));
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
}));
|
|
30
|
+
this.structure = { keys, nested };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Получение хэша вложенного эмиттера
|
|
34
|
+
*/
|
|
35
|
+
into(key) {
|
|
36
|
+
return this.structure.nested.get(key)?.zip;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Проверяет, останется ли ключ в итоговом объекте
|
|
40
|
+
*/
|
|
41
|
+
left(key) {
|
|
42
|
+
return !this.structure.keys.has(key);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Рекурсивно удаляет ключи из объекта на основе структуры
|
|
46
|
+
*
|
|
47
|
+
* @param obj - Объект, из которого нужно удалить ключи
|
|
48
|
+
* @param structure - Структура, определяющая ключи для удаления
|
|
49
|
+
*/
|
|
50
|
+
#process(obj, structure) {
|
|
51
|
+
const schema = structure.keys.size + structure.nested.size;
|
|
52
|
+
const keys = Object.keys(obj);
|
|
53
|
+
if (schema < keys.length) {
|
|
54
|
+
// Стратегия по схеме: итерируемся по ключам схемы
|
|
55
|
+
structure.keys.forEach((key) => {
|
|
56
|
+
delete obj[key];
|
|
57
|
+
});
|
|
58
|
+
structure.nested.forEach((omitter, key) => {
|
|
59
|
+
const nested = obj[key];
|
|
60
|
+
if (nested && typeof nested === "object")
|
|
61
|
+
omitter.#process(nested, omitter.structure);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// Стратегия по объекту: итерируемся по ключам объекта
|
|
66
|
+
for (const key of keys) {
|
|
67
|
+
if (structure.keys.has(key)) {
|
|
68
|
+
delete obj[key];
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
const omitter = structure.nested.get(key);
|
|
72
|
+
if (omitter) {
|
|
73
|
+
const nested = obj[key];
|
|
74
|
+
if (nested && typeof nested === "object") {
|
|
75
|
+
omitter.#process(nested, omitter.structure);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Удаление ключей из объекта
|
|
84
|
+
*
|
|
85
|
+
* @param source - Исходный объект
|
|
86
|
+
* @returns Объект с удалёнными ключами
|
|
87
|
+
*/
|
|
88
|
+
run(source) {
|
|
89
|
+
this.#process(source, this.structure);
|
|
90
|
+
return source;
|
|
91
|
+
}
|
|
92
|
+
}
|
package/dist/phymath.d.ts
CHANGED
|
@@ -43,3 +43,13 @@ export declare const mult: (...args: number[]) => number;
|
|
|
43
43
|
* @returns {number} Значение, ограниченное диапазоном [min, max]
|
|
44
44
|
*/
|
|
45
45
|
export declare const clamp: (v: number, min: number, max: number) => number;
|
|
46
|
+
/**
|
|
47
|
+
* Линейная интерполяция между двумя числами
|
|
48
|
+
*
|
|
49
|
+
* @param {number} s - Начальное значение
|
|
50
|
+
* @param {number} e - Конечное значение
|
|
51
|
+
* @param {number} t - Весовой коэффициент, определяющий пропорцию между начальным и конечным значениями. Значение должно быть в диапазоне [0, 1]
|
|
52
|
+
*
|
|
53
|
+
* @returns {number} Результат линейной интерполяции между s и e при коэффициенте t
|
|
54
|
+
*/
|
|
55
|
+
export declare const lerp: (s: number, e: number, t: number) => number;
|
package/dist/phymath.js
CHANGED
|
@@ -48,3 +48,14 @@ export const mult = (...args) => toRound(args.reduce((acc, v) => acc * v, 1));
|
|
|
48
48
|
* @returns {number} Значение, ограниченное диапазоном [min, max]
|
|
49
49
|
*/
|
|
50
50
|
export const clamp = (v, min, max) => Math.max(Math.min(v, max), min);
|
|
51
|
+
//...
|
|
52
|
+
/**
|
|
53
|
+
* Линейная интерполяция между двумя числами
|
|
54
|
+
*
|
|
55
|
+
* @param {number} s - Начальное значение
|
|
56
|
+
* @param {number} e - Конечное значение
|
|
57
|
+
* @param {number} t - Весовой коэффициент, определяющий пропорцию между начальным и конечным значениями. Значение должно быть в диапазоне [0, 1]
|
|
58
|
+
*
|
|
59
|
+
* @returns {number} Результат линейной интерполяции между s и e при коэффициенте t
|
|
60
|
+
*/
|
|
61
|
+
export const lerp = (s, e, t) => s * (1 - t) + e * t;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Пространственные характеристики
|
|
3
|
+
*/
|
|
4
|
+
export interface LWH<T = number> {
|
|
5
|
+
/**
|
|
6
|
+
* Длина
|
|
7
|
+
*/
|
|
8
|
+
length: T;
|
|
9
|
+
/**
|
|
10
|
+
* Ширина
|
|
11
|
+
*/
|
|
12
|
+
width: T;
|
|
13
|
+
/**
|
|
14
|
+
* Высота
|
|
15
|
+
*/
|
|
16
|
+
height: T;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Физические характеристики
|
|
20
|
+
*/
|
|
21
|
+
export interface MVD<T = number> {
|
|
22
|
+
/**
|
|
23
|
+
* Масса
|
|
24
|
+
*/
|
|
25
|
+
mass: T;
|
|
26
|
+
/**
|
|
27
|
+
* Объём
|
|
28
|
+
*/
|
|
29
|
+
volume: T;
|
|
30
|
+
/**
|
|
31
|
+
* Плотность
|
|
32
|
+
*/
|
|
33
|
+
density: T;
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RID } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Класс для создания простого механизма подписок
|
|
4
|
+
*/
|
|
5
|
+
export declare class Promoter<Data> {
|
|
6
|
+
private __subs;
|
|
7
|
+
/**
|
|
8
|
+
* Вызывает подписчиков
|
|
9
|
+
*/
|
|
10
|
+
notify(data: Data): void;
|
|
11
|
+
/**
|
|
12
|
+
* Подписка на события
|
|
13
|
+
*/
|
|
14
|
+
sub(call: (data: Data) => void, params?: {
|
|
15
|
+
key?: RID;
|
|
16
|
+
once?: boolean;
|
|
17
|
+
}): () => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Удаляет подписчика по ключу. Если не указан, очищаются все
|
|
20
|
+
*/
|
|
21
|
+
unsub(key?: RID): boolean;
|
|
22
|
+
}
|
package/dist/promoter.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Класс для создания простого механизма подписок
|
|
3
|
+
*/
|
|
4
|
+
export class Promoter {
|
|
5
|
+
__subs = new Map();
|
|
6
|
+
/**
|
|
7
|
+
* Вызывает подписчиков
|
|
8
|
+
*/
|
|
9
|
+
notify(data) {
|
|
10
|
+
this.__subs.forEach(({ call, once }, key) => {
|
|
11
|
+
call(data);
|
|
12
|
+
if (once)
|
|
13
|
+
this.__subs.delete(key);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Подписка на события
|
|
18
|
+
*/
|
|
19
|
+
sub(call, params = {}) {
|
|
20
|
+
const { key = Symbol(), once } = params;
|
|
21
|
+
this.__subs.set(key, { call, once });
|
|
22
|
+
return () => this.__subs.delete(key);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Удаляет подписчика по ключу. Если не указан, очищаются все
|
|
26
|
+
*/
|
|
27
|
+
unsub(key) {
|
|
28
|
+
if (key)
|
|
29
|
+
return this.__subs.delete(key);
|
|
30
|
+
this.__subs.clear();
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
package/dist/types.d.ts
CHANGED
package/dist/zipper.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Уникальный хэш для данных
|
|
3
|
+
*/
|
|
4
|
+
export type ZIP = string;
|
|
5
|
+
/**
|
|
6
|
+
* Полином для {@link zipper}
|
|
7
|
+
*/
|
|
8
|
+
export declare const polynomial: Uint32Array<ArrayBuffer>;
|
|
9
|
+
/**
|
|
10
|
+
* Вдохновлено (а может и является) CRC32
|
|
11
|
+
*/
|
|
12
|
+
export declare function zipper(data?: unknown): ZIP;
|
package/dist/zipper.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Полином для {@link zipper}
|
|
3
|
+
*/
|
|
4
|
+
export const polynomial = Uint32Array.from({ length: 256 }, (_, i) => {
|
|
5
|
+
let crc = i;
|
|
6
|
+
for (let j = 8; j--;)
|
|
7
|
+
crc = (crc >>> 1) ^ (0xedb88320 & -(crc & 1));
|
|
8
|
+
return crc;
|
|
9
|
+
});
|
|
10
|
+
/**
|
|
11
|
+
* Вдохновлено (а может и является) CRC32
|
|
12
|
+
*/
|
|
13
|
+
export function zipper(data = "undefined") {
|
|
14
|
+
const str = JSON.stringify(data);
|
|
15
|
+
let crc = 0 ^ -1;
|
|
16
|
+
for (let i = str.length - 1; i >= 0; i--)
|
|
17
|
+
crc = (crc >>> 8) ^ polynomial[(crc ^ str.charCodeAt(i)) & 0xff];
|
|
18
|
+
return "zi" + ((crc ^ -1) >>> 0).toString(16);
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nemigo/helpers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Vlad Logvin",
|
|
@@ -31,10 +31,18 @@
|
|
|
31
31
|
"types": "./dist/clean.d.ts",
|
|
32
32
|
"default": "./dist/clean.js"
|
|
33
33
|
},
|
|
34
|
+
"./cookie": {
|
|
35
|
+
"types": "./dist/cookie.d.ts",
|
|
36
|
+
"default": "./dist/cookie.js"
|
|
37
|
+
},
|
|
34
38
|
"./datetime": {
|
|
35
39
|
"types": "./dist/datetime.d.ts",
|
|
36
40
|
"default": "./dist/datetime.js"
|
|
37
41
|
},
|
|
42
|
+
"./emitter": {
|
|
43
|
+
"types": "./dist/emitter.d.ts",
|
|
44
|
+
"default": "./dist/emitter.js"
|
|
45
|
+
},
|
|
38
46
|
"./explorer": {
|
|
39
47
|
"types": "./dist/explorer.d.ts",
|
|
40
48
|
"default": "./dist/explorer.js"
|
|
@@ -47,6 +55,10 @@
|
|
|
47
55
|
"types": "./dist/format.d.ts",
|
|
48
56
|
"default": "./dist/format.js"
|
|
49
57
|
},
|
|
58
|
+
"./future": {
|
|
59
|
+
"types": "./dist/future.d.ts",
|
|
60
|
+
"default": "./dist/future.js"
|
|
61
|
+
},
|
|
50
62
|
"./html": {
|
|
51
63
|
"types": "./dist/html.d.ts",
|
|
52
64
|
"default": "./dist/html.js"
|
|
@@ -59,14 +71,30 @@
|
|
|
59
71
|
"types": "./dist/lens.d.ts",
|
|
60
72
|
"default": "./dist/lens.js"
|
|
61
73
|
},
|
|
74
|
+
"./lru": {
|
|
75
|
+
"types": "./dist/lru.d.ts",
|
|
76
|
+
"default": "./dist/lru.js"
|
|
77
|
+
},
|
|
62
78
|
"./msgpack": {
|
|
63
79
|
"types": "./dist/msgpack.d.ts",
|
|
64
80
|
"default": "./dist/msgpack.js"
|
|
65
81
|
},
|
|
82
|
+
"./omitter": {
|
|
83
|
+
"types": "./dist/omitter.d.ts",
|
|
84
|
+
"default": "./dist/omitter.js"
|
|
85
|
+
},
|
|
66
86
|
"./phymath": {
|
|
67
87
|
"types": "./dist/phymath.d.ts",
|
|
68
88
|
"default": "./dist/phymath.js"
|
|
69
89
|
},
|
|
90
|
+
"./phymath/types": {
|
|
91
|
+
"types": "./dist/phymath.types.d.ts",
|
|
92
|
+
"default": "./dist/phymath.types.js"
|
|
93
|
+
},
|
|
94
|
+
"./promoter": {
|
|
95
|
+
"types": "./dist/promoter.d.ts",
|
|
96
|
+
"default": "./dist/promoter.js"
|
|
97
|
+
},
|
|
70
98
|
"./queue": {
|
|
71
99
|
"types": "./dist/queue.d.ts",
|
|
72
100
|
"default": "./dist/queue.js"
|
|
@@ -94,6 +122,10 @@
|
|
|
94
122
|
"./xod": {
|
|
95
123
|
"types": "./dist/xod.d.ts",
|
|
96
124
|
"default": "./dist/xod.js"
|
|
125
|
+
},
|
|
126
|
+
"./zipper": {
|
|
127
|
+
"types": "./dist/zipper.d.ts",
|
|
128
|
+
"default": "./dist/zipper.js"
|
|
97
129
|
}
|
|
98
130
|
},
|
|
99
131
|
"peerDependencies": {
|