@nemigo/helpers 0.13.3 → 1.5.2

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.
Files changed (111) hide show
  1. package/dist/aggregator.d.ts +33 -0
  2. package/dist/aggregator.js +44 -0
  3. package/dist/array.d.ts +33 -0
  4. package/dist/array.js +24 -0
  5. package/dist/async/context.d.ts +73 -0
  6. package/dist/async/context.js +90 -0
  7. package/dist/async/future.d.ts +54 -0
  8. package/dist/async/future.js +71 -0
  9. package/dist/async/index.d.ts +56 -27
  10. package/dist/async/index.js +63 -58
  11. package/dist/async/loader.d.ts +67 -0
  12. package/dist/async/loader.js +101 -0
  13. package/dist/async/queue.d.ts +51 -0
  14. package/dist/async/queue.js +84 -0
  15. package/dist/cases.d.ts +31 -21
  16. package/dist/cases.js +41 -37
  17. package/dist/clean.d.ts +44 -26
  18. package/dist/clean.js +67 -42
  19. package/dist/color/types.d.ts +31 -0
  20. package/dist/color/types.js +1 -0
  21. package/dist/datetime/delta.d.ts +28 -0
  22. package/dist/datetime/delta.js +65 -0
  23. package/dist/datetime/format.d.ts +54 -0
  24. package/dist/datetime/format.js +122 -0
  25. package/dist/datetime/index.d.ts +6 -0
  26. package/dist/datetime/index.js +22 -0
  27. package/dist/datetime/plural.d.ts +77 -0
  28. package/dist/datetime/plural.js +78 -0
  29. package/dist/emitter.d.ts +29 -17
  30. package/dist/emitter.js +35 -21
  31. package/dist/explorer.d.ts +22 -29
  32. package/dist/explorer.js +18 -16
  33. package/dist/files.d.ts +31 -2
  34. package/dist/files.js +33 -8
  35. package/dist/fish.d.ts +29 -0
  36. package/dist/fish.js +70 -0
  37. package/dist/html/cookie.d.ts +48 -0
  38. package/dist/html/cookie.js +37 -0
  39. package/dist/html/events.d.ts +133 -0
  40. package/dist/html/events.js +139 -0
  41. package/dist/html/index.d.ts +31 -0
  42. package/dist/html/index.js +61 -0
  43. package/dist/index.d.ts +38 -40
  44. package/dist/index.js +43 -56
  45. package/dist/jiff/apply.d.ts +93 -0
  46. package/dist/jiff/apply.js +64 -0
  47. package/dist/jiff/extract.d.ts +7 -0
  48. package/dist/jiff/extract.js +82 -0
  49. package/dist/jiff/types.d.ts +57 -0
  50. package/dist/jiff/types.js +1 -0
  51. package/dist/lens.d.ts +20 -31
  52. package/dist/lens.js +22 -37
  53. package/dist/msgpack.d.ts +11 -26
  54. package/dist/msgpack.js +9 -21
  55. package/dist/mutate.d.ts +70 -0
  56. package/dist/mutate.js +130 -0
  57. package/dist/omitter.d.ts +54 -34
  58. package/dist/omitter.js +33 -25
  59. package/dist/path.d.ts +20 -1
  60. package/dist/path.js +21 -2
  61. package/dist/phymath/format.d.ts +60 -0
  62. package/dist/phymath/format.js +34 -0
  63. package/dist/phymath/index.d.ts +30 -30
  64. package/dist/phymath/index.js +41 -33
  65. package/dist/promoter.d.ts +20 -12
  66. package/dist/promoter.js +24 -17
  67. package/dist/random.d.ts +20 -21
  68. package/dist/random.js +22 -23
  69. package/dist/rubles.d.ts +24 -0
  70. package/dist/rubles.js +24 -0
  71. package/dist/script.d.ts +60 -13
  72. package/dist/script.js +46 -10
  73. package/dist/string.d.ts +46 -92
  74. package/dist/string.js +46 -171
  75. package/dist/types.d.ts +144 -25
  76. package/dist/url/index.d.ts +12 -0
  77. package/dist/url/index.js +17 -0
  78. package/dist/url/params.d.ts +141 -0
  79. package/dist/{url.js → url/params.js} +90 -18
  80. package/dist/url/slug.d.ts +28 -0
  81. package/dist/url/slug.js +102 -0
  82. package/dist/veil.d.ts +14 -0
  83. package/dist/veil.js +26 -0
  84. package/dist/xod.d.ts +237 -16
  85. package/dist/xod.js +192 -18
  86. package/dist/zipper.d.ts +22 -4
  87. package/dist/zipper.js +22 -5
  88. package/package.json +82 -34
  89. package/dist/async/space.d.ts +0 -8
  90. package/dist/async/space.js +0 -31
  91. package/dist/cleanup.d.ts +0 -9
  92. package/dist/cleanup.js +0 -18
  93. package/dist/colors.d.ts +0 -539
  94. package/dist/colors.js +0 -888
  95. package/dist/cookie.d.ts +0 -60
  96. package/dist/cookie.js +0 -48
  97. package/dist/datetime.d.ts +0 -82
  98. package/dist/datetime.js +0 -161
  99. package/dist/format.d.ts +0 -36
  100. package/dist/format.js +0 -26
  101. package/dist/future.d.ts +0 -51
  102. package/dist/future.js +0 -71
  103. package/dist/html.d.ts +0 -145
  104. package/dist/html.js +0 -205
  105. package/dist/humanly.d.ts +0 -9
  106. package/dist/humanly.js +0 -93
  107. package/dist/lru.d.ts +0 -77
  108. package/dist/lru.js +0 -128
  109. package/dist/queue.d.ts +0 -40
  110. package/dist/queue.js +0 -56
  111. package/dist/url.d.ts +0 -61
