@nemigo/helpers 0.13.2 → 1.5.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.
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 +53 -0
  24. package/dist/datetime/format.js +119 -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 +57 -34
  58. package/dist/omitter.js +38 -30
  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 +23 -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 -7
  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 -50
  102. package/dist/future.js +0 -59
  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 -39
  110. package/dist/queue.js +0 -54
  111. package/dist/url.d.ts +0 -61
package/dist/mutate.js ADDED
@@ -0,0 +1,130 @@
1
+ import { isObject, isSameType } from "./index.js";
2
+ /**
3
+ * Рекурсивно модифицирует объект, приводя его структуру к виду целевого объекта.
4
+ * Использует внутри {@link deepMutateArray}
5
+ *
6
+ * Удаляет лишние свойства, обновляет существующие и добавляет новые.
7
+ * Работает **мутативно** — изменяет исходный объект напрямую
8
+ *
9
+ * @remarks **НЕ** предназначен для работы с декларативными методами (могут потерять `this`)
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const source = { a: 1, b: 2, c: 3 };
14
+ * const target = { a: 10, d: 40 };
15
+ *
16
+ * deepMutateObject(source, target);
17
+ * // source теперь: { a: 10, d: 40 }
18
+ * // свойства b и c удалены, a обновлено, d добавлено
19
+ * ```
20
+ */
21
+ export const deepMutateObject = (source, target) => {
22
+ // Удаление лишних свойств
23
+ Object.keys(source).forEach((key) => {
24
+ if (!(key in target))
25
+ delete source[key];
26
+ });
27
+ // Обновление свойств
28
+ Object.entries(target).forEach(([key, targetValue]) => {
29
+ const sourceValue = source[key];
30
+ // Проверка изменения типа данных
31
+ if (!isSameType(sourceValue, targetValue)) {
32
+ source[key] = targetValue; // Полная замена при разном типе
33
+ return;
34
+ }
35
+ if (Array.isArray(targetValue)) {
36
+ if (!Array.isArray(sourceValue))
37
+ source[key] = [];
38
+ deepMutateArray(source[key], targetValue);
39
+ }
40
+ else if (isObject(targetValue)) {
41
+ if (!isObject(sourceValue))
42
+ source[key] = {};
43
+ deepMutateObject(source[key], targetValue);
44
+ }
45
+ else if (sourceValue !== targetValue) {
46
+ source[key] = targetValue;
47
+ }
48
+ });
49
+ };
50
+ /**
51
+ * Рекурсивно модифицирует массив, приводя его к виду целевого массива.
52
+ * Использует внутри {@link deepMutateObject}
53
+ *
54
+ * Обрезает лишние элементы, обновляет существующие и добавляет новые.
55
+ * Работает **мутативно** — изменяет исходный массив напрямую
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * const complexSource = [
60
+ * { id: 1, name: "John" },
61
+ * { id: 2, name: "Jane" }
62
+ * ];
63
+ * const complexTarget = [
64
+ * { id: 1, name: "Johnny" },
65
+ * { id: 3, name: "Bob" }
66
+ * ];
67
+ *
68
+ * deepMutateArray(complexSource, complexTarget);
69
+ *
70
+ * // complexSource теперь: [
71
+ * // { id: 1, name: "Johnny" },
72
+ * // { id: 3, name: "Bob" }
73
+ * // ]
74
+ * ```
75
+ */
76
+ export const deepMutateArray = (source, target) => {
77
+ // Обрезка длины массива
78
+ if (source.length > target.length) {
79
+ source.splice(target.length, source.length - target.length);
80
+ }
81
+ // Обновление элементов
82
+ target.forEach((targetItem, index) => {
83
+ const sourceItem = source[index];
84
+ if (Array.isArray(targetItem)) {
85
+ if (!Array.isArray(sourceItem))
86
+ source[index] = [];
87
+ deepMutateArray(source[index], targetItem);
88
+ }
89
+ else if (isObject(targetItem)) {
90
+ if (!isObject(sourceItem))
91
+ source[index] = {};
92
+ deepMutateObject(source[index], targetItem);
93
+ }
94
+ else if (sourceItem !== targetItem) {
95
+ source[index] = targetItem;
96
+ }
97
+ });
98
+ // Добавление новых элементов
99
+ while (source.length < target.length) {
100
+ source.push(target[source.length]);
101
+ }
102
+ };
103
+ /**
104
+ * Заменяет метод объекта обёрткой, передающей управление указанной функции
105
+ *
106
+ * Обёртка предоставляет контекст с оригинальным объектом, прокси-методом через {@link Reflect.apply} для вызова
107
+ * исходной реализации и аргументами вызова
108
+ *
109
+ * @param self - Объект, метод которого будет заменён
110
+ * @param key - Ключ метода в объекте
111
+ * @param func - Функция-обработчик, получающая контекст вызова
112
+ * @param [dynamic=false] - Использовать связывание `this` при вызове, что позволяет переносить цепочки на другие объекты
113
+ *
114
+ * @throws {TypeError} Если `self[key]` не является функцией
115
+ */
116
+ export const inject = (self, key, func, dynamic = false) => {
117
+ const original = self[key];
118
+ if (dynamic) {
119
+ // динамический this
120
+ self[key] = function (...args) {
121
+ const method = (...args) => Reflect.apply(original, this, args);
122
+ return func({ self: this, method, args });
123
+ };
124
+ }
125
+ else {
126
+ // статический (захват self и original на момент вызова)
127
+ const method = (...args) => Reflect.apply(original, self, args);
128
+ self[key] = ((...args) => func({ self, method, args }));
129
+ }
130
+ };
package/dist/omitter.d.ts CHANGED
@@ -1,72 +1,88 @@
1
1
  import type { DeepPartial, KEYS } from "./types.js";
