@nemigo/helpers 2.0.2 → 2.2.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.
@@ -31,14 +31,13 @@ export class Aggregator {
31
31
  run(promise = false) {
32
32
  if (promise) {
33
33
  return (async () => {
34
+ // oxlint-disable-next-line eslint/require-await
34
35
  await Promise.allSettled(this.__calls.map(async (f) => f()));
35
36
  this.__calls.length = 0;
36
37
  })();
37
38
  }
38
- else {
39
- for (const call of this.__calls)
40
- void call();
41
- this.__calls.length = 0;
42
- }
39
+ for (const call of this.__calls)
40
+ void call();
41
+ this.__calls.length = 0;
43
42
  }
44
43
  }
@@ -56,6 +56,7 @@ export class AsyncContext {
56
56
  const result = await this.__async_storage.run(transaction, () => func(transaction));
57
57
  if (autoAfterCommit && transaction.length > 0) {
58
58
  await this.__submit(transaction);
59
+ // eslint-disable-next-line require-atomic-updates
59
60
  transaction.length = 0;
60
61
  }
61
62
  return result;
@@ -45,7 +45,7 @@ export declare class Future {
45
45
  * @param [options.key=Symbol()] - Ключ фьючерса
46
46
  * @param [options.delay=this.delay] - Задержка в миллисекундах
47
47
  *
48
- * @return Функция для очистки
48
+ * @returns Функция для очистки
49
49
  *
50
50
  * @remarks Ошибки полностью игнорируются
51
51
  */
@@ -12,7 +12,10 @@ export class Future {
12
12
  }
13
13
  __entries = new Map();
14
14
  __delete(key, entry) {
15
- entry.type === "timer" ? clearTimeout(entry.id) : clearInterval(entry.id);
15
+ if (entry.type === "timer")
16
+ clearTimeout(entry.id);
17
+ else
18
+ clearInterval(entry.id);
16
19
  this.__entries.delete(key);
17
20
  }
18
21
  /**
@@ -41,7 +44,7 @@ export class Future {
41
44
  * @param [options.key=Symbol()] - Ключ фьючерса
42
45
  * @param [options.delay=this.delay] - Задержка в миллисекундах
43
46
  *
44
- * @return Функция для очистки
47
+ * @returns Функция для очистки
45
48
  *
46
49
  * @remarks Ошибки полностью игнорируются
47
50
  */
@@ -66,6 +69,8 @@ export class Future {
66
69
  }
67
70
  const entry = { type, id };
68
71
  this.__entries.set(key, entry);
69
- return () => this.__delete(key, entry);
72
+ return () => {
73
+ this.__delete(key, entry);
74
+ };
70
75
  }
71
76
  }
