@nemigo/helpers 0.0.10 → 0.0.13

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.
@@ -0,0 +1,42 @@
1
+ import type { Timestamp } from "./types.js";
2
+ /**
3
+ * Создаёт задержку на указанное количество миллисекунд
4
+ *
5
+ * @param ms - Количество миллисекунд для задержки
6
+ */
7
+ export declare const delay: (ms: Timestamp) => Promise<void>;
8
+ /**
9
+ * Создаёт debounce-функцию, которая откладывает выполнение до тех пор, пока не пройдёт указанное время без новых вызовов
10
+ *
11
+ * @param call - Функция для debounce
12
+ * @param delay - Задержка в миллисекундах
13
+ *
14
+ * @returns Функция с debounce
15
+ */
16
+ export declare const debounce: <T extends (...args: any[]) => any>(call: T, delay: Timestamp) => ((...args: Parameters<T>) => void);
17
+ /**
18
+ * Создаёт функцию-замыкание, которое гарантирует (старается), что переданная функция `call`
19
+ * будет вызвана не чаще одного раза в заданный интервал времени.
20
+ *
21
+ * mode = `"delay"`
22
+ * - первый вызов откладывается на `ms`
23
+ * - повторные вызовы до старта игнорируются, аргументы обновляются
24
+ * - все ждут одного промисса
25
+ *
26
+ * mode = `"urgent"`:
27
+ * - первый вызов исполняется сразу
28
+ * - повторные вызовы возвращают тот же промиcс в течение `ms` (даже после завершения)
29
+ * - после `ms` можно снова вызвать
30
+ */
31
+ export declare const trottling: <F extends (...args: any[]) => any>(call: F, mode: "urgent" | "delay", ms: number) => ((...args: Parameters<F>) => Promise<Awaited<ReturnType<F>>>);
32
+ /**
33
+ * Создаёт функцию-замыкание, которая гарантирует однократное выполнение асинхронной операции
34
+ *
35
+ * При первом вызове запускает переданный `call` и сохраняет его результат.
36
+ * Все последующие вызовы возвращают сохранённый результат без повторного выполнения операции.
37
+ * Если вызов происходит во время выполнения, возвращает тот же промисс, вместо создания нового
38
+ *
39
+ * @param call - Асинхронная функция, результат которой нужно кешировать
40
+ * @returns Функция, возвращающая закешированный результат после первого успешного выполнения
41
+ */
42
+ export declare const createPromiseTrap: <T>(call: () => Promise<T>) => () => Promise<T>;
package/dist/async.js ADDED
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Создаёт задержку на указанное количество миллисекунд
3
+ *
4
+ * @param ms - Количество миллисекунд для задержки
5
+ */
6
+ export const delay = (ms) => new Promise((ready) => setTimeout(ready, ms));
7
+ //...
8
+ /**
9
+ * Создаёт debounce-функцию, которая откладывает выполнение до тех пор, пока не пройдёт указанное время без новых вызовов
10
+ *
11
+ * @param call - Функция для debounce
12
+ * @param delay - Задержка в миллисекундах
13
+ *
14
+ * @returns Функция с debounce
15
+ */
16
+ export const debounce = (call, delay) => {
17
+ let timeout;
18
+ return (...args) => {
19
+ if (timeout)
20
+ clearTimeout(timeout);
21
+ timeout = setTimeout(() => call(...args), delay);
22
+ };
23
+ };
24
+ /**
25
+ * Создаёт функцию-замыкание, которое гарантирует (старается), что переданная функция `call`
26
+ * будет вызвана не чаще одного раза в заданный интервал времени.
27
+ *
28
+ * mode = `"delay"`
29
+ * - первый вызов откладывается на `ms`
30
+ * - повторные вызовы до старта игнорируются, аргументы обновляются
31
+ * - все ждут одного промисса
32
+ *
33
+ * mode = `"urgent"`:
34
+ * - первый вызов исполняется сразу
35
+ * - повторные вызовы возвращают тот же промиcс в течение `ms` (даже после завершения)
36
+ * - после `ms` можно снова вызвать
37
+ */
38
+ export const trottling = (call, mode, ms) => {
39
+ let _promise = null;
40
+ let _args = [];
41
+ return (...args) => {
42
+ _args = args;
43
+ if (_promise)
44
+ return _promise;
45
+ let resolver;
46
+ let rejecter;
47
+ _promise = new Promise((resolve, reject) => {
48
+ resolver = resolve;
49
+ rejecter = reject;
50
+ });
51
+ const reset = () => (_promise = null);
52
+ if (mode === "delay") {
53
+ setTimeout(() => {
54
+ call(..._args)
55
+ .then(resolver)
56
+ .catch(rejecter)
57
+ .finally(reset);
58
+ }, ms);
59
+ }
60
+ else {
61
+ call(..._args)
62
+ .then(resolver)
63
+ .catch(rejecter)
64
+ .finally(delay(ms).then(reset));
65
+ }
66
+ return _promise;
67
+ };
68
+ };
69
+ //...
70
+ /**
71
+ * Создаёт функцию-замыкание, которая гарантирует однократное выполнение асинхронной операции
72
+ *
73
+ * При первом вызове запускает переданный `call` и сохраняет его результат.
74
+ * Все последующие вызовы возвращают сохранённый результат без повторного выполнения операции.
75
+ * Если вызов происходит во время выполнения, возвращает тот же промисс, вместо создания нового
76
+ *
77
+ * @param call - Асинхронная функция, результат которой нужно кешировать
78
+ * @returns Функция, возвращающая закешированный результат после первого успешного выполнения
79
+ */
80
+ export const createPromiseTrap = (call) => {
81
+ const mark = Symbol();
82
+ let value = mark;
83
+ let promise = null;
84
+ return () => {
85
+ if (value !== mark)
86
+ return value;
87
+ if (!promise) {
88
+ promise = call().then((result) => {
89
+ value = result;
90
+ return result;
91
+ });
92
+ }
93
+ return promise;
94
+ };
95
+ };
@@ -0,0 +1 @@
1
+ export declare const fileToBase64: (file: File) => Promise<string>;
package/dist/files.js ADDED
@@ -0,0 +1,6 @@
1
+ export const fileToBase64 = (file) => new Promise((resolve, reject) => {
2
+ const reader = new FileReader();
3
+ reader.onload = () => resolve(reader.result);
4
+ reader.onerror = reject;
5
+ reader.readAsDataURL(file);
6
+ });
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Регулярное выражение для захвата всех нецифровых символов из строки
3
+ */
4
+ export declare const oDigitRegExp: RegExp;
5
+ /**
6
+ * Чистка строки от всего, кроме цифр
7
+ */
8
+ export declare const oDigitClean: (v?: string) => string;
9
+ /**
10
+ * Регулярное выражение для захвата пробелов
11
+ */
12
+ export declare const spaceRegExp: RegExp;
13
+ /**
14
+ * Заменяет все двойные, тройные и т. д. пробелы на один
15
+ */
16
+ export declare const spaceClean: (v?: string) => string;
17
+ /**
18
+ * Приводит первый символ слова к верхнему регистру
19
+ */
20
+ export declare const toCapital: (word?: string) => string;
21
+ /**
22
+ * Готовая {@link Map} для перевода кириллицы нижнего регистра в латиницу
23
+ */
24
+ export declare const cyrillicToLatinMap: Map<string, string>;
25
+ /**
26
+ * Функция для создания *slug* (фрагмента URL) сущности
27
+ */
28
+ export declare const toSlug: (text: string, separator?: string) => string;
package/dist/string.js ADDED
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Регулярное выражение для захвата всех нецифровых символов из строки
3
+ */
4
+ export const oDigitRegExp = /\D/g;
5
+ /**
6
+ * Чистка строки от всего, кроме цифр
7
+ */
8
+ export const oDigitClean = (v = "") => v.replace(oDigitRegExp, "");
9
+ //...
10
+ /**
11
+ * Регулярное выражение для захвата пробелов
12
+ */
13
+ export const spaceRegExp = /\s+/g;
14
+ /**
15
+ * Заменяет все двойные, тройные и т. д. пробелы на один
16
+ */
17
+ export const spaceClean = (v = "") => v.replace(spaceRegExp, " ").trim();
18
+ //...
19
+ /**
20
+ * Приводит первый символ слова к верхнему регистру
21
+ */
22
+ export const toCapital = (word = "") => word.charAt(0).toUpperCase() + word.slice(1);
23
+ //...
24
+ /**
25
+ * Готовая {@link Map} для перевода кириллицы нижнего регистра в латиницу
26
+ */
27
+ export const cyrillicToLatinMap = new Map([
28
+ ["а", "a"],
29
+ ["б", "b"],
30
+ ["в", "v"],
31
+ ["г", "g"],
32
+ ["д", "d"],
33
+ ["е", "e"],
34
+ ["ё", "yo"],
35
+ ["ж", "zh"],
36
+ ["з", "z"],
37
+ ["и", "i"],
38
+ ["й", "y"],
39
+ ["к", "k"],
40
+ ["л", "l"],
41
+ ["м", "m"],
42
+ ["н", "n"],
43
+ ["о", "o"],
44
+ ["п", "p"],
45
+ ["р", "r"],
46
+ ["с", "s"],
47
+ ["т", "t"],
48
+ ["у", "u"],
49
+ ["ф", "f"],
50
+ ["х", "h"],
51
+ ["ц", "ts"],
52
+ ["ч", "ch"],
53
+ ["ш", "sh"],
54
+ ["щ", "sch"],
55
+ ["ъ", ""],
56
+ ["ы", "y"],
57
+ ["ь", ""],
58
+ ["э", "e"],
59
+ ["ю", "yu"],
60
+ ["я", "ya"],
61
+ ]);
62
+ /**
63
+ * Функция для создания *slug* (фрагмента URL) сущности
64
+ */
65
+ export const toSlug = (text, separator = "-") => {
66
+ let acc = "";
67
+ let wasSpace = false;
68
+ for (const _char of text.split("")) {
69
+ const char = _char.toLowerCase();
70
+ const code = char.charCodeAt(0);
71
+ // Кириллица (а-я, ё)
72
+ if ((code >= 1072 && code <= 1103) || code === 1105) {
73
+ acc += cyrillicToLatinMap.get(char) || char;
74
+ wasSpace = false;
75
+ }
76
+ // Латиница (a-z)
77
+ else if (code >= 97 && code <= 122) {
78
+ acc += char;
79
+ wasSpace = false;
80
+ }
81
+ // Цифры (0-9)
82
+ else if (code >= 48 && code <= 57) {
83
+ acc += char;
84
+ wasSpace = false;
85
+ }
86
+ // Пробел или другие символы, которые нужно заменить на separator
87
+ else {
88
+ if (!wasSpace && acc.length > 0) {
89
+ acc += separator;
90
+ wasSpace = true;
91
+ }
92
+ }
93
+ }
94
+ // Убираем завершающий separator, если он есть
95
+ return acc.endsWith(separator) ? acc.slice(0, -1) : acc;
96
+ };
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Дата и время в формате UNIX
3
+ */
4
+ export type Timestamp = number;
5
+ /**
6
+ * Идентификатор чего-либо для рантайма (например, для кэша)
7
+ */
8
+ export type RID = string | number | symbol;
9
+ /**
10
+ * Обобщённый тип таймеров
11
+ */
12
+ export type TimeoutType = ReturnType<typeof setTimeout>;
13
+ /**
14
+ * Обобщённый тип интервалов
15
+ */
16
+ export type IntervalType = ReturnType<typeof setInterval>;
17
+ /**
18
+ * Массив в массиве
19
+ */
20
+ export type Matrix<T = unknown> = T[][];
21
+ /**
22
+ * Значение может быть `null` или `undefined`
23
+ */
24
+ export type CanBeNullable<T = unknown> = T | null | undefined;
25
+ /**
26
+ * Значение может быть массивом или одиночным элементом
27
+ */
28
+ export type CanBeArray<T = unknown> = T | T[];
29
+ /**
30
+ * Значение может быть промиссом
31
+ */
32
+ export type CanBePromise<T = unknown> = T | Promise<T>;
33
+ /**
34
+ * Исключение `undefined`
35
+ */
36
+ export type Exist<T> = Exclude<T, undefined>;
37
+ /**
38
+ * Только строковые ключи объектов
39
+ */
40
+ export type KEYS<O> = keyof O extends infer Key ? (Key extends string ? Key : never) : never;
41
+ /**
42
+ * Рекурсивный {@link Partial}
43
+ */
44
+ export type DeepPartial<O> = {
45
+ [K in keyof O]?: O[K] extends object | undefined ? DeepPartial<O[K]> : O[K];
46
+ };
47
+ /**
48
+ * Рекурсивный {@link Required}
49
+ */
50
+ export type DeepRequired<O> = {
51
+ [K in keyof O]-?: O[K] extends object | undefined ? DeepRequired<NonNullable<O[K]>> : O[K];
52
+ };
53
+ /**
54
+ * Получение тип элемента массива
55
+ */
56
+ export type ArrayElement<T> = T extends (infer U)[] ? U : never;
57
+ /**
58
+ * - ASC - по возрастанию
59
+ * - DESC - по убыванию
60
+ */
61
+ export type SortDirection = "ASC" | "DESC";
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/dist/url.d.ts ADDED
@@ -0,0 +1,61 @@
1
+ import type { CanBeNullable } from "./types.js";
2
+ /**
3
+ * Возможные значения параметра для {@link pushParams} и {@link clearParams}
4
+ */
5
+ export type ParamValue = CanBeNullable<string | number | boolean>;
6
+ /**
7
+ * KV-параметры для URL для {@link pushParams} и {@link clearParams}
8
+ */
9
+ export type ParamKV<V extends ParamValue = ParamValue> = {
10
+ key: string;
11
+ value?: V;
12
+ };
13
+ /**
14
+ * Параметры для URL для {@link pushParams} и {@link clearParams}
15
+ */
16
+ export type Params<V extends ParamValue = ParamValue> = CanBeNullable<string | ParamKV<V>>[];
17
+ /**
18
+ * Добавляет параметры в URL
19
+ *
20
+ * Для каждого параметра из массива:
21
+ * - Если параметр равен `null` или `undefined`, он пропускается
22
+ * - Если параметр имеет тип `string`, то в строке запроса добавляется параметр с ключом равным значению строки и значением `"true"`
23
+ * - Если параметр является объектом с ключом и значением, то, если значение не `undefined` и не является объектом, оно приводится к строке и устанавливается в качестве значения
24
+ *
25
+ * **Небезопасное поведение:**
26
+ * - При передаче параметра типа `string` он добавляется как `?param1&param2` (без значения, то есть без `true`)
27
+ * - При передаче параметра, значение которого равно `true` или пустой строке, параметр добавляется без значения
28
+ *
29
+ * @param url - URL, в который будут добавлены параметры
30
+ * @param params - Массив параметров
31
+ * @param [unsafe=false] - Небезопасное поведение
32
+ */
33
+ export declare const pushParams: (url: URL, params: Params, unsafe?: boolean) => URL;
34
+ export type StrictPushParams = Required<ParamKV<string | boolean | number>>[];
35
+ /**
36
+ * Объединяет массивы параметров для {@link pushParams} в один массив, исключая дубликаты
37
+ *
38
+ * @param args - Массивы параметров для объединения
39
+ * @returns Массив параметров без дубликатов
40
+ */
41
+ export declare const mergePushParams: (...args: Params[]) => StrictPushParams;
42
+ /**
43
+ * Удаляет из URL параметры
44
+ *
45
+ * Для каждого элемента массива:
46
+ * - Если параметр отсутствует или равен `null` или `undefined`, он пропускается
47
+ * - Если параметр имеет тип `string`, из URL удаляется параметр с таким именем
48
+ * - Если параметр является объектом с ключом (`key`), из URL удаляется параметр с этим ключом
49
+ *
50
+ * @param url - URL, из которого будут удалены параметры
51
+ * @param params - Массив параметров для удаления
52
+ */
53
+ export declare const clearParams: (url: URL, params: Params) => URL;
54
+ export type StrictClearParams = string[];
55
+ /**
56
+ * Объединяет массивы параметров для {@link clearParams} в один массив, исключая дубликаты
57
+ *
58
+ * @param args - Массивы параметров для объединения
59
+ * @returns Массив параметров без дубликатов
60
+ */
61
+ export declare const mergeClearParams: (...args: Params[]) => StrictClearParams;
package/dist/url.js ADDED
@@ -0,0 +1,137 @@
1
+ //...
2
+ /**
3
+ * Добавляет параметры в URL
4
+ *
5
+ * Для каждого параметра из массива:
6
+ * - Если параметр равен `null` или `undefined`, он пропускается
7
+ * - Если параметр имеет тип `string`, то в строке запроса добавляется параметр с ключом равным значению строки и значением `"true"`
8
+ * - Если параметр является объектом с ключом и значением, то, если значение не `undefined` и не является объектом, оно приводится к строке и устанавливается в качестве значения
9
+ *
10
+ * **Небезопасное поведение:**
11
+ * - При передаче параметра типа `string` он добавляется как `?param1&param2` (без значения, то есть без `true`)
12
+ * - При передаче параметра, значение которого равно `true` или пустой строке, параметр добавляется без значения
13
+ *
14
+ * @param url - URL, в который будут добавлены параметры
15
+ * @param params - Массив параметров
16
+ * @param [unsafe=false] - Небезопасное поведение
17
+ */
18
+ export const pushParams = (url, params, unsafe = false) => {
19
+ for (const param of params) {
20
+ if (!param)
21
+ continue;
22
+ if (typeof param === "string") {
23
+ // Если unsafe === true, добавляем параметр без значения, иначе - как "true"
24
+ url.searchParams.set(param, unsafe ? "" : "true");
25
+ continue;
26
+ }
27
+ if (!param?.key)
28
+ continue;
29
+ if (typeof param.value !== "object") {
30
+ if (unsafe && (param?.value === undefined || param.value === true || param.value === "")) {
31
+ url.searchParams.set(param.key, "");
32
+ }
33
+ else {
34
+ url.searchParams.set(param.key, String(param.value));
35
+ }
36
+ }
37
+ }
38
+ if (unsafe) {
39
+ const splitted = url.href.split("?");
40
+ if (splitted[1]) {
41
+ splitted[1] = splitted[1].replaceAll("=&", "&");
42
+ if (splitted[1].endsWith("="))
43
+ splitted[1] = splitted[1].slice(0, splitted[1].length - 1);
44
+ }
45
+ url.href = splitted.join("?");
46
+ }
47
+ return url;
48
+ };
49
+ /**
50
+ * Объединяет массивы параметров для {@link pushParams} в один массив, исключая дубликаты
51
+ *
52
+ * @param args - Массивы параметров для объединения
53
+ * @returns Массив параметров без дубликатов
54
+ */
55
+ export const mergePushParams = (...args) => {
56
+ const acc = [];
57
+ for (const params of args) {
58
+ for (const param of params) {
59
+ if (!param)
60
+ continue;
61
+ if (typeof param === "string") {
62
+ const existed = acc.find((v) => v.key === param);
63
+ if (existed)
64
+ existed.value = true;
65
+ else
66
+ acc.push({ key: param, value: true });
67
+ continue;
68
+ }
69
+ if (!param?.key)
70
+ continue;
71
+ if (typeof param?.value !== "object") {
72
+ const existed = acc.find((v) => v.key === param.key);
73
+ if (param.value === undefined || param.value === true || param.value === "") {
74
+ if (existed)
75
+ existed.value = true;
76
+ else
77
+ acc.push({ key: param.key, value: true });
78
+ }
79
+ else {
80
+ if (existed)
81
+ existed.value = String(param.value);
82
+ else
83
+ acc.push({ key: param.key, value: param.value });
84
+ }
85
+ }
86
+ }
87
+ }
88
+ return acc;
89
+ };
90
+ //...
91
+ /**
92
+ * Удаляет из URL параметры
93
+ *
94
+ * Для каждого элемента массива:
95
+ * - Если параметр отсутствует или равен `null` или `undefined`, он пропускается
96
+ * - Если параметр имеет тип `string`, из URL удаляется параметр с таким именем
97
+ * - Если параметр является объектом с ключом (`key`), из URL удаляется параметр с этим ключом
98
+ *
99
+ * @param url - URL, из которого будут удалены параметры
100
+ * @param params - Массив параметров для удаления
101
+ */
102
+ export const clearParams = (url, params) => {
103
+ for (const param of params) {
104
+ if (!param)
105
+ continue;
106
+ if (typeof param === "string") {
107
+ url.searchParams.delete(param);
108
+ continue;
109
+ }
110
+ if (param?.key)
111
+ url.searchParams.delete(param.key);
112
+ }
113
+ return url;
114
+ };
115
+ /**
116
+ * Объединяет массивы параметров для {@link clearParams} в один массив, исключая дубликаты
117
+ *
118
+ * @param args - Массивы параметров для объединения
119
+ * @returns Массив параметров без дубликатов
120
+ */
121
+ export const mergeClearParams = (...args) => {
122
+ const acc = [];
123
+ for (const params of args) {
124
+ for (const param of params) {
125
+ if (!param)
126
+ continue;
127
+ if (typeof param === "string") {
128
+ if (!acc.includes(param))
129
+ acc.push(param);
130
+ continue;
131
+ }
132
+ if (param.key && !acc.includes(param.key))
133
+ acc.push(param.key);
134
+ }
135
+ }
136
+ return acc;
137
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nemigo/helpers",
3
- "version": "0.0.10",
3
+ "version": "0.0.13",
4
4
  "private": false,
5
5
  "author": {
6
6
  "name": "Vlad Logvin",
@@ -15,6 +15,10 @@
15
15
  "format": "prettier --write ./"
16
16
  },
17
17
  "exports": {
18
+ "./async": {
19
+ "types": "./dist/async.d.ts",
20
+ "default": "./dist/async.js"
21
+ },
18
22
  "./cases": {
19
23
  "types": "./dist/cases.d.ts",
20
24
  "default": "./dist/cases.js"
@@ -27,6 +31,10 @@
27
31
  "types": "./dist/explorer.d.ts",
28
32
  "default": "./dist/explorer.js"
29
33
  },
34
+ "./files": {
35
+ "types": "./dist/files.d.ts",
36
+ "default": "./dist/files.js"
37
+ },
30
38
  "./lens": {
31
39
  "types": "./dist/lens.d.ts",
32
40
  "default": "./dist/lens.js"
@@ -35,17 +43,25 @@
35
43
  "types": "./dist/msgpack.d.ts",
36
44
  "default": "./dist/msgpack.js"
37
45
  },
38
- "./random": {
39
- "types": "./dist/random.d.ts",
40
- "default": "./dist/random.js"
41
- },
42
46
  "./phymath": {
43
47
  "types": "./dist/phymath.d.ts",
44
48
  "default": "./dist/phymath.js"
45
49
  },
50
+ "./random": {
51
+ "types": "./dist/random.d.ts",
52
+ "default": "./dist/random.js"
53
+ },
46
54
  "./script": {
47
55
  "types": "./dist/script.d.ts",
48
56
  "default": "./dist/script.js"
57
+ },
58
+ "./types": {
59
+ "types": "./dist/types.d.ts",
60
+ "default": "./dist/types.js"
61
+ },
62
+ "./url": {
63
+ "types": "./dist/url.d.ts",
64
+ "default": "./dist/url.js"
49
65
  }
50
66
  },
51
67
  "dependencies": {