2
2
  import type { ZIP } from "./zipper.js";
3
3
  /**
4
- * Исключает ключи из объекта `Source`, которые присутствуют в объекте `Target`.
5
- * Если значение ключа в `Source` и `Target` является объектом, рекурсивно применяет `OmitKEYS` к этим объектам
4
+ * Исключает ключи из объекта `Source`, которые присутствуют в объекте `Target`
5
+ *
6
+ * Если значение ключа в `Source` и `Target` является объектом, рекурсивно применяет себя к этим объектам
7
+ *
8
+ * @remarks Криво работает с функциональными методами и **НЕ** имеет защиты от бесконечных рекурсий
6
9
  *
7
10
  * @template Source - Исходный объект, из которого нужно исключить ключи
8
11
  * @template Target - Объект, ключи которого нужно исключить из `Source`
9
12
  *
10
13
  * @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
+ * ```typescript
15
+ * type Source = { a: number; b: { c: string; d: boolean }; e: string }
16
+ * type Target = { b: { c: string }; e: string }
17
+ * type Result = ExtractOmitSchema<Source, Target> // { a: number; b: { d: boolean } }
18
+ * ```
14
19
  */
15
20
  export type ExtractOmitSchema<Source, Target extends DeepPartial<Source>> = {
16
21
  [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
22
  };
18
23
  /**
19
- * Вычисляет тип Target на основе исходного типа Source и схемы удаления OmitSchema.
24
+ * Вычисляет тип Target на основе исходного типа Source и схемы удаления OmitSchema
25
+ *
20
26
  * Удаляет ключи, помеченные в схеме как null, и рекурсивно обрабатывает вложенные объекты
21
27
  *
28
+ * @remarks Криво работает с функциональными методами и **НЕ** имеет защиты от бесконечных рекурсий
29
+ *
30
+ * @template Source - Исходный тип объекта
31
+ * @template OmitSchema - Схема удаления ключей
32
+ *
22
33
  * @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 }
34
+ * ```typescript
35
+ * type Source = { a: number; b: { c: string; d: boolean }; e: string }
36
+ * type OmitSchema = { a: null; b: { c: null } }
37
+ * type Result = ExtractOmitTarget<Source, OmitSchema> // { b: { d: boolean }; e: string }
38
+ * ```
26
39
  */
27
40
  export type ExtractOmitTarget<Source, OmitSchema> = {
28
41
  [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
42
  };
30
43
  /**
31
- * Рекурсивно объединяет две схемы удаления ключей.
44
+ * Рекурсивно объединяет две схемы удаления ключей
45
+ *
32
46
  * Если ключ присутствует в обеих схемах:
33
47
  * - Если оба значения являются объектами — объединяет вложенные схемы
34
48
  * - Если хотя бы одно значение null — результат null (приоритет удаления)
35
49
  *
36
50
  * @example
51
+ * ```typescript
52
+ * type SchemaA = { a: null; b: { c: null } }
53
+ * type SchemaB = { b: { d: null }; e: null }
54
+ * type MergedSchema = MergeOmitSchemas<SchemaA, SchemaB> // { a: null; b: { c: null; d: null }; e: null }
37
55
  *
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 } (приоритет удаления)
56
+ * type ConflictSchema = MergeOmitSchemas<{ user: { name: null } }, { user: null }> // { user: null }
57
+ * ```
49
58
  */
50
59
  export type MergeOmitSchemas<S1, S2> = {
51
60
  [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
61
  };
53
62
  /**
54
- * Класс для удаления указанных ключей из объекта на основе схемы
63
+ * Очистка объектов от свойств на основе схемы
55
64
  *
56
- * @template Source - Исходный объект, из которого нужно удалить ключи
65
+ * @remarks Мутирует исходный объект
66
+ *
67
+ * @template Source - Тип объектов, из которых нужно удалить ключи
57
68
  * @template OmitSchema - Схема удаления
58
69
  *
59
70
  * @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 }
71
+ * ```typescript
72
+ * const source = { a: 1, b: { c: 2, d: 3 }, e: 4 }
73
+ * const schema = { b: { c: null } }
74
+ * const omitter = new Omitter(schema)
75
+ * const result = omitter.apply(source) // { a: 1, b: { d: 3 }, e: 4 }
76
+ * ```
64
77
  */
65
78
  export declare class Omitter<Source, OmitSchema> {
66
79
  #private;
67
- private readonly structure;
68
- readonly schema: OmitSchema;
69
- readonly zip: ZIP;
80
+ __structure: {
81
+ keys: Set<KEYS<OmitSchema>>;
82
+ nested: Map<KEYS<OmitSchema>, Omitter<any, any>>;
83
+ };
84
+ schema: OmitSchema;
85
+ zip: ZIP;
70
86
  constructor(schema: OmitSchema);
71
87
  /**
72
88
  * Получение хэша вложенного эмиттера
@@ -77,10 +93,17 @@ export declare class Omitter<Source, OmitSchema> {
77
93
  */
78
94
  left(key: KEYS<Source>): boolean;
79
95
  /**
80
- * Удаление ключей из объекта
96
+ * Удаление ключей из объекта по внутренней структуры
97
+ *
98
+ * @remarks Мутирует исходный объект
81
99
  *
82
- * @param source - Исходный объект
83
- * @returns Объект с удалёнными ключами
100
+ * @example
101
+ * ```typescript
102
+ * const source = { a: 1, b: { c: 2, d: 3 }, e: 4 }
103
+ * const schema = { b: { c: null } }
104
+ * const omitter = new Omitter(schema)
105
+ * const result = omitter.apply(source) // { a: 1, b: { d: 3 }, e: 4 }
106
+ * ```
84
107
  */
85
- run(source: Source): ExtractOmitTarget<Source, OmitSchema>;
108
+ apply(source: Source): ExtractOmitTarget<Source, OmitSchema>;
86
109
  }
package/dist/omitter.js CHANGED
@@ -1,18 +1,22 @@
1
1
  import { zipper } from "./zipper.js";
2
2
  /**
3
- * Класс для удаления указанных ключей из объекта на основе схемы
3
+ * Очистка объектов от свойств на основе схемы
4
4
  *
5
- * @template Source - Исходный объект, из которого нужно удалить ключи
5
+ * @remarks Мутирует исходный объект
6
+ *
7
+ * @template Source - Тип объектов, из которых нужно удалить ключи
6
8
  * @template OmitSchema - Схема удаления
7
9
  *
8
10
  * @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 }
11
+ * ```typescript
12
+ * const source = { a: 1, b: { c: 2, d: 3 }, e: 4 }
13
+ * const schema = { b: { c: null } }
14
+ * const omitter = new Omitter(schema)
15
+ * const result = omitter.apply(source) // { a: 1, b: { d: 3 }, e: 4 }
16
+ * ```
13
17
  */
14
18
  export class Omitter {
15
- structure;
19
+ __structure;
16
20
  schema;
17
21
  zip;
18
22
  constructor(schema) {
@@ -27,25 +31,10 @@ export class Omitter {
27
31
  }
28
32
  return true;
29
33
  }));
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);
34
+ this.__structure = { keys, nested };
43
35
  }