@@ -0,0 +1,78 @@
1
+ import { createValuePluralizer } from "../index.js";
2
+ /**
3
+ * Склонение слова "секунда" в зависимости от числа
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * pluralSeconds(1); // "секунда"
8
+ * pluralSeconds(3); // "секунды"
9
+ * pluralSeconds(155); // "секунд"
10
+ * ```
11
+ */
12
+ export const pluralSeconds = createValuePluralizer("секунда", "секунды", "секунд");
13
+ /**
14
+ * Склонение слова "минута" в зависимости от числа
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * pluralMinutes(1); // "минута"
19
+ * pluralMinutes(3); // "минуты"
20
+ * pluralMinutes(155); // "минут"
21
+ * ```
22
+ */
23
+ export const pluralMinutes = createValuePluralizer("минута", "минуты", "минут");
24
+ /**
25
+ * Склонение слова "час" в зависимости от числа
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * pluralHours(1); // "час"
30
+ * pluralHours(3); // "часа"
31
+ * pluralHours(155); // "часов"
32
+ * ```
33
+ */
34
+ export const pluralHours = createValuePluralizer("час", "часа", "часов");
35
+ /**
36
+ * Склонение слова "день" в зависимости от числа
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * pluralDays(1); // "день"
41
+ * pluralDays(3); // "дня"
42
+ * pluralDays(155); // "дней"
43
+ * ```
44
+ */
45
+ export const pluralDays = createValuePluralizer("день", "дня", "дней");
46
+ /**
47
+ * Склонение слова "неделя" в зависимости от числа
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * pluralWeeks(1); // "неделя"
52
+ * pluralWeeks(3); // "недели"
53
+ * pluralWeeks(155); // "недель"
54
+ * ```
55
+ */
56
+ export const pluralWeeks = createValuePluralizer("неделя", "недели", "недель");
57
+ /**
58
+ * Склонение слова "месяц" в зависимости от числа
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * pluralMonths(1); // "месяц"
63
+ * pluralMonths(3); // "месяца"
64
+ * pluralMonths(155); // "месяцев"
65
+ * ```
66
+ */
67
+ export const pluralMonths = createValuePluralizer("месяц", "месяца", "месяцев");
68
+ /**
69
+ * Склонение слова "год" в зависимости от числа
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * pluralYears(1); // "год"
74
+ * pluralYears(3); // "года"
75
+ * pluralYears(155); // "лет"
76
+ * ```
77
+ */
78
+ export const pluralYears = createValuePluralizer("год", "года", "лет");
package/dist/emitter.d.ts CHANGED
@@ -1,28 +1,40 @@
1
- import { Promoter } from "./promoter.js";
2
- import type { RID } from "./types.js";
1
+ import type { KEYS, RID } from "./types.js";
3
2
  /**
4
- * Класс `Emitter` реализует простую систему событийного взаимодействия.
5
- * Позволяет подписываться на события, уведомлять и удалять обработчики
3
+ * Реализует простую систему событийного взаимодействия
6
4
  *
7
- * @template Events - Схема событий вида `{ [key]: data }`
5
+ * @template Schema - Схема событий вида `{ [key]: data }`
8
6
  */