@@ -16,7 +16,14 @@ export const createManualPromise = () => {
16
16
  *
17
17
  * @remarks При `success = false` промис отклоняется с ошибкой `"delay rejected"`
18
18
  */
19
- export const delay = (ms, success = true) => new Promise((resolve, reject) => setTimeout(() => (success ? resolve() : reject(new Error("delay rejected"))), ms));
19
+ export const delay = (ms, success = true) => new Promise((resolve, reject) => {
20
+ setTimeout(() => {
21
+ if (success)
22
+ resolve();
23
+ else
24
+ reject(new Error("delay rejected"));
25
+ }, ms);
26
+ });
20
27
  /**
21
28
  * Создаёт debounce-функцию, которая откладывает выполнение до тех пор, пока не пройдёт указанное время без новых вызовов
22
29
  *
@@ -90,10 +97,10 @@ export const boundary = async (func, fallback) => {
90
97
  try {
91
98
  return await func();
92
99
  }
93
- catch (e) {
100
+ catch (error) {
94
101
  if (typeof fallback === "function") {
95
- // @ts-expect-error <тут не типизировать>
96
- return fallback(e);
102
+ // @ts-expect-error : тут не типизировать
103
+ return fallback(error);
97
104
  }
98
105
  return fallback;
99
106
  }
@@ -24,9 +24,15 @@ export class Loader {
24
24
  this.reset();
25
25
  }
26
26
  __check(version) {
27
- if (this.__heap.length === 0)
28
- return this.reset();
29
- void Promise.allSettled(this.__heap).then(() => this.__reset(version));
27
+ if (this.__heap.length === 0) {
28
+ this.reset();
29
+ }
30
+ else {
31
+ // oxlint-disable-next-line promise/always-return
32
+ void Promise.allSettled(this.__heap).then(() => {
33
+ this.__reset(version);
34
+ });
35
+ }
30
36
  }
31
37
  __awaiter(version) {
32
38
  this.__onchange(true);
@@ -14,7 +14,7 @@ export type QueueHandler<T> = (item: T, abort: () => void) => CanBePromise;
14
14
  * const queue = new Queue(async (url, abort) => {
15
15
  * try {
16
16
  * await fetch(url);
17
- * } catch (e) {
17
+ * } catch {
18
18
  * abort(); // прекращает обработку оставшихся URL
19
19
  * }
20
20
  * }, 50);
@@ -40,6 +40,7 @@ export declare class Queue<T> {
40
40
  * @param [run=true] - Запуск выполнения через {@link run}
41
41
  */
42
42
  push(item: T, run?: boolean): void;
43
+ __start(): Promise<void>;
43
44
  /**
44
45
  * @param [delay=this.delay] - Задержка перед запуском шага очереди
45
46
  *
@@ -12,7 +12,7 @@
12
12
  * const queue = new Queue(async (url, abort) => {
13
13
  * try {
14
14
  * await fetch(url);
15
- * } catch (e) {
15
+ * } catch {
16
16
  * abort(); // прекращает обработку оставшихся URL
17
17
  * }
18
18
  * }, 50);
@@ -45,6 +45,27 @@ export class Queue {
45
45
  if (run)
46
46
  this.run();
47
47
  }
48
+ async __start() {
49
+ if (this.__queue.length === 0) {
50
+ this.stop();
51
+ return;
52
+ }
53
+ const item = this.__queue.shift();
54
+ let aborted = false;
55
+ try {
56
+ await this.__handle(item, () => {
57
+ aborted = true;
58
+ });
59
+ }
60
+ finally {
61
+ if (!aborted) {
62
+ if (this.__queue.length > 0)
63
+ this.run();
64
+ else
65
+ this.stop();
66
+ }
67
+ }
68
+ }
48
69
  /**
49
70
  * @param [delay=this.delay] - Задержка перед запуском шага очереди
50
71
  *
@@ -52,26 +73,11 @@ export class Queue {
52
73
  */
53
74
  run(delay = this.delay) {
54
75
  this.stop();
55
- const start = async () => {
56
- if (this.__queue.length === 0)
57
- return this.stop();
58
- const item = this.__queue.shift();
59
- let aborted = false;
60
- try {
61
- await this.__handle(item, () => {
62
- aborted = true;
63
- });
64
- }
65
- finally {
66
- if (!aborted)
67
- this.__queue.length > 0 ? this.run() : this.stop();
68
- }
69
- };
70
76
  if (delay) {
71
- this.__timeout = setTimeout(() => void start(), delay);
77
+ this.__timeout = setTimeout(() => void this.__start(), delay);
72
78
  }
73
79
  else {
74
- void start();
80
+ void this.__start();
75
81
  }
76
82
  }
77
83
  stop() {
package/dist/clean.js CHANGED
@@ -83,7 +83,7 @@ export const deepCleanObject = (data) => {
83
83
  if (value !== "" && value !== null && value !== undefined) {
84
84
  if (typeof value === "object") {
85
85
  const cleaned = deepCleanObject(value);
86
- if (Object.keys(cleaned).length !== 0)
86
+ if (Object.keys(cleaned).length > 0)
87
87
  result[key] = cleaned;
88
88
  }
89
89
  else {
package/dist/emitter.js CHANGED
@@ -6,12 +6,12 @@
6
6
  export class Emitter {
7
7
  __listeners = new Map();
8
8
  dispatch(event, data) {
9
- this.__listeners.forEach((handler, key) => {
9
+ for (const [key, handler] of this.__listeners.entries()) {
10
10
  if (event === handler.event)
11
11
  handler.callback(data);
12
12
  if (handler.once)
13
13
  this.__listeners.delete(key);
14
- });
14
+ }
15
15
  }
16
16
  /**
17
17
  * @param event - Ключ события
@@ -37,7 +37,7 @@ export interface RemoveOptions {
37
37
  *
38
38
  * @throws {Error} Если это была не пустая директория при {@link RemoveOptions.empty} или не соответствует ожидаемому типу {@link RemoveOptions.expected}
39
39
  */
40
- export declare function remove(path: PathLike, options?: RemoveOptions): Promise<Stats | null>;
40
+ export declare const remove: (path: PathLike, options?: RemoveOptions) => Promise<Stats | null>;
41
41
  /**
42
42
  * Опции поведения для функции {@link remake}
43
43
  */
package/dist/explorer.js CHANGED
@@ -33,7 +33,7 @@ export { exists };
33
33
  *
34
34
  * @throws {Error} Если это была не пустая директория при {@link RemoveOptions.empty} или не соответствует ожидаемому типу {@link RemoveOptions.expected}
35
35
  */
36
- export async function remove(path, options = {}) {
36
+ export const remove = async (path, options = {}) => {
37
37
  const { empty = false, expected } = options;
38
38
  let existed;
39
39
  if (empty) {
@@ -52,7 +52,7 @@ export async function remove(path, options = {}) {
52
52
  }
53
53
  await rm(path, { recursive: true });
54
54
  return existed;
55
- }
55
+ };
56
56
  /**
57
57
  * Удаляет (если существовала) и заново создаёт директорию по указанному пути
58
58
  *
@@ -80,6 +80,6 @@ export const compare = async (path, expected, strict = false) => {
80
80
  const existed = await exists(path, "file", strict);
81
81
  if (!existed)
82
82
  return false;
83
- const content = await readFile(path, "utf-8");
83
+ const content = await readFile(path, "utf8");
84
84
  return content === expected;
85
85
  };
package/dist/files.js CHANGED
@@ -5,8 +5,10 @@
5
5
  */
6
6
  export const fileToBase64 = (file) => new Promise((resolve, reject) => {
7
7
  const reader = new FileReader();
8
- reader.onload = () => resolve(reader.result);
9
- reader.onerror = reject;
8
+ reader.addEventListener("load", () => {
9
+ resolve(reader.result);
10
+ });
11
+ reader.addEventListener("error", reject);
10
12
  reader.readAsDataURL(file);
11
13
  });
12
14
  /**
package/dist/fish.js CHANGED
@@ -23,9 +23,9 @@ export const profish = (func) => {
23
23
  let promise;
24
24
  return (...args) => {
25
25
  if (!promise) {
26
- promise = func(...args).catch((err) => {
26
+ promise = func(...args).catch((error) => {
27
27
  promise = undefined;
28
- throw err;
28
+ throw error;
29
29
  });
30
30
  }
31
31
  return promise;
@@ -57,14 +57,12 @@ export const goldfish = (func, strategy) => {
57
57
  *
58
58
  * @throws {unknown} Если вызов `func` завершается ошибкой, результат не кэшируется, и ошибка пробрасывается
59
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
- };
60
+ export const memofish = (func, serialize, cache = new Map()) => (...args) => {
61
+ const key = serialize(args, cache);
62
+ const existed = cache.get(key);
63
+ if (existed)
64
+ return existed;
65
+ const result = func(...args);
66
+ cache.set(key, result);
67
+ return result;
70
68
  };
@@ -33,4 +33,6 @@ export const getDocumentCookie = (name) => {
33
33
  /**
34
34
  * Удаляет куку по имени, устанавливая Max-Age=0 через {@link setDocumentCookie}
35
35
  */
36
- export const deleteDocumentCookie = (name, Path) => setDocumentCookie(name, "", { Path, MaxAge: 0 });
36
+ export const deleteDocumentCookie = (name, Path) => {
37
+ setDocumentCookie(name, "", { Path, MaxAge: 0 });
38
+ };
@@ -2,7 +2,10 @@ import { useConditionGuard } from "../index.js";
2
2
  /**
3
3
  * Предотвращает стандартное поведение события и останавливает его всплытие
4
4
  */
5
- export const preventStop = (e) => (e.preventDefault(), e.stopPropagation());
5
+ export const preventStop = (e) => {
6
+ e.preventDefault();
7
+ e.stopPropagation();
8
+ };
6
9
  /**
7
10
  * @param handler - Обработчик события
8
11
  * @param [guards={}] - Условия выполнений
@@ -31,10 +34,8 @@ export const createEnterHandler = (handler, props = {}) => (event) => {
31
34
  if (isEnter)
32
35
  preventStop(event);
33
36
  }
34
- else {
35
- if (useConditionGuard(preventStopGuard, { event, isEnter }))
36
- preventStop(event);
37
- }
37
+ else if (useConditionGuard(preventStopGuard, { event, isEnter }))
38
+ preventStop(event);
38
39
  if (isEnter) {
39
40
  if (handler && useConditionGuard(eventHandlerGuard, event))
40
41
  void handler(event);
@@ -43,6 +44,7 @@ export const createEnterHandler = (handler, props = {}) => (event) => {
43
44
  secondary?.(event);
44
45
  }
45
46
  };
47
+ // oxlint-disable-next-line typescript/explicit-module-boundary-types
46
48
  export const isKeyboardEvent = (e) => !!e.code;
47
49
  /**
48
50
  * Создаёт обработчик события контекстного меню
@@ -121,7 +123,9 @@ export const createClickHandlers = (singleClickHandler, doubleClickHandler, dela
121
123
  export const createEventListener = (event, listener, options = {}) => {
122
124
  const target = options.target ?? window;
123
125
  target.addEventListener(event, listener, options);
124
- return () => target.removeEventListener(event, listener);
126
+ return () => {
127
+ target.removeEventListener(event, listener);
128
+ };
125
129
  };
126
130
  /**
127
131
  * Создаёт обработчик события `scrollTo`
@@ -43,19 +43,17 @@ export const formon = (form, multi = false) => {
43
43
  if (multi) {
44
44
  const result = {};
45
45
  for (const { 0: key, 1: value } of form.entries()) {
46
- if (result[key] !== undefined) {
46
+ if (result[key] === undefined) {
47
+ result[key] = value;
48
+ }
49
+ else {
47
50
  if (!Array.isArray(result[key])) {
48
51
  result[key] = [result[key]];
49
52
  }
50
53
  result[key].push(value);
51
54
  }
52
- else {
53
- result[key] = value;
54
- }
55
55
  }
56
56
  return result;
57
57
  }
58
- else {
59
- return Object.fromEntries(form.entries());
60
- }
58
+ return Object.fromEntries(form.entries());
61
59
  };
package/dist/index.d.ts CHANGED
@@ -17,7 +17,7 @@ export declare const parsify: <T>(v: T) => T;
17
17
  /**
18
18
  * Агрегация функций в одну
19
19
  */
20
- export declare const aggregate: (...args: (() => void)[]) => () => void;
20
+ export declare const aggregate: (...args: (() => void)[]) => (() => void);
21
21
  /**
22
22
  * Проверяет, является ли значение объектом
23
23
  *
@@ -90,4 +90,4 @@ export interface JiffApplyProps<CustomPatch extends NeverPatch = never> {
90
90
  *
91
91
  * @see https://jsonpatch.com/ Документация стандарта
92
92
  */
93
- export declare function jiffApply<CustomPatch extends NeverPatch = never>(obj: object, jiff: (CustomPatch | JiffPatch)[], props?: JiffApplyProps<CustomPatch>): void;
93
+ export declare const jiffApply: <CustomPatch extends NeverPatch = never>(obj: object, jiff: (CustomPatch | JiffPatch)[], props?: JiffApplyProps<CustomPatch>) => void;
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * @see https://jsonpatch.com/ Документация стандарта
13
13
  */
14
- export function jiffApply(obj, jiff, props) {
14
+ export const jiffApply = (obj, jiff, props) => {
15
15
  for (const patch of jiff) {
16
16
  // Разделение пути патча на массив сегментов ("/foo/bar" -> ["foo", "bar"])
17
17
  const path = patch.path.split("/").slice(1);
@@ -34,12 +34,10 @@ export function jiffApply(obj, jiff, props) {
34
34
  cursor = cursor[property];
35
35
  }
36
36
  // Для патчей "remove" и "replace" проверяем существование целевого элемента
37
- if (patch.op === "remove" || patch.op === "replace") {
38
- if (!(target in cursor)) {
39
- // Ожидаемый ключ не найден
40
- cursor[target] = {};
41
- props?.onerror?.({ type: "property", property: target, obj, cursor, patch });
42
- }
37
+ if ((patch.op === "remove" || patch.op === "replace") && !(target in cursor)) {
38
+ // Ожидаемый ключ не найден
39
+ cursor[target] = {};
40
+ props?.onerror?.({ type: "property", property: target, obj, cursor, patch });
43
41
  }
44
42
  switch (patch.op) {
45
43
  case "remove":
@@ -61,4 +59,4 @@ export function jiffApply(obj, jiff, props) {
61
59
  props?.onerror?.({ type: "operation", obj, patch });
62
60
  }
63
61
  }
64
- }
62
+ };
@@ -4,4 +4,4 @@ import type { JiffPatch } from "./types.js";
4
4
  *
5
5
  * @see https://jsonpatch.com/ Документация стандарта
6
6
  */
7
- export declare function jiffExtract(source: object, target: object): JiffPatch[];
7
+ export declare const jiffExtract: (source: object, target: object) => JiffPatch[];
@@ -30,25 +30,25 @@ const handleArrayDifference = (sourceArr, targetArr, currentPath, diffs) => {
30
30
  };
31
31
  const handleObjectDifference = (sourceObj, targetObj, currentPath, diffs) => {
32
32
  // Удаление отсутствующих свойств
33
- Object.keys(sourceObj).forEach((key) => {
33
+ for (const key of Object.keys(sourceObj)) {
34
34
  if (!(key in targetObj)) {
35
35
  diffs.remove.push({
36
36
  op: "remove",
37
37
  path: `/${[...currentPath, key].join("/")}`,
38
38
  });
39
39
  }
40
- });
40
+ }
41
41
  // Обработка существующих и новых свойств
42
- Object.entries(targetObj).forEach(([key, targetValue]) => {
42
+ for (const [key, targetValue] of Object.entries(targetObj)) {
43
43
  const path = [...currentPath, key];
44
44
  const sourceValue = sourceObj[key];
45
- if (!(key in sourceObj)) {
46
- diffs.add.push({ op: "add", path: `/${path.join("/")}`, value: targetValue });
45
+ if (key in sourceObj) {
46
+ compareValues(sourceValue, targetValue, path, diffs);
47
47
  }
48
48
  else {
49
- compareValues(sourceValue, targetValue, path, diffs);
49
+ diffs.add.push({ op: "add", path: `/${path.join("/")}`, value: targetValue });
50
50
  }
51
- });
51
+ }
52
52
  };
53
53
  const compareValues = (source, target, currentPath, diffs) => {
54
54
  if (!isSameType(source, target)) {
@@ -71,7 +71,7 @@ const compareValues = (source, target, currentPath, diffs) => {
71
71
  *
72
72
  * @see https://jsonpatch.com/ Документация стандарта
73
73
  */
74
- export function jiffExtract(source, target) {
74
+ export const jiffExtract = (source, target) => {
75
75
  const diffs = {
76
76
  remove: [],
77
77
  replace: [],
@@ -79,4 +79,4 @@ export function jiffExtract(source, target) {
79
79
  };
80
80
  compareValues(source, target, [], diffs);
81
81
  return [...diffs.remove.reverse(), ...diffs.replace, ...diffs.add];
82
- }
82
+ };
package/dist/lens.d.ts CHANGED
@@ -47,6 +47,5 @@ export declare class Lens<O> {
47
47
  __mode: LensMode;
48
48
  __schema: LensSchema<O>;
49
49
  constructor(config: LensConfig<O>);
50
- reconstruct(config: LensConfig<O>): void;
51
50
  check(key: keyof O): boolean;
52
51
  }
package/dist/lens.js CHANGED
@@ -18,9 +18,6 @@ export class Lens {
18
18
  __mode;
19
19
  __schema;
20
20
  constructor(config) {
21
- this.reconstruct(config);
22
- }
23
- reconstruct(config) {
24
21
  this.__mode = config.mode ?? "exclude";
25
22
  this.__schema = config.schema ?? {};
26
23
  }
package/dist/mutate.js CHANGED
@@ -20,17 +20,16 @@ import { isObject, isSameType } from "./index.js";
20
20
  */
21
21
  export const deepMutateObject = (source, target) => {
22
22
  // Удаление лишних свойств
23
- Object.keys(source).forEach((key) => {
23
+ for (const key of Object.keys(source))
24
24
  if (!(key in target))
25
25
  delete source[key];
26
- });
27
26
  // Обновление свойств
28
- Object.entries(target).forEach(([key, targetValue]) => {
27
+ for (const [key, targetValue] of Object.entries(target)) {
29
28
  const sourceValue = source[key];
30
29
  // Проверка изменения типа данных
31
30
  if (!isSameType(sourceValue, targetValue)) {
32
31
  source[key] = targetValue; // Полная замена при разном типе
33
- return;
32
+ continue;
34
33
  }
35
34
  if (Array.isArray(targetValue)) {
36
35
  if (!Array.isArray(sourceValue))
@@ -45,7 +44,7 @@ export const deepMutateObject = (source, target) => {
45
44
  else if (sourceValue !== targetValue) {
46
45
  source[key] = targetValue;
47
46
  }
48
- });
47
+ }
49
48
  };
50
49
  /**
51
50
  * Рекурсивно модифицирует массив, приводя его к виду целевого массива.
@@ -79,7 +78,7 @@ export const deepMutateArray = (source, target) => {
79
78
  source.splice(target.length, source.length - target.length);
80
79
  }
81
80
  // Обновление элементов
82
- target.forEach((targetItem, index) => {
81
+ for (const [index, targetItem] of target.entries()) {
83
82
  const sourceItem = source[index];
84
83
  if (Array.isArray(targetItem)) {
85
84
  if (!Array.isArray(sourceItem))
@@ -94,7 +93,7 @@ export const deepMutateArray = (source, target) => {
94
93
  else if (sourceItem !== targetItem) {
95
94
  source[index] = targetItem;
96
95
  }
97
- });
96
+ }
98
97
  // Добавление новых элементов
99
98
  while (source.length < target.length) {
100
99
  source.push(target[source.length]);
@@ -117,8 +116,11 @@ export const inject = (self, key, func, dynamic = false) => {
117
116
  const original = self[key];
118
117
  if (dynamic) {
119
118
  // динамический this
119
+ // oxlint-disable-next-line eslint/func-names
120
+ // eslint-disable-next-line func-names
120
121
  self[key] = function (...args) {
121
- const method = (...args) => Reflect.apply(original, this, args);
122
+ // eslint-disable-next-line unicorn/consistent-function-scoping
123
+ const method = (...method_args) => Reflect.apply(original, this, method_args);
122
124
  return func({ self: this, method, args });
123
125
  };
124
126
  }
package/dist/omitter.js CHANGED
@@ -41,14 +41,14 @@ export class Omitter {
41
41
  const keys = Object.keys(obj);
42
42
  if (schema < keys.length) {
43
43
  // Стратегия по схеме: итерируемся по ключам схемы
44
- structure.keys.forEach((key) => {
44
+ for (const key of structure.keys) {
45
45
  delete obj[key];
46
- });
47
- structure.nested.forEach((omitter, key) => {
46
+ }
47
+ for (const [key, omitter] of structure.nested.entries()) {
48
48
  const nested = obj[key];
49
49
  if (nested && typeof nested === "object")
50
50
  omitter.#process(nested, omitter.__structure);
51
- });
51
+ }
52
52
  }
53
53
  else {
54
54
  // Стратегия по объекту: итерируемся по ключам объекта
@@ -1,6 +1,6 @@
1
1
  import { caseNumber } from "../cases.js";
2
2
  import { round } from "./index.js";
3
- export const NumberFormatRegExp = /\B(?=(\d{3})+(?!\d))/g;
3
+ export const NumberFormatRegExp = /\B(?=(?:\d{3})+(?!\d))/gu;
4
4
  /**
5
5
  * Форматирование числа по тысячам
6
6
  *
package/dist/promoter.js CHANGED
@@ -4,11 +4,11 @@
4
4
  export class Promoter {
5
5
  __subs = new Map();
6
6
  notify(event) {
7
- this.__subs.forEach(({ callback, once }, key) => {
7
+ for (const [key, { callback, once }] of this.__subs.entries()) {
8
8
  callback(event);
9
9
  if (once)
10
10
  this.__subs.delete(key);
11
- });
11
+ }
12
12
  }
13
13
  /**
14
14
  * @param callback - Функция подписчика
@@ -34,7 +34,8 @@ export class Promoter {
34
34
  */
35
35
  unsubscribe(key) {
36
36
  if (key === undefined)
37
- return this.__subs.clear();
38
- this.__subs.delete(key);
37
+ this.__subs.clear();
38
+ else
39
+ this.__subs.delete(key);
39
40
  }
40
41
  }
package/dist/script.js CHANGED
@@ -1,3 +1,5 @@
1
+ /* eslint-disable no-console */
2
+ // oxlint-disable no-console
1
3
  import { exec } from "node:child_process";
2
4
  import { MS_IN_MINUTE } from "./datetime/delta.js";
3
5
  /**
@@ -18,7 +20,7 @@ import { MS_IN_MINUTE } from "./datetime/delta.js";
18
20
  function getProcessFlag(cmd, name, strict = true) {
19
21
  const argv = cmd.slice(2);
20
22
  const index = argv.indexOf(name);
21
- if (index > -1) {
23
+ if (index !== -1) {
22
24
  const value = argv[index + 1];
23
25
  if (value)
24
26
  return value;
@@ -59,7 +61,7 @@ export { getProcessFlag };
59
61
  * await execute("/path", "long-running-command", { timeout: null | 0 });
60
62
  * ```
61
63
  */
62
- export const execute = async (path, command, { logger = {}, timeout = 5 * MS_IN_MINUTE } = {}) => new Promise((resolve, reject) => {
64
+ export const execute = (path, command, { logger = {}, timeout = 5 * MS_IN_MINUTE } = {}) => new Promise((resolve, reject) => {
63
65
  if (logger.before)
64
66
  console.log(logger.before(path));
65
67
  let process = null;
package/dist/string.js CHANGED
@@ -16,7 +16,7 @@ export const clearPH = (str = "", placeholder = "_") => str.replaceAll(placehold
16
16
  * Регулярное выражение для захвата всех нецифровых символов из строки.
17
17
  * Используется для удаления всех символов, кроме цифр 0-9
18
18
  */
19
- export const oDigitRegExp = /\D/g;
19
+ export const oDigitRegExp = /\D/gu;
20
20
  /**
21
21
  * Удаляет все символы из строки, кроме цифр 0-9
22
22
  *
@@ -32,7 +32,7 @@ export const oDigitClean = (str = "") => str.replace(oDigitRegExp, "");
32
32
  /**
33
33
  * Регулярное выражение для захвата одного или более пробельных символов подряд
34
34
  */
35
- export const oSpaceRegExp = /\s+/g;
35
+ export const oSpaceRegExp = /\s+/gu;
36
36
  /**
37
37
  * Нормализует пробелы в строке: заменяет множественные пробелы на один и удаляет пробелы в начале и конце
38
38
  *
@@ -6,10 +6,10 @@ export type UrlParamValue = CanBeNullable<string | number | boolean>;
6
6
  /**
7
7
  * KV-параметры для URL для {@link pushUrlParams} и {@link clearUrlParams}
8
8
  */
9
- export type UrlParamKV<V extends UrlParamValue = UrlParamValue> = {
9
+ export interface UrlParamKV<V extends UrlParamValue = UrlParamValue> {
10
10
  key: string;
11
11
  value?: V;
12
- };
12
+ }
13
13
  /**
14
14
  * Параметры для URL для {@link pushUrlParams} и {@link clearUrlParams}
15
15
  */
@@ -75,7 +75,7 @@ export const pushUrlParams = (url, params, unsafe = false) => {
75
75
  if (splitted[1]) {
76
76
  splitted[1] = splitted[1].replaceAll("=&", "&");
77
77
  if (splitted[1].endsWith("="))
78
- splitted[1] = splitted[1].slice(0, splitted[1].length - 1);
78
+ splitted[1] = splitted[1].slice(0, -1);
79
79
  }
80
80
  url.href = splitted.join("?");
81
81
  }
@@ -124,12 +124,10 @@ export const mergePushUrlParams = (...args) => {
124
124
  else
125
125
  acc.push({ key: param.key, value: true });
126
126
  }
127
- else {
128
- if (existed)
129
- existed.value = String(param.value);
130
- else
131
- acc.push({ key: param.key, value: param.value });
132
- }
127
+ else if (existed)
128
+ existed.value = String(param.value);
129
+ else
130
+ acc.push({ key: param.key, value: param.value });
133
131
  }
134
132
  }
135
133
  }
package/dist/url/slug.js CHANGED
@@ -64,7 +64,7 @@ export const toSlug = (str, separator = "-") => {
64
64
  let wasSpace = false;
65
65
  for (const _char of str.split("")) {
66
66
  const char = _char.toLowerCase();
67
- const code = char.charCodeAt(0);
67
+ const code = char.codePointAt(0);
68
68
  // Кириллица (а-я, ё)
69
69
  if ((code >= 1072 && code <= 1103) || code === 1105) {
70
70
  buf.push(cyrillicToLatinMap.get(char) ?? char);
@@ -82,17 +82,15 @@ export const toSlug = (str, separator = "-") => {
82
82
  }
83
83
  // Пробуем нормализовать символы с диакритиками в латиницу (é -> e)
84
84
  else {
85
- const normalized = char.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
86
- const nCode = normalized.charCodeAt(0);
85
+ const normalized = char.normalize("NFD").replaceAll(/[\u0300-\u036F]/gu, "");
86
+ const nCode = normalized.codePointAt(0);
87
87
  if (normalized.length === 1 && nCode >= 97 && nCode <= 122) {
88
88
  buf.push(normalized);
89
89
  wasSpace = false;
90
90
  }
91
- else {
92
- if (!wasSpace && buf.length > 0) {
93
- buf.push(separator);
94
- wasSpace = true;
95
- }
91
+ else if (!wasSpace && buf.length > 0) {
92
+ buf.push(separator);
93
+ wasSpace = true;
96
94
  }
97
95
  }
98
96
  }
package/dist/veil.js CHANGED
@@ -9,7 +9,7 @@ export const unveil = (veiled) => {
9
9
  const decoded = atob(decodeURIComponent(veiled));
10
10
  const bytes = new Uint8Array(decoded.length);
11
11
  for (let i = 0; i < decoded.length; i++)
12
- bytes[i] = decoded.charCodeAt(i);
12
+ bytes[i] = decoded.codePointAt(i);
13
13
  return JSON.parse(decoder.decode(bytes));
14
14
  };
15
15
  /**
@@ -21,6 +21,6 @@ export const unveil = (veiled) => {
21
21
  export const veil = (snap) => {
22
22
  const str = JSON.stringify(snap);
23
23
  const bytes = encoder.encode(str);
24
- const binary = String.fromCharCode(...bytes);
24
+ const binary = String.fromCodePoint(...bytes);
25
25
  return encodeURIComponent(btoa(binary));
26
26
  };
package/dist/xod.d.ts CHANGED
@@ -244,4 +244,3 @@ export declare const xod: {
244
244
  height: typeof numberStrictSchema;
245
245
  }, z.core.$strip>]>;
246
246
  };
247
- export default xod;
package/dist/xod.js CHANGED
@@ -27,14 +27,16 @@ export const throwValueIssue = (props) => {
27
27
  * - `ETC` → ZodError
28
28
  */
29
29
  export const nullSchema = z.union([
30
- // biome-ignore format: потеря смысла
30
+ // biome-ignore format : потеря смысла
31
+ // oxlint-disable-next-line unicorn/no-useless-undefined
32
+ // eslint-disable-next-line unicorn/no-useless-undefined
31
33
  z.null().optional().transform(() => undefined),
32
34
  z.string().transform((value, ctx) => {
33
35
  if (!value)
34
- return undefined;
36
+ return;
35
37
  const flat = value.trim().toLowerCase();
36
38
  if (flat === "undefined" || flat === "null")
37
- return undefined;
39
+ return;
38
40
  return throwValueIssue({
39
41
  ctx,
40
42
  value,
@@ -237,4 +239,3 @@ export const xod = {
237
239
  lwhStrict: lwhStrictSchema,
238
240
  lwhStrictOptional: lwhStrictSchemaOptional,
239
241
  };
240
- export default xod;
package/dist/zipper.js CHANGED
@@ -4,7 +4,7 @@
4
4
  export const polynomial = Uint32Array.from({ length: 256 }, (_, i) => {
5
5
  let crc = i;
6
6
  for (let j = 8; j--;)
7
- crc = (crc >>> 1) ^ (0xedb88320 & -(crc & 1));
7
+ crc = (crc >>> 1) ^ (0xed_b8_83_20 & -(crc & 1));
8
8
  return crc;
9
9
  });
10
10
  /**
@@ -31,6 +31,9 @@ export const zipper = (data, prefix = "zip:") => {
31
31
  const str = JSON.stringify(data);
32
32
  let crc = 0 ^ -1;
33
33
  for (let i = str.length - 1; i >= 0; i--)
34
- crc = (crc >>> 8) ^ polynomial[(crc ^ str.charCodeAt(i)) & 0xff];
35
- return prefix + ((crc ^ -1) >>> 0).toString(16).padStart(8, "0");
34
+ crc = (crc >>> 8) ^ polynomial[(crc ^ str.codePointAt(i)) & 0xff];
35
+ const hash = Math.trunc(crc ^ -1)
36
+ .toString(16)
37
+ .padStart(8, "0");
38
+ return prefix + hash;
36
39
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nemigo/helpers",
3
- "version": "2.0.2",
3
+ "version": "2.2.1",
4
4
  "private": false,
5
5
  "author": {
6
6
  "name": "Vlad Logvin",
@@ -8,15 +8,13 @@
8
8
  },
9
9
  "type": "module",
10
10
  "scripts": {
11
- "build": "svelte-package && rimraf .svelte-kit",
11
+ "build": "bunx --bun svelte-package && bunx --bun rimraf .svelte-kit",
12
12
  "check": "bunx --bun tsc --noemit",
13
13
  "eslint": "bunx --bun eslint ./",
14
- "eslint:fix": "bunx --bun eslint --fix ./",
15
- "lint": "biome lint",
16
- "lint:fix": "biome lint --fix --unsafe",
17
- "lint:fix:unsafe": "biome lint --fix --unsafe",
14
+ "oxlint": "bunx --bun oxlint --config .././../oxlintrc.jsonc --ignore-path ../configs/.eslint.ignore ./",
15
+ "bilint": "bunx --bun biome lint",
18
16
  "test": "bun test",
19
- "format": "biome check --write --linter-enabled=false"
17
+ "format": "bunx --bun biome check --write --linter-enabled=false"
20
18
  },
21
19
  "exports": {
22
20
  ".": {
@@ -197,7 +195,7 @@
197
195
  }
198
196
  },
199
197
  "peerDependencies": {
200
- "zod": ">=4.0.0"
198
+ "zod": ">=4.1.0"
201
199
  },
202
200
  "peerDependenciesMeta": {
203
201
  "zod": {
@@ -208,7 +206,6 @@
208
206
  "@std/msgpack": "npm:@jsr/std__msgpack"
209
207
  },
210
208
  "devDependencies": {
211
- "@nemigo/configs": "2.1.2",
212
- "zod": "4.1.12"
209
+ "@nemigo/configs": "2.2.3"
213
210
  }
214
211
  }