44
36
  /**
45
37
  * Рекурсивно удаляет ключи из объекта на основе структуры
46
- *
47
- * @param obj - Объект, из которого нужно удалить ключи
48
- * @param structure - Структура, определяющая ключи для удаления
49
38
  */
50
39
  #process(obj, structure) {
51
40
  const schema = structure.keys.size + structure.nested.size;
@@ -58,7 +47,7 @@ export class Omitter {
58
47
  structure.nested.forEach((omitter, key) => {
59
48
  const nested = obj[key];
60
49
  if (nested && typeof nested === "object")
61
- omitter.#process(nested, omitter.structure);
50
+ omitter.#process(nested, omitter.__structure);
62
51
  });
63
52
  }
64
53
  else {
@@ -72,7 +61,7 @@ export class Omitter {
72
61
  if (omitter) {
73
62
  const nested = obj[key];
74
63
  if (nested && typeof nested === "object") {
75
- omitter.#process(nested, omitter.structure);
64
+ omitter.#process(nested, omitter.__structure);
76
65
  }
77
66
  }
78
67
  }
@@ -80,13 +69,32 @@ export class Omitter {
80
69
  }
81
70
  }
82
71
  /**
83
- * Удаление ключей из объекта
72
+ * Получение хэша вложенного эмиттера
73
+ */
74
+ into(key) {
75
+ return this.__structure.nested.get(key)?.zip;
76
+ }
77
+ /**
78
+ * Проверяет, останется ли ключ в итоговом объекте
79
+ */
80
+ left(key) {
81
+ return !this.__structure.keys.has(key);
82
+ }
83
+ /**
84
+ * Удаление ключей из объекта по внутренней структуры
85
+ *
86
+ * @remarks Мутирует исходный объект
84
87
  *
85
- * @param source - Исходный объект
86
- * @returns Объект с удалёнными ключами
88
+ * @example
89
+ * ```typescript
90
+ * const source = { a: 1, b: { c: 2, d: 3 }, e: 4 }
91
+ * const schema = { b: { c: null } }
92
+ * const omitter = new Omitter(schema)
93
+ * const result = omitter.apply(source) // { a: 1, b: { d: 3 }, e: 4 }
94
+ * ```
87
95
  */
