@nemigo/helpers 2.0.1 → 2.2.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.
@@ -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);
@@ -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
  *
@@ -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,6 +6,8 @@
6
6
  export class Emitter {
7
7
  __listeners = new Map();
8
8
  dispatch(event, data) {
9
+ // oxlint-disable-next-line unicorn/no-array-for-each
10
+ // eslint-disable-next-line unicorn/no-array-for-each
9
11
  this.__listeners.forEach((handler, key) => {
10
12
  if (event === handler.event)
11
13
  handler.callback(data);
@@ -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,6 +78,8 @@ export const deepMutateArray = (source, target) => {
79
78
  source.splice(target.length, source.length - target.length);
80
79
  }
81
80
  // Обновление элементов
81
+ // oxlint-disable-next-line unicorn/no-array-for-each
82
+ // eslint-disable-next-line unicorn/no-array-for-each
82
83
  target.forEach((targetItem, index) => {
83
84
  const sourceItem = source[index];
84
85
  if (Array.isArray(targetItem)) {
@@ -117,8 +118,11 @@ export const inject = (self, key, func, dynamic = false) => {
117
118
  const original = self[key];
118
119
  if (dynamic) {
119
120
  // динамический this
121
+ // oxlint-disable-next-line eslint/func-names
122
+ // eslint-disable-next-line func-names
120
123
  self[key] = function (...args) {
121
- const method = (...args) => Reflect.apply(original, this, args);
124
+ // eslint-disable-next-line unicorn/consistent-function-scoping
125
+ const method = (...method_args) => Reflect.apply(original, this, method_args);
122
126
  return func({ self: this, method, args });
123
127
  };
124
128
  }
package/dist/omitter.js CHANGED
@@ -41,9 +41,13 @@ export class Omitter {
41
41
  const keys = Object.keys(obj);
42
42
  if (schema < keys.length) {
43
43
  // Стратегия по схеме: итерируемся по ключам схемы
44
+ // oxlint-disable-next-line unicorn/no-array-for-each
45
+ // eslint-disable-next-line unicorn/no-array-for-each
44
46
  structure.keys.forEach((key) => {
45
47
  delete obj[key];
46
48
  });
49
+ // oxlint-disable-next-line unicorn/no-array-for-each
50
+ // eslint-disable-next-line unicorn/no-array-for-each
47
51
  structure.nested.forEach((omitter, key) => {
48
52
  const nested = obj[key];
49
53
  if (nested && typeof nested === "object")
@@ -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,6 +4,8 @@
4
4
  export class Promoter {
5
5
  __subs = new Map();
6
6
  notify(event) {
7
+ // oxlint-disable-next-line unicorn/no-array-for-each
8
+ // eslint-disable-next-line unicorn/no-array-for-each
7
9
  this.__subs.forEach(({ callback, once }, key) => {
8
10
  callback(event);
9
11
  if (once)
@@ -34,7 +36,8 @@ export class Promoter {
34
36
  */
35
37
  unsubscribe(key) {
36
38
  if (key === undefined)
37
- return this.__subs.clear();
38
- this.__subs.delete(key);
39
+ this.__subs.clear();
40
+ else
41
+ this.__subs.delete(key);
39
42
  }
40
43
  }
package/dist/script.js CHANGED
@@ -18,7 +18,7 @@ import { MS_IN_MINUTE } from "./datetime/delta.js";
18
18
  function getProcessFlag(cmd, name, strict = true) {
19
19
  const argv = cmd.slice(2);
20
20
  const index = argv.indexOf(name);
21
- if (index > -1) {
21
+ if (index !== -1) {
22
22
  const value = argv[index + 1];
23
23
  if (value)
24
24
  return value;
@@ -59,7 +59,9 @@ export { getProcessFlag };
59
59
  * await execute("/path", "long-running-command", { timeout: null | 0 });
60
60
  * ```
61
61
  */
62
- export const execute = async (path, command, { logger = {}, timeout = 5 * MS_IN_MINUTE } = {}) => new Promise((resolve, reject) => {
62
+ export const execute = (path, command, { logger = {}, timeout = 5 * MS_IN_MINUTE } = {}) => new Promise((resolve, reject) => {
63
+ // oxlint-disable-next-line no-console
64
+ // eslint-disable-next-line no-console
63
65
  if (logger.before)
64
66
  console.log(logger.before(path));
65
67
  let process = null;
@@ -73,6 +75,8 @@ export const execute = async (path, command, { logger = {}, timeout = 5 * MS_IN_
73
75
  if (timeout) {
74
76
  timer = setTimeout(() => {
75
77
  process?.kill("SIGTERM");
78
+ // oxlint-disable-next-line no-console
79
+ // eslint-disable-next-line no-console
76
80
  if (logger.ontimeout)
77
81
  console.error(logger.ontimeout());
78
82
  reject(new Error("TIMEOUT"));
@@ -80,11 +84,17 @@ export const execute = async (path, command, { logger = {}, timeout = 5 * MS_IN_
80
84
  }
81
85
  process = exec(command, { cwd: path }, (error, stdout, stderr) => {
82
86
  cleanup();
87
+ // oxlint-disable-next-line no-console
88
+ // eslint-disable-next-line no-console
83
89
  if (stderr)
84
90
  console.warn(stderr);
91
+ // oxlint-disable-next-line no-console
92
+ // eslint-disable-next-line no-console
85
93
  if (stdout)
86
94
  console.log(stdout);
87
95
  if (error) {
96
+ // oxlint-disable-next-line no-console
97
+ // eslint-disable-next-line no-console
88
98
  if (logger.onerror)
89
99
  console.error(logger.onerror(error));
90
100
  reject(error);
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.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,5 @@ export const xod = {
237
239
  lwhStrict: lwhStrictSchema,
238
240
  lwhStrictOptional: lwhStrictSchemaOptional,
239
241
  };
242
+ // oxlint-disable-next-line import/no-default-export
240
243
  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.1",
3
+ "version": "2.2.0",
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.1",
212
- "zod": "4.1.12"
209
+ "@nemigo/configs": "2.2.0"
213
210
  }
214
211
  }