@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.
- 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 +2 -1
- package/dist/async/queue.js +24 -18
- package/dist/clean.js +1 -1
- package/dist/emitter.js +2 -2
- 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 -8
- package/dist/omitter.js +4 -4
- package/dist/phymath/format.js +1 -1
- package/dist/promoter.js +5 -4
- package/dist/script.js +4 -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.d.ts +0 -1
- package/dist/xod.js +5 -4
- 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
|
@@ -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
|
|
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
|
*
|
package/dist/async/queue.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* const queue = new Queue(async (url, abort) => {
|
|
13
13
|
* try {
|
|
14
14
|
* await fetch(url);
|
|
15
|
-
* } catch
|
|
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
|
|
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,12 +6,12 @@
|
|
|
6
6
|
export class Emitter {
|
|
7
7
|
__listeners = new Map();
|
|
8
8
|
dispatch(event, data) {
|
|
9
|
-
this.__listeners.
|
|
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 - Ключ события
|
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,7 +78,7 @@ export const deepMutateArray = (source, target) => {
|
|
|
79
78
|
source.splice(target.length, source.length - target.length);
|
|
80
79
|
}
|
|
81
80
|
// Обновление элементов
|
|
82
|
-
target.
|
|
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
|
-
|
|
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
|
|
44
|
+
for (const key of structure.keys) {
|
|
45
45
|
delete obj[key];
|
|
46
|
-
}
|
|
47
|
-
structure.nested.
|
|
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
|
// Стратегия по объекту: итерируемся по ключам объекта
|
package/dist/phymath/format.js
CHANGED
package/dist/promoter.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
export class Promoter {
|
|
5
5
|
__subs = new Map();
|
|
6
6
|
notify(event) {
|
|
7
|
-
|
|
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
|
-
|
|
38
|
-
|
|
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
|
|
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 =
|
|
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/
|
|
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.d.ts
CHANGED
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,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) ^ (
|
|
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.
|
|
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
|
-
"
|
|
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.3"
|
|
213
210
|
}
|
|
214
211
|
}
|