@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.
- package/dist/aggregator.js +4 -5
- package/dist/async/context.js +1 -0
- package/dist/async/future.d.ts +1 -1
- package/dist/async/future.js +8 -3
- package/dist/async/index.js +11 -4
- package/dist/async/loader.js +9 -3
- package/dist/async/queue.d.ts +1 -0
- package/dist/async/queue.js +23 -17
- package/dist/clean.js +1 -1
- package/dist/emitter.js +2 -0
- package/dist/explorer.d.ts +1 -1
- package/dist/explorer.js +3 -3
- package/dist/files.js +4 -2
- package/dist/fish.js +10 -12
- package/dist/html/cookie.js +3 -1
- package/dist/html/events.js +10 -6
- package/dist/html/index.js +5 -7
- package/dist/index.d.ts +1 -1
- package/dist/jiff/apply.d.ts +1 -1
- package/dist/jiff/apply.js +6 -8
- package/dist/jiff/extract.d.ts +1 -1
- package/dist/jiff/extract.js +9 -9
- package/dist/lens.d.ts +0 -1
- package/dist/lens.js +0 -3
- package/dist/mutate.js +10 -6
- package/dist/omitter.js +4 -0
- package/dist/phymath/format.js +1 -1
- package/dist/promoter.js +5 -2
- package/dist/script.js +12 -2
- package/dist/string.js +2 -2
- package/dist/url/params.d.ts +2 -2
- package/dist/url/params.js +5 -7
- package/dist/url/slug.js +6 -8
- package/dist/veil.js +2 -2
- package/dist/xod.js +6 -3
- package/dist/zipper.js +6 -3
- package/package.json +7 -10
package/dist/aggregator.js
CHANGED
|
@@ -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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
}
|
package/dist/async/context.js
CHANGED
|
@@ -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;
|
package/dist/async/future.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ export declare class Future {
|
|
|
45
45
|
* @param [options.key=Symbol()] - Ключ фьючерса
|
|
46
46
|
* @param [options.delay=this.delay] - Задержка в миллисекундах
|
|
47
47
|
*
|
|
48
|
-
* @
|
|
48
|
+
* @returns Функция для очистки
|
|
49
49
|
*
|
|
50
50
|
* @remarks Ошибки полностью игнорируются
|
|
51
51
|
*/
|
package/dist/async/future.js
CHANGED
|
@@ -12,7 +12,10 @@ export class Future {
|
|
|
12
12
|
}
|
|
13
13
|
__entries = new Map();
|
|
14
14
|
__delete(key, entry) {
|
|
15
|
-
entry.type === "timer"
|
|
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
|
-
* @
|
|
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 () =>
|
|
72
|
+
return () => {
|
|
73
|
+
this.__delete(key, entry);
|
|
74
|
+
};
|
|
70
75
|
}
|
|
71
76
|
}
|
package/dist/async/index.js
CHANGED
|
@@ -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) =>
|
|
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 (
|
|
100
|
+
catch (error) {
|
|
94
101
|
if (typeof fallback === "function") {
|
|
95
|
-
// @ts-expect-error
|
|
96
|
-
return fallback(
|
|
102
|
+
// @ts-expect-error : тут не типизировать
|
|
103
|
+
return fallback(error);
|
|
97
104
|
}
|
|
98
105
|
return fallback;
|
|
99
106
|
}
|
package/dist/async/loader.js
CHANGED
|
@@ -24,9 +24,15 @@ export class Loader {
|
|
|
24
24
|
this.reset();
|
|
25
25
|
}
|
|
26
26
|
__check(version) {
|
|
27
|
-
if (this.__heap.length === 0)
|
|
28
|
-
|
|
29
|
-
|
|
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);
|
package/dist/async/queue.d.ts
CHANGED
package/dist/async/queue.js
CHANGED
|
@@ -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
|
|
77
|
+
this.__timeout = setTimeout(() => void this.__start(), delay);
|
|
72
78
|
}
|
|
73
79
|
else {
|
|
74
|
-
void
|
|
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
|
|
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);
|
package/dist/explorer.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export interface RemoveOptions {
|
|
|
37
37
|
*
|
|
38
38
|
* @throws {Error} Если это была не пустая директория при {@link RemoveOptions.empty} или не соответствует ожидаемому типу {@link RemoveOptions.expected}
|
|
39
39
|
*/
|
|
40
|
-
export declare
|
|
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
|
|
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, "
|
|
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.
|
|
9
|
-
|
|
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((
|
|
26
|
+
promise = func(...args).catch((error) => {
|
|
27
27
|
promise = undefined;
|
|
28
|
-
throw
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
};
|
package/dist/html/cookie.js
CHANGED
|
@@ -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) =>
|
|
36
|
+
export const deleteDocumentCookie = (name, Path) => {
|
|
37
|
+
setDocumentCookie(name, "", { Path, MaxAge: 0 });
|
|
38
|
+
};
|
package/dist/html/events.js
CHANGED
|
@@ -2,7 +2,10 @@ import { useConditionGuard } from "../index.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Предотвращает стандартное поведение события и останавливает его всплытие
|
|
4
4
|
*/
|
|
5
|
-
export const preventStop = (e) =>
|
|
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
|
-
|
|
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 () =>
|
|
126
|
+
return () => {
|
|
127
|
+
target.removeEventListener(event, listener);
|
|
128
|
+
};
|
|
125
129
|
};
|
|
126
130
|
/**
|
|
127
131
|
* Создаёт обработчик события `scrollTo`
|
package/dist/html/index.js
CHANGED
|
@@ -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]
|
|
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
|
-
|
|
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
|
*
|
package/dist/jiff/apply.d.ts
CHANGED
|
@@ -90,4 +90,4 @@ export interface JiffApplyProps<CustomPatch extends NeverPatch = never> {
|
|
|
90
90
|
*
|
|
91
91
|
* @see https://jsonpatch.com/ Документация стандарта
|
|
92
92
|
*/
|
|
93
|
-
export declare
|
|
93
|
+
export declare const jiffApply: <CustomPatch extends NeverPatch = never>(obj: object, jiff: (CustomPatch | JiffPatch)[], props?: JiffApplyProps<CustomPatch>) => void;
|
package/dist/jiff/apply.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* @see https://jsonpatch.com/ Документация стандарта
|
|
13
13
|
*/
|
|
14
|
-
export
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
+
};
|
package/dist/jiff/extract.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ import type { JiffPatch } from "./types.js";
|
|
|
4
4
|
*
|
|
5
5
|
* @see https://jsonpatch.com/ Документация стандарта
|
|
6
6
|
*/
|
|
7
|
-
export declare
|
|
7
|
+
export declare const jiffExtract: (source: object, target: object) => JiffPatch[];
|
package/dist/jiff/extract.js
CHANGED
|
@@ -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)
|
|
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
|
-
|
|
42
|
+
for (const [key, targetValue] of Object.entries(targetObj)) {
|
|
43
43
|
const path = [...currentPath, key];
|
|
44
44
|
const sourceValue = sourceObj[key];
|
|
45
|
-
if (
|
|
46
|
-
|
|
45
|
+
if (key in sourceObj) {
|
|
46
|
+
compareValues(sourceValue, targetValue, path, diffs);
|
|
47
47
|
}
|
|
48
48
|
else {
|
|
49
|
-
|
|
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
|
|
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
package/dist/lens.js
CHANGED
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)
|
|
23
|
+
for (const key of Object.keys(source))
|
|
24
24
|
if (!(key in target))
|
|
25
25
|
delete source[key];
|
|
26
|
-
});
|
|
27
26
|
// Обновление свойств
|
|
28
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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")
|
package/dist/phymath/format.js
CHANGED
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
|
-
|
|
38
|
-
|
|
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
|
|
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 =
|
|
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/
|
|
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+/
|
|
35
|
+
export const oSpaceRegExp = /\s+/gu;
|
|
36
36
|
/**
|
|
37
37
|
* Нормализует пробелы в строке: заменяет множественные пробелы на один и удаляет пробелы в начале и конце
|
|
38
38
|
*
|
package/dist/url/params.d.ts
CHANGED
|
@@ -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
|
|
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
|
*/
|
package/dist/url/params.js
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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.
|
|
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").
|
|
86
|
-
const nCode = normalized.
|
|
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
|
-
|
|
93
|
-
|
|
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.
|
|
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.
|
|
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
|
|
36
|
+
return;
|
|
35
37
|
const flat = value.trim().toLowerCase();
|
|
36
38
|
if (flat === "undefined" || flat === "null")
|
|
37
|
-
return
|
|
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) ^ (
|
|
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.
|
|
35
|
-
|
|
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
|
|
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
|
-
"
|
|
15
|
-
"
|
|
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.
|
|
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.
|
|
212
|
-
"zod": "4.1.12"
|
|
209
|
+
"@nemigo/configs": "2.2.0"
|
|
213
210
|
}
|
|
214
211
|
}
|