9
- export declare class Emitter<Events extends object> extends Promoter<{
10
- type: keyof Events;
11
- data: Events[keyof Events];
12
- }> {
13
- /**
14
- * Вызывает все обработчики, связанные с указанным событием
15
- */
16
- dispatch<K extends keyof Events>(target: K, data: Events[K]): void;
7
+ export declare class Emitter<Schema extends object> {
8
+ __listeners: Map<RID, {
9
+ event: KEYS<Schema>;
10
+ callback: (data: Schema[KEYS<Schema>]) => void;
11
+ once?: boolean;
12
+ }>;
13
+ dispatch<K extends KEYS<Schema>>(event: K, data: Schema[K]): void;
17
14
  /**
18
- * Добавляет обработчик для события
15
+ * @param event - Ключ события
16
+ * @param callback - Обработчик события
17
+ * @param [options] - Опции запуска
18
+ * @param [options.once] - Одноразовая подписка
19
+ * @param [options.key=Symbol()] - Ключ подписчика
20
+ *
21
+ * @returns - Функция для удаления обработчика
19
22
  */
20
- on<K extends keyof Events>(event: K, call: (data: Events[K]) => void, params?: {
23
+ on<K extends KEYS<Schema>>(event: K, callback: (data: Schema[K]) => void, options?: {
21
24
  key?: RID;
22
25
  once?: boolean;
23
26
  }): () => void;
24
27
  /**
25
- * Удаляет обработчик события по ключу. Если не указан, очищаются все обработчики
28
+ * **Если ключ не указан, очищаются все**
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // Удаление конкретного обработчика
33
+ * emitter.un("my-handler")
34
+ *
35
+ * // Очистка всех обработчиков
36
+ * emitter.un()
37
+ * ```
26
38
  */
27
- un(key?: RID): boolean;
39
+ un(key?: RID): void;
28
40
  }
package/dist/emitter.js CHANGED
@@ -1,33 +1,47 @@
1
- import { Promoter } from "./promoter.js";
2
1
  /**
3
- * Класс `Emitter` реализует простую систему событийного взаимодействия.
4
- * Позволяет подписываться на события, уведомлять и удалять обработчики
2
+ * Реализует простую систему событийного взаимодействия
5
3
  *
6
- * @template Events - Схема событий вида `{ [key]: data }`
4
+ * @template Schema - Схема событий вида `{ [key]: data }`
7
5
  */
8
- export class Emitter extends Promoter {
9
- /**
10
- * Вызывает все обработчики, связанные с указанным событием
11
- */
12
- dispatch(target, data) {
13
- super.notify({ type: target, data });
6
+ export class Emitter {
7
+ __listeners = new Map();
8
+ dispatch(event, data) {
9
+ this.__listeners.forEach((handler, key) => {
10
+ if (event === handler.event)
11
+ handler.callback(data);
12
+ if (handler.once)
13
+ this.__listeners.delete(key);
14
+ });
14
15
  }
15
16
  /**
16
- * Добавляет обработчик для события
17
+ * @param event - Ключ события
18
+ * @param callback - Обработчик события
19
+ * @param [options] - Опции запуска
20
+ * @param [options.once] - Одноразовая подписка
21
+ * @param [options.key=Symbol()] - Ключ подписчика
22
+ *
23
+ * @returns - Функция для удаления обработчика
17
24
  */
18
- on(event, call, params = {}) {
19
- const { key = Symbol(), once } = params;
20
- return super.sub((payload) => {
21
- if (payload.type === event) {
22
- // @ts-expect-error <оно не может корректно сузить тип>
23
- call(payload.data);
24
- }
25
- }, { key, once });
25
+ on(event, callback, options = {}) {
26
+ const { key = Symbol(), once } = options;
27
+ this.__listeners.set(key, { event, callback, once });
28
+ return () => this.__listeners.delete(key);
26
29
  }
27
30
  /**
28
- * Удаляет обработчик события по ключу. Если не указан, очищаются все обработчики
31
+ * **Если ключ не указан, очищаются все**
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * // Удаление конкретного обработчика
36
+ * emitter.un("my-handler")
37
+ *
38
+ * // Очистка всех обработчиков
39
+ * emitter.un()
40
+ * ```
29
41
  */
30
42
  un(key) {
31
- return super.unsub(key);
43
+ if (key)
44
+ return void this.__listeners.delete(key);
45
+ this.__listeners.clear();
32
46
  }
33
47
  }
@@ -1,15 +1,19 @@
1
1
  import type { PathLike, Stats } from "node:fs";
2
2
  /**
3
- * Проверяет существование пути и его тип (файл или папка) через {@link stat}
3
+ * @param path - Проверяет существование пути через {@link stat}
4
+ * @param [expected] - Ожидаемый тип: `"file"` (файл) или `"folder"` (директория)
5
+ * @param [strict=false] - Выбрасывает ошибку, если путь не существует
4
6
  *
5
- * @param path - Путь для проверки
6
- * @param [expected] - Ожидаемый тип: `"file"` (файл) или `"folder"` (папка)
7
- * @param [strict=false] - Если `true`, выбрасывает ошибку, если путь не существует
8
- *
9
- * @returns {@link Stats}, если путь существует и соответствует ожидаемому типу (если указан). Иначе возвращает `null`, если `strict = false`
10
7
  * @throws {Error} Если `strict = true` и путь не существует или не соответствует ожидаемому типу
11
8
  */
12
9
  declare function exists(path: PathLike, expected?: "file" | "folder", strict?: boolean): Promise<Stats | null>;
10
+ /**
11
+ * @param path - Проверяет существование пути через {@link stat}
12
+ * @param [expected] - Ожидаемый тип: `"file"` (файл) или `"folder"` (директория)
13
+ * @param strict - Выбрасывает ошибку, если путь не существует
14
+ *
15
+ * @throws {Error} Если путь не существует или не соответствует ожидаемому типу
16
+ */
13
17
  declare function exists(path: PathLike, expected: "file" | "folder" | undefined, strict: true): Promise<Stats>;
14
18
  export { exists };
15
19
  /**
@@ -17,37 +21,29 @@ export { exists };
17
21
  */
18
22
  export interface RemoveOptions {
19
23
  /**
20
- * Если `true` и это была не пустая папка, бросит ошибку.
21
- * Параметр `expected` приводится к `"folder"`
22
- *
23
- * @default false
24
+ * Если это была не пустая директория, бросит ошибку
25
+ * @remarks {@link RemoveOptions.expected} приводится к `"folder"`
24
26
  */
25
27
  empty?: boolean;
26
28
  /**
27
29
  * Проверка перед удалением
28
- *
29
- * @default undefined
30
30
  */
31
31
  expected?: "file" | "folder";
32
32
  }
33
33
  /**
34
34
  * Удаляет файл или папку по указанному пути
35
35
  *
36
- * @param path - Путь к файлу или папке
37
- * @param options - Опции поведения {@link RemoveOptions}
36
+ * @returns {@link Stats} удалённого элемента или `null`, если он не существовал
38
37
  *
39
- * @returns {@link Stats}, если путь существовал и был удалён, иначе `null`
40
- * @throws {Error} Если путь не существует или не соответствует ожидаемому типу
38
+ * @throws {Error} Если это была не пустая директория при {@link RemoveOptions.empty} или не соответствует ожидаемому типу {@link RemoveOptions.expected}
41
39
  */
42
40
  export declare function remove(path: PathLike, options?: RemoveOptions): Promise<Stats | null>;
43
41
  /**
44
- * Опции для функции {@link remake}
42
+ * Опции поведения для функции {@link remake}
45
43
  */
46
44
  export interface RemakeOptions {
47
45
  /**
48
- * Если `true` и это была не пустая папка, бросит ошибку
49
- *
50
- * @default false
46
+ * Если это была не пустая директория, бросит ошибку
51
47
  */
52
48
  empty?: boolean;
53
49
  /**
@@ -58,23 +54,20 @@ export interface RemakeOptions {
58
54
  recursive?: boolean;
59
55
  }
60
56
  /**
61
- * Удаляет (если существовала) и заново создаёт папку по указанному пути
57
+ * Удаляет (если существовала) и заново создаёт директорию по указанному пути
62
58
  *
63
- * @param path - Путь к папке
64
- * @param options - Опции поведения {@link RemakeOptions}
59
+ * @returns {@link Stats} удалённой директории или `null`, если она не существовала
65
60
  *
66
- * @returns {@link Stats}, если папка существовала и была удалена, иначе `null`
67
- * @throws {Error} Если путь не существует или не является папкой
61
+ * @throws {Error} Если это была не пустая директория при {@link RemakeOptions.empty} или нет родительской папки при отключённом {@link RemakeOptions.recursive}
68
62
  */
69
- export declare function remake(path: PathLike, options?: RemakeOptions): Promise<Stats | null>;
63
+ export declare const remake: (path: PathLike, options?: RemakeOptions) => Promise<Stats | null>;
70
64
  /**
71
65
  * Сравнивает содержимое файла с ожидаемым значением
72
66
  *
73
67
  * @param path - Путь к файлу
74
68
  * @param expected - Ожидаемое содержимое файла
75
- * @param [strict=true] - Если `true`, выбрасывает ошибку, если файл не существует. Если `false`, возвращает `false`
69
+ * @param [strict=false] - Выбрасывает ошибку, если файл не существует
76
70
  *
77
- * @returns `true`, если содержимое файла совпадает с ожидаемым, иначе `false`
78
71
  * @throws {Error} Если `strict = true` и файл не существует
79
72
  */
80
- export declare function compare(path: PathLike, expected: string, strict?: boolean): Promise<boolean>;
73
+ export declare const compare: (path: PathLike, expected: string, strict?: boolean) => Promise<boolean>;
package/dist/explorer.js CHANGED
@@ -1,4 +1,11 @@
1
1
  import { mkdir, readdir, readFile, rm, stat } from "node:fs/promises";
2
+ /**
3
+ * @param path - Проверяет существование пути через {@link stat}
4
+ * @param [expected] - Ожидаемый тип: `"file"` (файл) или `"folder"` (директория)
5
+ * @param [strict=false] - Выбрасывает ошибку, если путь не существует
6
+ *
7
+ * @throws {Error} Если `strict = true` и путь не существует или не соответствует ожидаемому типу
8
+ */
2
9
  async function exists(path, expected, strict = false) {
3
10
  let existed;
4
11
  try {
@@ -22,11 +29,9 @@ export { exists };
22
29
  /**
23
30
  * Удаляет файл или папку по указанному пути
24
31
  *
25
- * @param path - Путь к файлу или папке
26
- * @param options - Опции поведения {@link RemoveOptions}
32
+ * @returns {@link Stats} удалённого элемента или `null`, если он не существовал
27
33
  *
28
- * @returns {@link Stats}, если путь существовал и был удалён, иначе `null`
29
- * @throws {Error} Если путь не существует или не соответствует ожидаемому типу
34
+ * @throws {Error} Если это была не пустая директория при {@link RemoveOptions.empty} или не соответствует ожидаемому типу {@link RemoveOptions.expected}
30
35
  */
31
36
  export async function remove(path, options = {}) {
32
37
  const { empty = false, expected } = options;
@@ -37,7 +42,7 @@ export async function remove(path, options = {}) {
37
42
  return null;
38
43
  const entries = await readdir(path, { withFileTypes: true });
39
44
  if (entries.length > 0) {
40
- throw new Error(`Ожидалось, что папка "${path}" будет пуста`);
45
+ throw new Error(`Ожидалось, что директория "${path}" будет пуста`);
41
46
  }
42
47
  }
43
48
  else {
@@ -49,35 +54,32 @@ export async function remove(path, options = {}) {
49
54
  return existed;
50
55
  }
51
56
  /**
52
- * Удаляет (если существовала) и заново создаёт папку по указанному пути
57
+ * Удаляет (если существовала) и заново создаёт директорию по указанному пути
53
58
  *
54
- * @param path - Путь к папке
55
- * @param options - Опции поведения {@link RemakeOptions}
59
+ * @returns {@link Stats} удалённой директории или `null`, если она не существовала
56
60
  *
57
- * @returns {@link Stats}, если папка существовала и была удалена, иначе `null`
58
- * @throws {Error} Если путь не существует или не является папкой
61
+ * @throws {Error} Если это была не пустая директория при {@link RemakeOptions.empty} или нет родительской папки при отключённом {@link RemakeOptions.recursive}
59
62
  */
60
- export async function remake(path, options = {}) {
63
+ export const remake = async (path, options = {}) => {
61
64
  const { empty = false, recursive = true } = options;
62
65
  const existed = await remove(path, { empty, expected: "folder" });
63
66
  await mkdir(path, { recursive });
64
67
  return existed;
65
- }
68
+ };
66
69
  //...
67
70
  /**
68
71
  * Сравнивает содержимое файла с ожидаемым значением
69
72
  *
70
73
  * @param path - Путь к файлу
71
74
  * @param expected - Ожидаемое содержимое файла
72
- * @param [strict=true] - Если `true`, выбрасывает ошибку, если файл не существует. Если `false`, возвращает `false`
75
+ * @param [strict=false] - Выбрасывает ошибку, если файл не существует
73
76
  *
74
- * @returns `true`, если содержимое файла совпадает с ожидаемым, иначе `false`
75
77
  * @throws {Error} Если `strict = true` и файл не существует
76
78
  */
77
- export async function compare(path, expected, strict = true) {
79
+ export const compare = async (path, expected, strict = false) => {
78
80
  const existed = await exists(path, "file", strict);
79
81
  if (!existed)
80
82
  return false;
81
83
  const content = await readFile(path, "utf-8");
82
84
  return content === expected;
83
- }
85
+ };
package/dist/files.d.ts CHANGED
@@ -1,8 +1,37 @@
1
+ /**
2
+ * Конвертирует файл в строку base64 используя {@link FileReader.readAsDataURL}
3
+ *
4
+ * @throws {Error} Если чтение файла завершается с ошибкой
5
+ */
1
6
  export declare const fileToBase64: (file: File) => Promise<string>;
2
7
  /**
3
- * Проверяет, является ли файл изображением. SVG данную проверку не проходят.
8
+ * Проверяет, является ли файл изображением.
9
+ * SVG данную проверку не проходят
4
10
  */
5
11
  export declare const isImage: (file: File) => boolean;
12
+ /**
13
+ * Проверяет, является ли файл видео
14
+ */
6
15
  export declare const isVideo: (file: File) => boolean;
16
+ /**
17
+ * Проверяет, является ли файл аудио
18
+ */
7
19
  export declare const isAudio: (file: File) => boolean;
8
- export declare const getFileSize: (size: number) => string;
20
+ /**
21
+ * Словарь степеней байтов для {@link getFileSize}
22
+ */
23
+ export declare const BYTES_UNITS: string[];
24
+ /**
25
+ * Форматирует размер файла в читаемом виде
26
+ *
27
+ * @param size - Размер файла в байтах
28
+ * @param [dictionary=BYTES_UNITS] - Словарь степеней байтов
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * getFileSize(1024) // "1 kB"
33
+ * getFileSize(1048576) // "1 MB"
34
+ * getFileSize(500) // "500 B"
35
+ * ```
36
+ */
37
+ export declare const getFileSize: (size: number, dictionary?: string[]) => string;
package/dist/files.js CHANGED
@@ -1,18 +1,32 @@
1
+ /**
2
+ * Конвертирует файл в строку base64 используя {@link FileReader.readAsDataURL}
3
+ *
4
+ * @throws {Error} Если чтение файла завершается с ошибкой
5
+ */
1
6
  export const fileToBase64 = (file) => new Promise((resolve, reject) => {
2
7
  const reader = new FileReader();
3
8
  reader.onload = () => resolve(reader.result);
4
9
  reader.onerror = reject;
5
10
  reader.readAsDataURL(file);
6
11
  });
7
- //...
8
12
  /**
9
- * Проверяет, является ли файл изображением. SVG данную проверку не проходят.
13
+ * Проверяет, является ли файл изображением.
14
+ * SVG данную проверку не проходят
10
15
  */
11
16
  export const isImage = (file) => file.type.startsWith("image/") && !file.type.includes("svg");
17
+ /**
18
+ * Проверяет, является ли файл видео
19
+ */
12
20
  export const isVideo = (file) => file.type.startsWith("video/");
21
+ /**
22
+ * Проверяет, является ли файл аудио
23
+ */
13
24
  export const isAudio = (file) => file.type.startsWith("audio/");
14
25
  //...
15
- const UNITS = [
26
+ /**
27
+ * Словарь степеней байтов для {@link getFileSize}
28
+ */
29
+ export const BYTES_UNITS = [
16
30
  "B",
17
31
  "kB",
18
32
  "MB",
@@ -23,13 +37,24 @@ const UNITS = [
23
37
  "ZB",
24
38
  "YB",
25
39
  ];
26
- export const getFileSize = (size) => {
40
+ /**
41
+ * Форматирует размер файла в читаемом виде
42
+ *
43
+ * @param size - Размер файла в байтах
44
+ * @param [dictionary=BYTES_UNITS] - Словарь степеней байтов
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * getFileSize(1024) // "1 kB"
49
+ * getFileSize(1048576) // "1 MB"
50
+ * getFileSize(500) // "500 B"
51
+ * ```
52
+ */
53
+ export const getFileSize = (size, dictionary = BYTES_UNITS) => {
27
54
  const bytes = Math.round(size);
28
- if (bytes === 0)
29
- return "0 B";
30
55
  if (bytes < 1000)
31
56
  return bytes.toString() + " B";
32
- const exponent = Math.min(Math.floor(Math.log10(bytes) / 3), UNITS.length - 1);
57
+ const exponent = Math.min(Math.floor(Math.log10(bytes) / 3), dictionary.length - 1);
33
58
  const result = bytes / 1000 ** exponent;
34
- return Math.round(result) + " " + UNITS[exponent];
59
+ return Math.round(result) + " " + dictionary[exponent];
35
60
  };
package/dist/fish.d.ts ADDED
@@ -0,0 +1,29 @@
1
+ import type { AnyFunc, Args, Dictionary, FuncCopy, Return } from "./types.js";
2
+ /**
3
+ * Выполнение функции только один раз, после будет возвращать уже полученный ранее результат
4
+ *
5
+ * @throws {unknown} Если первый вызов будет с ошибкой, можно попровать ещё раз
6
+ */
7
+ export declare const oncefish: <F extends AnyFunc>(func: F) => FuncCopy<F>;
8
+ /**
9
+ * Однократное выполнение асинхронной функции, после будет возвращать уже полученный ранее промисс
10
+ *
11
+ * @throws {unknown} Если первый вызов будет с ошибкой, можно попровать ещё раз
12
+ */
13
+ export declare const profish: <T, A extends any[] = any[]>(func: (...args: A) => Promise<T>) => ((...args: A) => Promise<T>);
14
+ /**
15
+ * Оборачивает функцию так, чтобы она запоминала **только последний вызов**.
16
+ * При повторном аналогичном (согласно `strategy`) вызове возвращается сохранённый результат
17
+ *
18
+ * @throws {unknown} Если вызов `func` завершается ошибкой, новый результат не кэшируется, и ошибка пробрасывается
19
+ */
20
+ export declare const goldfish: <F extends AnyFunc>(func: F, strategy: (curr: Args<F>, prev: Args<F>, result: Return<F>) => boolean) => FuncCopy<F>;
21
+ /**
22
+ * Оборачивает функцию так, чтобы она кэшировала результаты вызовов по ключу,
23
+ * полученному с помощью функции `serialize`
24
+ *
25
+ * Кэш хранится в обычной `Map`, ключи генерируются вызовом `serialize` от аргументов
26
+ *
27
+ * @throws {unknown} Если вызов `func` завершается ошибкой, результат не кэшируется, и ошибка пробрасывается
28
+ */
29
+ export declare const memofish: <F extends AnyFunc, Cache extends Dictionary<any, Return<F>>>(func: F, serialize: (args: Args<F>, cache: Cache) => Args<Cache["get"]>[0], cache?: Cache) => FuncCopy<F>;
package/dist/fish.js ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Выполнение функции только один раз, после будет возвращать уже полученный ранее результат
3
+ *
4
+ * @throws {unknown} Если первый вызов будет с ошибкой, можно попровать ещё раз
5
+ */
6
+ export const oncefish = (func) => {
7
+ let ready = false;
8
+ let result;
9
+ return (...args) => {
10
+ if (!ready) {
11
+ result = func(args);
12
+ ready = true;
13
+ }
14
+ return result;
15
+ };
16
+ };
17
+ /**
18
+ * Однократное выполнение асинхронной функции, после будет возвращать уже полученный ранее промисс
19
+ *
20
+ * @throws {unknown} Если первый вызов будет с ошибкой, можно попровать ещё раз
21
+ */
22
+ export const profish = (func) => {
23
+ let promise;
24
+ return (...args) => {
25
+ if (!promise) {
26
+ promise = func(...args).catch((err) => {
27
+ promise = undefined;
28
+ throw err;
29
+ });
30
+ }
31
+ return promise;
32
+ };
33
+ };
34
+ /**
35
+ * Оборачивает функцию так, чтобы она запоминала **только последний вызов**.
36
+ * При повторном аналогичном (согласно `strategy`) вызове возвращается сохранённый результат
37
+ *
38
+ * @throws {unknown} Если вызов `func` завершается ошибкой, новый результат не кэшируется, и ошибка пробрасывается
39
+ */
40
+ export const goldfish = (func, strategy) => {
41
+ let lastArgs;
42
+ let lastResult;
43
+ return (...args) => {
44
+ if (lastArgs && strategy(args, lastArgs, lastResult)) {
45
+ return lastResult;
46
+ }
47
+ lastResult = func(args);
48
+ lastArgs = args;
49
+ return lastResult;
50
+ };
51
+ };
52
+ /**
53
+ * Оборачивает функцию так, чтобы она кэшировала результаты вызовов по ключу,
54
+ * полученному с помощью функции `serialize`
55
+ *
56
+ * Кэш хранится в обычной `Map`, ключи генерируются вызовом `serialize` от аргументов
57
+ *
58
+ * @throws {unknown} Если вызов `func` завершается ошибкой, результат не кэшируется, и ошибка пробрасывается
59
+ */
60
+ export const memofish = (func, serialize, cache = new Map()) => {
61
+ return (...args) => {
62
+ const key = serialize(args, cache);
63
+ const existed = cache.get(key);
64
+ if (existed)
65
+ return existed;
66
+ const result = func(...args);
67
+ cache.set(key, result);
68
+ return result;
69
+ };
70
+ };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Политика {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite SameSite} приватности кук для {@link setDocumentCookie}
3
+ *
4
+ * - Strict: Куки будут отправляться только при навигации внутри сайта
5
+ * - Lax: Куки доступны для навигации с одного сайта на другой (рекомендуется)
6
+ * - None: Куки доступны для всех запросов, требуется параметр Secure (для кросс-сайтовых запросов)
7
+ */
8
+ export type CookieSameSite = "Strict" | "Lax" | "None";
9
+ /**
10
+ * Опции установки куки для {@link setDocumentCookie}
11
+ */
12
+ export interface SetDocumentCookieOptions {
13
+ SameSite?: CookieSameSite;
14
+ /**
15
+ * Максимальное время жизни куки в секундах
16
+ *
17
+ * @remarks `MaxAge === null` делает хранение сессионным!
18
+ */
19
+ MaxAge?: number | null;
20
+ /**
21
+ * Флаг, указывающий, что кука будет передаваться только по защищенному соединению (HTTPS)
22
+ */
23
+ Secure?: boolean;
24
+ /**
25
+ * Путь раздела, для которого кука существует при отправке на сервер
26
+ */
27
+ Path?: string;
28
+ /**
29
+ * Для установки куки, которая будет доступна на текущем домене и всех его поддоменах `.${window.location.hostname}`
30
+ */
31
+ Domain?: string;
32
+ }
33
+ /**
34
+ * @param name - Имя куки
35
+ * @param value - Значение куки
36
+ * @param [options] - Опции куки
37
+ * @param [options.MaxAge=21days] - {@link SetDocumentCookieOptions.MaxAge}
38
+ * @param [options.SameSite="Lax"] - {@link SetDocumentCookieOptions.SameSite}
39
+ * @param [options.Secure=true] - {@link SetDocumentCookieOptions.Secure}
40
+ * @param [options.Path="/"] - {@link SetDocumentCookieOptions.Path}
41
+ * @param [options.Domain] - {@link SetDocumentCookieOptions.Domain}
42
+ */
43
+ export declare const setDocumentCookie: (name: string, value: string, options?: SetDocumentCookieOptions) => void;
44
+ export declare const getDocumentCookie: (name: string) => string | undefined;
45
+ /**
46
+ * Удаляет куку по имени, устанавливая Max-Age=0 через {@link setDocumentCookie}
47
+ */
48
+ export declare const deleteDocumentCookie: (name: string, Path?: string) => void;