88
- run(source) {
89
- this.#process(source, this.structure);
96
+ apply(source) {
97
+ this.#process(source, this.__structure);
90
98
  return source;
91
99
  }
92
100
  }
package/dist/path.d.ts CHANGED
@@ -1,3 +1,22 @@
1
- export declare const pathRegExp: RegExp;
1
+ /**
2
+ * Преобразует путь в Unix-формат, заменяя все разделители на прямые слэши
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * toUnixPath("C:\\Users\\Project"); // "C:/Users/Project"
7
+ * toUnixPath("src\\components\\file.ts"); // "src/components/file.ts"
8
+ * ```
9
+ */
2
10
  export declare const toUnixPath: (path: string) => string;
11
+ /**
12
+ * Проверяет, является ли один путь дочерним {@link String.startsWith} по отношению к другому.
13
+ * Использует {@link toUnixPath} для нормализации путей
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * isChildPath("/home/user", "\\home\\user\\project"); // true
18
+ * isChildPath("src", "src/components/file.ts"); // true
19
+ * isChildPath("/home/user", "/home/other"); // false
20
+ * ```
21
+ */
3
22
  export declare const isChildPath: (parentPath: string, childPath: string) => boolean;
package/dist/path.js CHANGED
@@ -1,5 +1,24 @@
1
- export const pathRegExp = /[\\/]/g;
2
- export const toUnixPath = (path) => path.replace(pathRegExp, "/");
1
+ /**
2
+ * Преобразует путь в Unix-формат, заменяя все разделители на прямые слэши
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * toUnixPath("C:\\Users\\Project"); // "C:/Users/Project"
7
+ * toUnixPath("src\\components\\file.ts"); // "src/components/file.ts"
8
+ * ```
9
+ */
10
+ export const toUnixPath = (path) => path.replaceAll("\\", "/");
11
+ /**
12
+ * Проверяет, является ли один путь дочерним {@link String.startsWith} по отношению к другому.
13
+ * Использует {@link toUnixPath} для нормализации путей
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * isChildPath("/home/user", "\\home\\user\\project"); // true
18
+ * isChildPath("src", "src/components/file.ts"); // true
19
+ * isChildPath("/home/user", "/home/other"); // false
20
+ * ```
21
+ */
3
22
  export const isChildPath = (parentPath, childPath) => {
4
23
  const uChildPath = toUnixPath(childPath);
5
24
  const nParentPath = toUnixPath(parentPath) + "/";
@@ -0,0 +1,60 @@
1
+ import type { CanBeNullable } from "../types.js";
2
+ /**
3
+ * Стратегии обработки нуля в {@link toNumberFormat}:
4
+ * - "always" - "0" для всех исключительных ситуаций
5
+ * - "value" - "0" только при значении равном нулю, иначе `fallback`
6
+ * - "never" - `fallback` всегда
7
+ */
8
+ export type NumberFormatZeroStrategy = "always" | "value" | "never";
9
+ /**
10
+ * Конфигурация вывода из {@link toNumberFormat}
11
+ */
12
+ export interface NumberFormatConfig {
13
+ /**
14
+ * Количество знаков после запятой
15
+ */
16
+ fraction?: number;
17
+ /**
18
+ * Значение для исключительных ситуаций
19
+ *
20
+ * @see {@link NumberFormatZeroStrategy}
21
+ */
22
+ fallback?: string;
23
+ /**
24
+ * @example "₽"
25
+ */
26
+ postfix?: string;
27
+ /**
28
+ * Стратегия обработки нуля
29
+ */
30
+ zero?: NumberFormatZeroStrategy;
31
+ /**
32
+ * Разделитель дробной части
33
+ */
34
+ fractional?: string;
35
+ /**
36
+ * Разделитель тысяч
37
+ */
38
+ separator?: string;
39
+ }
40
+ export declare const NumberFormatRegExp: RegExp;
41
+ /**
42
+ * Форматирование числа по тысячам
43
+ *
44
+ * @param value - Входное значение (число, строка, null, undefined)
45
+ * @param [config] - Конфигурация форматирования
46
+ * @param [config.fraction=2] - {@link NumberFormatConfig.fraction}
47
+ * @param [config.fallback="---"] - {@link NumberFormatConfig.fallback}
48
+ * @param [config.postfix=""] - {@link NumberFormatConfig.postfix}
49
+ * @param [config.zero="value"] - {@link NumberFormatConfig.zero}
50
+ * @param [config.fractional=","] - {@link NumberFormatConfig.fractional}
51
+ * @param [config.separator=" "] - {@link NumberFormatConfig.separator}
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * toNumberFormat(1234); // "1 234"
56
+ * toNumberFormat(1234.5); // "1 234,50"
57
+ * toNumberFormat(1234.56); // "1 234,56"
58
+ * ```
59
+ */
60
+ export declare const toNumberFormat: (value: CanBeNullable<number | string>, { fraction, fallback, zero, postfix, fractional, separator }?: NumberFormatConfig) => string;
@@ -0,0 +1,34 @@
1
+ import { caseNumber } from "../cases.js";
2
+ import { round } from "./index.js";
3
+ export const NumberFormatRegExp = /\B(?=(\d{3})+(?!\d))/g;
4
+ /**
5
+ * Форматирование числа по тысячам
6
+ *
7
+ * @param value - Входное значение (число, строка, null, undefined)
8
+ * @param [config] - Конфигурация форматирования
9
+ * @param [config.fraction=2] - {@link NumberFormatConfig.fraction}
10
+ * @param [config.fallback="---"] - {@link NumberFormatConfig.fallback}
11
+ * @param [config.postfix=""] - {@link NumberFormatConfig.postfix}
12
+ * @param [config.zero="value"] - {@link NumberFormatConfig.zero}
13
+ * @param [config.fractional=","] - {@link NumberFormatConfig.fractional}
14
+ * @param [config.separator=" "] - {@link NumberFormatConfig.separator}
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * toNumberFormat(1234); // "1 234"
19
+ * toNumberFormat(1234.5); // "1 234,50"
20
+ * toNumberFormat(1234.56); // "1 234,56"
21
+ * ```
22
+ */
23
+ export const toNumberFormat = (value, { fraction = 2, fallback = "---", zero = "value", postfix, fractional = ",", separator = " " } = {}) => caseNumber(value, (v) => {
24
+ if (v === undefined)
25
+ return zero === "always" ? (postfix ? "0 " + postfix : "0") : fallback;
26
+ if (v === 0)
27
+ return zero === "never" ? fallback : postfix ? "0 " + postfix : "0";
28
+ if (fraction === 0)
29
+ return Math.round(v).toString().replace(NumberFormatRegExp, separator);
30
+ const { 0: integer, 1: float = "" } = round(v, fraction).toString().split(".");
31
+ const result = integer.replace(NumberFormatRegExp, separator);
32
+ const formatted = float ? `${result}${fractional}${float}` : result;
33
+ return postfix ? formatted + " " + postfix : formatted;
34
+ });
@@ -1,56 +1,56 @@
1
1
  /**
2
- * Приведение -/+ 0 к 0
2
+ * Приведение -0 и +0 к обычному 0
3
+ *
4
+ * Если не 0, то вернётся исходное значение
3
5
  */
4
- export declare const toZero: (value: number) => number;
6
+ export declare const normalizero: (value: number) => number;
7
+ export type RoundMethod = "up" | "down" | "math";
5
8
  /**
6
9
  * Округляет число до заданного количества знаков после запятой
7
10
  *
8
- * Если переданное значение является `NaN` возвращает 0
11
+ * Если переданное значение является `NaN` или 0, возвращает 0
9
12
  *
10
- * @param {number} value - Число для округления
11
- * @param {number} [fraction=2] - Количество знаков после запятой
12
- * @returns {number} Округленное число
13
+ * @param value - Число для округления
14
+ * @param [fraction=2] - Количество знаков после запятой
15
+ * @param [method="math"] - Метод округления
13
16
  */
14
- export declare const toRound: (value: number, fraction?: number) => number;
17
+ export declare const round: (value: number, fraction?: number, method?: RoundMethod) => number;
15
18
  /**
16
19
  * Вычисляет сумму всех переданных аргументов
17
20
  *
18
- * Сумма округляется с использованием функции {@link toRound}
19
- *
20
- * @param {...number} args - Числа для суммирования
21
- * @returns {number} Округленная сумма переданных чисел (или 0)
21
+ * Для пустого массива возвращает 0
22
22
  */
23
23
  export declare const sum: (...args: number[]) => number;
24
24
  /**
25
25
  * Вычисляет произведение всех переданных аргументов
26
26
  *
27
- * Произведение округляется с использованием функции {@link toRound}
28
- *
29
- * @param {...number} args - Числа для перемножения.
30
- * @returns {number} Округленное произведение переданных чисел (или 1)
27
+ * Для пустого массива возвращает 1
31
28
  */
32
29
  export declare const mult: (...args: number[]) => number;
33
30
  /**
34
31
  * Ограничивает значение в заданном диапазоне [min, max]
35
32
  *
36
- * Если значение меньше min, вернёт min. Если больше max — вернёт max.
37
- * Иначе возвращает само значение без изменений.
38
- *
39
- * @param {number} v - Исходное значение для ограничения
40
- * @param {number} min - Нижняя граница диапазона
41
- * @param {number} max - Верхняя граница диапазона
42
- *
43
- * @returns {number} Значение, ограниченное диапазоном [min, max]
33
+ * @example
34
+ * ```typescript
35
+ * clamp(5, 0, 10); // 5
36
+ * clamp(-5, 0, 10); // 0
37
+ * clamp(15, 0, 10); // 10
38
+ * ```
44
39
  */
45
- export declare const clamp: (v: number, min: number, max: number) => number;
46
- export declare const toRadians: (deg: number) => number;
40
+ export declare const clamp: (value: number, min: number, max: number) => number;
41
+ /**
42
+ * Преобразует градусы в радианы
43
+ */
44
+ export declare const toRadians: (degrees: number) => number;
45
+ /**
46
+ * Преобразует радианы в градусы
47
+ */
48
+ export declare const toDegrees: (radians: number) => number;
47
49
  /**
48
50
  * Линейная интерполяция между двумя числами
49
51
  *
50
- * @param {number} a - Начальное значение
51
- * @param {number} b - Конечное значение
52
- * @param {number} t - Весовой коэффициент, определяющий пропорцию между начальным и конечным значениями. Значение должно быть в диапазоне [0, 1]
53
- *
54
- * @returns {number} Результат линейной интерполяции между a и b при коэффициенте t
52
+ * @param a - Начальное значение
53
+ * @param b - Конечное значение
54
+ * @param t - Весовой коэффициент, определяющий состояние пропорции между начальным и конечным значениями. Должно быть в диапазоне `[0, 1]`
55
55
  */
56
56
  export declare const lerp: (a: number, b: number, t: number) => number;