@filen/utils 0.0.6 → 0.0.8
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/checklistParser.js +1 -1
- package/dist/misc.js +50 -42
- package/dist/notes.js +4 -5
- package/dist/run.js +288 -189
- package/dist/semaphore.js +1 -1
- package/dist/time.js +2 -6
- package/dist/types/run.d.ts +10 -0
- package/package.json +1 -1
package/dist/checklistParser.js
CHANGED
package/dist/misc.js
CHANGED
|
@@ -57,48 +57,53 @@ export function chunkArray(array, chunkSize) {
|
|
|
57
57
|
}
|
|
58
58
|
return chunks;
|
|
59
59
|
}
|
|
60
|
+
const ZERO_WIDTH_AND_CONTROL_RE = /[\u200B-\u200D\uFEFF\u00AD\u0000-\u001F\u007F-\u009F]/g;
|
|
61
|
+
const NON_ASCII_RE = /[^\x00-\x7F]/g;
|
|
62
|
+
const ILLEGAL_CHARS_WINDOWS_RE = /[<>:"/\\|?*]/g;
|
|
63
|
+
const ILLEGAL_CHARS_UNIX_RE = /\//g;
|
|
64
|
+
const TRAILING_DOTS_SPACES_RE = /[. ]+$/;
|
|
65
|
+
const WHITESPACE_RE = /\s+/g;
|
|
66
|
+
const RESERVED_NAMES_WINDOWS = new Set([
|
|
67
|
+
"CON",
|
|
68
|
+
"PRN",
|
|
69
|
+
"AUX",
|
|
70
|
+
"NUL",
|
|
71
|
+
"COM1",
|
|
72
|
+
"COM2",
|
|
73
|
+
"COM3",
|
|
74
|
+
"COM4",
|
|
75
|
+
"COM5",
|
|
76
|
+
"COM6",
|
|
77
|
+
"COM7",
|
|
78
|
+
"COM8",
|
|
79
|
+
"COM9",
|
|
80
|
+
"LPT1",
|
|
81
|
+
"LPT2",
|
|
82
|
+
"LPT3",
|
|
83
|
+
"LPT4",
|
|
84
|
+
"LPT5",
|
|
85
|
+
"LPT6",
|
|
86
|
+
"LPT7",
|
|
87
|
+
"LPT8",
|
|
88
|
+
"LPT9"
|
|
89
|
+
]);
|
|
90
|
+
const textEncoder = new TextEncoder();
|
|
60
91
|
export function sanitizeFileName(filename, replacement = "_") {
|
|
61
92
|
let sanitizedFilename = filename.normalize("NFC");
|
|
62
|
-
sanitizedFilename = sanitizedFilename.replace(
|
|
63
|
-
sanitizedFilename = sanitizedFilename.replace(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
"AUX",
|
|
70
|
-
"NUL",
|
|
71
|
-
"COM1",
|
|
72
|
-
"COM2",
|
|
73
|
-
"COM3",
|
|
74
|
-
"COM4",
|
|
75
|
-
"COM5",
|
|
76
|
-
"COM6",
|
|
77
|
-
"COM7",
|
|
78
|
-
"COM8",
|
|
79
|
-
"COM9",
|
|
80
|
-
"LPT1",
|
|
81
|
-
"LPT2",
|
|
82
|
-
"LPT3",
|
|
83
|
-
"LPT4",
|
|
84
|
-
"LPT5",
|
|
85
|
-
"LPT6",
|
|
86
|
-
"LPT7",
|
|
87
|
-
"LPT8",
|
|
88
|
-
"LPT9"
|
|
89
|
-
]);
|
|
90
|
-
sanitizedFilename = sanitizedFilename.replace(illegalCharsWindows, replacement);
|
|
91
|
-
sanitizedFilename = sanitizedFilename.replace(illegalCharsUnix, replacement);
|
|
92
|
-
sanitizedFilename = sanitizedFilename.replace(/[. ]+$/, "");
|
|
93
|
-
sanitizedFilename = sanitizedFilename.replace(/\s+/g, replacement);
|
|
94
|
-
if (reservedNamesWindows.has(sanitizedFilename.toUpperCase())) {
|
|
93
|
+
sanitizedFilename = sanitizedFilename.replace(ZERO_WIDTH_AND_CONTROL_RE, "");
|
|
94
|
+
sanitizedFilename = sanitizedFilename.replace(NON_ASCII_RE, replacement);
|
|
95
|
+
sanitizedFilename = sanitizedFilename.replace(ILLEGAL_CHARS_WINDOWS_RE, replacement);
|
|
96
|
+
sanitizedFilename = sanitizedFilename.replace(ILLEGAL_CHARS_UNIX_RE, replacement);
|
|
97
|
+
sanitizedFilename = sanitizedFilename.replace(TRAILING_DOTS_SPACES_RE, "");
|
|
98
|
+
sanitizedFilename = sanitizedFilename.replace(WHITESPACE_RE, replacement);
|
|
99
|
+
if (RESERVED_NAMES_WINDOWS.has(sanitizedFilename.toUpperCase())) {
|
|
95
100
|
sanitizedFilename += replacement;
|
|
96
101
|
}
|
|
97
102
|
const maxByteLength = 255;
|
|
98
|
-
let byteLength =
|
|
103
|
+
let byteLength = textEncoder.encode(sanitizedFilename).length;
|
|
99
104
|
while (byteLength > maxByteLength && sanitizedFilename.length > 0) {
|
|
100
105
|
sanitizedFilename = sanitizedFilename.slice(0, -1);
|
|
101
|
-
byteLength =
|
|
106
|
+
byteLength = textEncoder.encode(sanitizedFilename).length;
|
|
102
107
|
}
|
|
103
108
|
if (!sanitizedFilename) {
|
|
104
109
|
return "file";
|
|
@@ -158,7 +163,7 @@ export function parseFilenPublicLink(url) {
|
|
|
158
163
|
try {
|
|
159
164
|
key = Buffer.from(key, "hex").toString("utf8");
|
|
160
165
|
}
|
|
161
|
-
catch
|
|
166
|
+
catch {
|
|
162
167
|
return null;
|
|
163
168
|
}
|
|
164
169
|
}
|
|
@@ -222,7 +227,7 @@ export function jsonBigIntReplacer(_, value) {
|
|
|
222
227
|
}
|
|
223
228
|
export function jsonBigIntReviver(_, value) {
|
|
224
229
|
if (typeof value === "string" && value.startsWith("$bigint:") && value.endsWith("n")) {
|
|
225
|
-
return BigInt(value.
|
|
230
|
+
return BigInt(value.slice(8, -1));
|
|
226
231
|
}
|
|
227
232
|
return value;
|
|
228
233
|
}
|
|
@@ -314,20 +319,20 @@ export function bpsToReadable(bps) {
|
|
|
314
319
|
if (!(bps > 0 && bps < 1099511627776)) {
|
|
315
320
|
return "0.1 B/s";
|
|
316
321
|
}
|
|
317
|
-
let i =
|
|
322
|
+
let i = -1;
|
|
318
323
|
let value = bps;
|
|
319
324
|
if (value >= 1024) {
|
|
320
325
|
value /= 1024;
|
|
321
|
-
i =
|
|
326
|
+
i = 0;
|
|
322
327
|
if (value >= 1024) {
|
|
323
328
|
value /= 1024;
|
|
324
|
-
i =
|
|
329
|
+
i = 1;
|
|
325
330
|
if (value >= 1024) {
|
|
326
331
|
value /= 1024;
|
|
327
|
-
i =
|
|
332
|
+
i = 2;
|
|
328
333
|
if (value >= 1024) {
|
|
329
334
|
value /= 1024;
|
|
330
|
-
i =
|
|
335
|
+
i = 3;
|
|
331
336
|
}
|
|
332
337
|
}
|
|
333
338
|
}
|
|
@@ -335,6 +340,9 @@ export function bpsToReadable(bps) {
|
|
|
335
340
|
if (value < 0.1) {
|
|
336
341
|
value = 0.1;
|
|
337
342
|
}
|
|
343
|
+
if (i < 0) {
|
|
344
|
+
return value.toFixed(1) + " B";
|
|
345
|
+
}
|
|
338
346
|
return value.toFixed(1) + " " + BPS_TO_READABLE_UNITS[i];
|
|
339
347
|
}
|
|
340
348
|
export const FORMAT_BYTES_SIZES = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
|
package/dist/notes.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import striptags from "striptags";
|
|
2
2
|
export function createNotePreviewFromContentText(type, content) {
|
|
3
|
-
var _a, _b, _c;
|
|
4
3
|
try {
|
|
5
4
|
if (!content || content.length === 0) {
|
|
6
5
|
return "";
|
|
7
6
|
}
|
|
8
7
|
if (type === "rich") {
|
|
9
8
|
if (content.indexOf("<p><br></p>") === -1) {
|
|
10
|
-
return striptags(
|
|
9
|
+
return striptags(content.split("\n")[0] ?? "").slice(0, 128);
|
|
11
10
|
}
|
|
12
|
-
return striptags(
|
|
11
|
+
return striptags(content.split("<p><br></p>")[0] ?? "").slice(0, 128);
|
|
13
12
|
}
|
|
14
13
|
if (type === "checklist") {
|
|
15
14
|
const ex = content
|
|
@@ -31,9 +30,9 @@ export function createNotePreviewFromContentText(type, content) {
|
|
|
31
30
|
}
|
|
32
31
|
return "";
|
|
33
32
|
}
|
|
34
|
-
return striptags(
|
|
33
|
+
return striptags(content.split("\n")[0] ?? "").slice(0, 128);
|
|
35
34
|
}
|
|
36
|
-
catch
|
|
35
|
+
catch {
|
|
37
36
|
return "";
|
|
38
37
|
}
|
|
39
38
|
}
|
package/dist/run.js
CHANGED
|
@@ -1,49 +1,37 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
var _a, _b, _c;
|
|
13
|
-
const deferredFunctions = [];
|
|
14
|
-
const defer = deferFn => {
|
|
15
|
-
deferredFunctions.push(deferFn);
|
|
1
|
+
export async function run(fn, options) {
|
|
2
|
+
const deferredFunctions = [];
|
|
3
|
+
const defer = deferFn => {
|
|
4
|
+
deferredFunctions.push(deferFn);
|
|
5
|
+
};
|
|
6
|
+
try {
|
|
7
|
+
const result = await fn(defer);
|
|
8
|
+
return {
|
|
9
|
+
success: true,
|
|
10
|
+
data: result,
|
|
11
|
+
error: null
|
|
16
12
|
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
error: null
|
|
23
|
-
};
|
|
13
|
+
}
|
|
14
|
+
catch (e) {
|
|
15
|
+
options?.onError?.(e);
|
|
16
|
+
if (options?.throw) {
|
|
17
|
+
throw e;
|
|
24
18
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
return {
|
|
20
|
+
success: false,
|
|
21
|
+
data: null,
|
|
22
|
+
error: e
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
for (let i = deferredFunctions.length - 1; i >= 0; i--) {
|
|
27
|
+
try {
|
|
28
|
+
await deferredFunctions[i]?.();
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
data: null,
|
|
33
|
-
error: e
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
finally {
|
|
37
|
-
for (let i = deferredFunctions.length - 1; i >= 0; i--) {
|
|
38
|
-
try {
|
|
39
|
-
yield ((_b = deferredFunctions[i]) === null || _b === void 0 ? void 0 : _b.call(deferredFunctions));
|
|
40
|
-
}
|
|
41
|
-
catch (e) {
|
|
42
|
-
(_c = options === null || options === void 0 ? void 0 : options.onError) === null || _c === void 0 ? void 0 : _c.call(options, e);
|
|
43
|
-
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
options?.onError?.(e);
|
|
44
32
|
}
|
|
45
33
|
}
|
|
46
|
-
}
|
|
34
|
+
}
|
|
47
35
|
}
|
|
48
36
|
export class AbortError extends Error {
|
|
49
37
|
constructor(message = "Operation aborted") {
|
|
@@ -64,109 +52,103 @@ export function abortSignalReason(signal) {
|
|
|
64
52
|
}
|
|
65
53
|
return undefined;
|
|
66
54
|
}
|
|
67
|
-
catch
|
|
55
|
+
catch {
|
|
68
56
|
return undefined;
|
|
69
57
|
}
|
|
70
58
|
}
|
|
71
|
-
export function runAbortable(fn, options) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
59
|
+
export async function runAbortable(fn, options) {
|
|
60
|
+
const deferredFunctions = [];
|
|
61
|
+
const controller = options?.controller ?? new AbortController();
|
|
62
|
+
const signal = options?.signal ?? options?.controller?.signal ?? controller.signal;
|
|
63
|
+
const defer = deferFn => {
|
|
64
|
+
deferredFunctions.push(deferFn);
|
|
65
|
+
};
|
|
66
|
+
const abortable = async (abortableFn, opts) => {
|
|
67
|
+
if (signal.aborted) {
|
|
68
|
+
throw new AbortError(abortSignalReason(signal));
|
|
69
|
+
}
|
|
70
|
+
return await new Promise((resolve, reject) => {
|
|
71
|
+
;
|
|
72
|
+
(async () => {
|
|
73
|
+
const signal = opts?.signal ?? controller.signal;
|
|
74
|
+
const abortHandler = () => {
|
|
75
|
+
reject(new AbortError(abortSignalReason(signal)));
|
|
76
|
+
};
|
|
77
|
+
signal.addEventListener("abort", abortHandler);
|
|
78
|
+
try {
|
|
79
|
+
if (signal.aborted) {
|
|
90
80
|
reject(new AbortError(abortSignalReason(signal)));
|
|
91
|
-
|
|
92
|
-
signal.addEventListener("abort", abortHandler);
|
|
93
|
-
try {
|
|
94
|
-
if (signal.aborted) {
|
|
95
|
-
reject(new AbortError(abortSignalReason(signal)));
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const result = yield abortableFn();
|
|
99
|
-
if (signal.aborted) {
|
|
100
|
-
reject(new AbortError(abortSignalReason(signal)));
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
resolve(result);
|
|
104
|
-
}
|
|
105
|
-
catch (e) {
|
|
106
|
-
reject(e);
|
|
81
|
+
return;
|
|
107
82
|
}
|
|
108
|
-
|
|
109
|
-
|
|
83
|
+
const result = await abortableFn();
|
|
84
|
+
if (signal.aborted) {
|
|
85
|
+
reject(new AbortError(abortSignalReason(signal)));
|
|
86
|
+
return;
|
|
110
87
|
}
|
|
111
|
-
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
try {
|
|
115
|
-
if (signal.aborted) {
|
|
116
|
-
throw new AbortError(abortSignalReason(signal));
|
|
117
|
-
}
|
|
118
|
-
const result = yield fn({
|
|
119
|
-
abortable,
|
|
120
|
-
defer,
|
|
121
|
-
signal,
|
|
122
|
-
controller
|
|
123
|
-
});
|
|
124
|
-
if (signal.aborted) {
|
|
125
|
-
throw new AbortError(abortSignalReason(signal));
|
|
126
|
-
}
|
|
127
|
-
return {
|
|
128
|
-
success: true,
|
|
129
|
-
data: result,
|
|
130
|
-
error: null
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
catch (e) {
|
|
134
|
-
(_e = options === null || options === void 0 ? void 0 : options.onError) === null || _e === void 0 ? void 0 : _e.call(options, e);
|
|
135
|
-
if (options === null || options === void 0 ? void 0 : options.throw) {
|
|
136
|
-
throw e;
|
|
137
|
-
}
|
|
138
|
-
return {
|
|
139
|
-
success: false,
|
|
140
|
-
data: null,
|
|
141
|
-
error: e
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
finally {
|
|
145
|
-
for (let i = deferredFunctions.length - 1; i >= 0; i--) {
|
|
146
|
-
try {
|
|
147
|
-
yield ((_f = deferredFunctions[i]) === null || _f === void 0 ? void 0 : _f.call(deferredFunctions));
|
|
88
|
+
resolve(result);
|
|
148
89
|
}
|
|
149
90
|
catch (e) {
|
|
150
|
-
(
|
|
91
|
+
reject(e);
|
|
151
92
|
}
|
|
93
|
+
finally {
|
|
94
|
+
signal.removeEventListener("abort", abortHandler);
|
|
95
|
+
}
|
|
96
|
+
})();
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
try {
|
|
100
|
+
if (signal.aborted) {
|
|
101
|
+
throw new AbortError(abortSignalReason(signal));
|
|
102
|
+
}
|
|
103
|
+
const result = await fn({
|
|
104
|
+
abortable,
|
|
105
|
+
defer,
|
|
106
|
+
signal,
|
|
107
|
+
controller
|
|
108
|
+
});
|
|
109
|
+
if (signal.aborted) {
|
|
110
|
+
throw new AbortError(abortSignalReason(signal));
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
success: true,
|
|
114
|
+
data: result,
|
|
115
|
+
error: null
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
options?.onError?.(e);
|
|
120
|
+
if (options?.throw) {
|
|
121
|
+
throw e;
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
success: false,
|
|
125
|
+
data: null,
|
|
126
|
+
error: e
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
for (let i = deferredFunctions.length - 1; i >= 0; i--) {
|
|
131
|
+
try {
|
|
132
|
+
await deferredFunctions[i]?.();
|
|
133
|
+
}
|
|
134
|
+
catch (e) {
|
|
135
|
+
options?.onError?.(e);
|
|
152
136
|
}
|
|
153
137
|
}
|
|
154
|
-
}
|
|
138
|
+
}
|
|
155
139
|
}
|
|
156
140
|
export function runEffect(fn, options) {
|
|
157
|
-
var _a;
|
|
158
141
|
const deferredFunctions = [];
|
|
159
142
|
const defer = deferFn => {
|
|
160
143
|
deferredFunctions.push(deferFn);
|
|
161
144
|
};
|
|
162
145
|
const cleanup = () => {
|
|
163
|
-
var _a, _b;
|
|
164
146
|
for (let i = deferredFunctions.length - 1; i >= 0; i--) {
|
|
165
147
|
try {
|
|
166
|
-
|
|
148
|
+
deferredFunctions[i]?.();
|
|
167
149
|
}
|
|
168
150
|
catch (e) {
|
|
169
|
-
|
|
151
|
+
options?.onError?.(e);
|
|
170
152
|
}
|
|
171
153
|
}
|
|
172
154
|
};
|
|
@@ -180,8 +162,8 @@ export function runEffect(fn, options) {
|
|
|
180
162
|
};
|
|
181
163
|
}
|
|
182
164
|
catch (e) {
|
|
183
|
-
|
|
184
|
-
if (options
|
|
165
|
+
options?.onError?.(e);
|
|
166
|
+
if (options?.throw) {
|
|
185
167
|
throw e;
|
|
186
168
|
}
|
|
187
169
|
return {
|
|
@@ -192,44 +174,44 @@ export function runEffect(fn, options) {
|
|
|
192
174
|
};
|
|
193
175
|
}
|
|
194
176
|
finally {
|
|
195
|
-
if (options
|
|
177
|
+
if (options?.automaticCleanup) {
|
|
196
178
|
cleanup();
|
|
197
179
|
}
|
|
198
180
|
}
|
|
199
181
|
}
|
|
200
|
-
export function runRetry(fn, options) {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
(_d = options === null || options === void 0 ? void 0 : options.onRetry) === null || _d === void 0 ? void 0 : _d.call(options, result.error, attempt);
|
|
223
|
-
const delay = backoff === "exponential" ? delayMs * Math.pow(2, attempt - 1) : delayMs * attempt;
|
|
224
|
-
yield new Promise(resolve => setTimeout(resolve, delay));
|
|
182
|
+
export async function runRetry(fn, options) {
|
|
183
|
+
const maxAttempts = options?.maxAttempts ?? 3;
|
|
184
|
+
const delayMs = options?.delayMs ?? 1000;
|
|
185
|
+
const backoff = options?.backoff ?? "exponential";
|
|
186
|
+
let lastError = null;
|
|
187
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
188
|
+
const result = await run(defer => fn(defer, attempt), {
|
|
189
|
+
...options,
|
|
190
|
+
throw: false
|
|
191
|
+
});
|
|
192
|
+
if (result.success) {
|
|
193
|
+
return result;
|
|
194
|
+
}
|
|
195
|
+
lastError = result.error;
|
|
196
|
+
if (attempt < maxAttempts) {
|
|
197
|
+
const shouldRetry = typeof options?.shouldRetry === "boolean"
|
|
198
|
+
? options.shouldRetry
|
|
199
|
+
: options && typeof options.shouldRetry === "function"
|
|
200
|
+
? options.shouldRetry(result.error, attempt)
|
|
201
|
+
: true;
|
|
202
|
+
if (!shouldRetry) {
|
|
203
|
+
break;
|
|
225
204
|
}
|
|
205
|
+
options?.onRetry?.(result.error, attempt);
|
|
206
|
+
const delay = backoff === "exponential" ? delayMs * Math.pow(2, attempt - 1) : delayMs * attempt;
|
|
207
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
226
208
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
success: false,
|
|
212
|
+
data: null,
|
|
213
|
+
error: lastError
|
|
214
|
+
};
|
|
233
215
|
}
|
|
234
216
|
export class TimeoutError extends Error {
|
|
235
217
|
constructor(message = "Operation timed out") {
|
|
@@ -237,54 +219,171 @@ export class TimeoutError extends Error {
|
|
|
237
219
|
this.name = "TimeoutError";
|
|
238
220
|
}
|
|
239
221
|
}
|
|
240
|
-
export function runTimeout(fn, timeoutMs, options) {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
222
|
+
export async function runTimeout(fn, timeoutMs, options) {
|
|
223
|
+
let timeoutId = null;
|
|
224
|
+
try {
|
|
225
|
+
const result = await Promise.race([
|
|
226
|
+
run(fn, options),
|
|
227
|
+
new Promise((_, reject) => {
|
|
228
|
+
timeoutId = setTimeout(() => {
|
|
229
|
+
timeoutId = null;
|
|
230
|
+
reject(new TimeoutError(`Operation timed out after ${timeoutMs}ms`));
|
|
231
|
+
}, timeoutMs);
|
|
232
|
+
})
|
|
233
|
+
]);
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
catch (e) {
|
|
237
|
+
options?.onError?.(e);
|
|
238
|
+
if (options?.throw) {
|
|
239
|
+
throw e;
|
|
256
240
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
};
|
|
241
|
+
return {
|
|
242
|
+
success: false,
|
|
243
|
+
data: null,
|
|
244
|
+
error: e
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
finally {
|
|
248
|
+
if (timeoutId !== null) {
|
|
249
|
+
clearTimeout(timeoutId);
|
|
267
250
|
}
|
|
268
|
-
}
|
|
251
|
+
}
|
|
269
252
|
}
|
|
270
253
|
export function runDebounced(fn, delayMs, options) {
|
|
271
254
|
let timeoutId = null;
|
|
255
|
+
let pendingResolve = null;
|
|
272
256
|
let pendingPromise = null;
|
|
257
|
+
let executing = false;
|
|
273
258
|
return (...args) => {
|
|
274
259
|
if (timeoutId) {
|
|
275
260
|
clearTimeout(timeoutId);
|
|
276
261
|
}
|
|
277
262
|
if (!pendingPromise) {
|
|
278
263
|
pendingPromise = new Promise(resolve => {
|
|
279
|
-
|
|
280
|
-
const result = yield run(defer => fn(defer, ...args), options);
|
|
281
|
-
resolve(result);
|
|
282
|
-
pendingPromise = null;
|
|
283
|
-
timeoutId = null;
|
|
284
|
-
}), delayMs);
|
|
264
|
+
pendingResolve = resolve;
|
|
285
265
|
});
|
|
286
266
|
}
|
|
267
|
+
timeoutId = setTimeout(async () => {
|
|
268
|
+
if (executing || !pendingResolve) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
executing = true;
|
|
272
|
+
const result = await run(defer => fn(defer, ...args), options);
|
|
273
|
+
executing = false;
|
|
274
|
+
if (pendingResolve) {
|
|
275
|
+
pendingResolve(result);
|
|
276
|
+
}
|
|
277
|
+
pendingPromise = null;
|
|
278
|
+
pendingResolve = null;
|
|
279
|
+
timeoutId = null;
|
|
280
|
+
}, delayMs);
|
|
287
281
|
return pendingPromise;
|
|
288
282
|
};
|
|
289
283
|
}
|
|
284
|
+
export function createAbortablePipeline(signal) {
|
|
285
|
+
const controller = new AbortController();
|
|
286
|
+
const controllerSignal = controller.signal;
|
|
287
|
+
if (signal) {
|
|
288
|
+
if (signal.aborted) {
|
|
289
|
+
controller.abort(signal.reason);
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
signal.addEventListener("abort", () => controller.abort(signal.reason), {
|
|
293
|
+
once: true
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
let chain = Promise.resolve();
|
|
298
|
+
let halted = false;
|
|
299
|
+
const step = (fn) => {
|
|
300
|
+
let resolve;
|
|
301
|
+
let reject;
|
|
302
|
+
const promise = new Promise((res, rej) => {
|
|
303
|
+
resolve = res;
|
|
304
|
+
reject = rej;
|
|
305
|
+
});
|
|
306
|
+
chain = chain.then(async () => {
|
|
307
|
+
if (halted || controllerSignal.aborted) {
|
|
308
|
+
reject(new AbortError(controllerSignal.aborted ? abortSignalReason(controllerSignal) : "Pipeline halted"));
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const stepDeferred = [];
|
|
312
|
+
const defer = deferFn => {
|
|
313
|
+
stepDeferred.push(deferFn);
|
|
314
|
+
};
|
|
315
|
+
const runCleanups = async () => {
|
|
316
|
+
for (let i = stepDeferred.length - 1; i >= 0; i--) {
|
|
317
|
+
try {
|
|
318
|
+
await stepDeferred[i]?.();
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
let fnSucceeded = false;
|
|
325
|
+
let fnValue;
|
|
326
|
+
let fnError;
|
|
327
|
+
const fnPromise = (async () => {
|
|
328
|
+
try {
|
|
329
|
+
fnValue = await fn(defer, controllerSignal);
|
|
330
|
+
fnSucceeded = true;
|
|
331
|
+
}
|
|
332
|
+
catch (e) {
|
|
333
|
+
fnError = e;
|
|
334
|
+
fnSucceeded = false;
|
|
335
|
+
}
|
|
336
|
+
})();
|
|
337
|
+
if (controllerSignal.aborted) {
|
|
338
|
+
await fnPromise;
|
|
339
|
+
await runCleanups();
|
|
340
|
+
if (fnSucceeded) {
|
|
341
|
+
resolve(fnValue);
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
halted = true;
|
|
345
|
+
reject(fnError);
|
|
346
|
+
}
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
try {
|
|
350
|
+
await new Promise((res, rej) => {
|
|
351
|
+
const onAbort = () => {
|
|
352
|
+
rej(new AbortError(abortSignalReason(controllerSignal)));
|
|
353
|
+
};
|
|
354
|
+
controllerSignal.addEventListener("abort", onAbort, {
|
|
355
|
+
once: true
|
|
356
|
+
});
|
|
357
|
+
fnPromise.then(() => {
|
|
358
|
+
controllerSignal.removeEventListener("abort", onAbort);
|
|
359
|
+
res();
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
catch (e) {
|
|
364
|
+
await runCleanups();
|
|
365
|
+
halted = true;
|
|
366
|
+
reject(e);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
await runCleanups();
|
|
370
|
+
if (fnSucceeded) {
|
|
371
|
+
resolve(fnValue);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
halted = true;
|
|
375
|
+
reject(fnError);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
return {
|
|
379
|
+
then: promise.then.bind(promise),
|
|
380
|
+
catch: promise.catch.bind(promise),
|
|
381
|
+
finally: promise.finally.bind(promise)
|
|
382
|
+
};
|
|
383
|
+
};
|
|
384
|
+
return {
|
|
385
|
+
step,
|
|
386
|
+
signal: controllerSignal
|
|
387
|
+
};
|
|
388
|
+
}
|
|
290
389
|
export default run;
|
package/dist/semaphore.js
CHANGED
|
@@ -40,7 +40,7 @@ export class Semaphore {
|
|
|
40
40
|
return unresolved;
|
|
41
41
|
}
|
|
42
42
|
processQueue() {
|
|
43
|
-
|
|
43
|
+
while (this.waiting.length > 0 && this.counter < this.maxCount) {
|
|
44
44
|
this.counter++;
|
|
45
45
|
const waiter = this.waiting.shift();
|
|
46
46
|
if (waiter) {
|
package/dist/time.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
export function isTimestampSameDay(timestamp1, timestamp2) {
|
|
2
2
|
const diff = timestamp1 - timestamp2;
|
|
3
|
-
if (diff
|
|
4
|
-
|
|
5
|
-
const day2 = Math.floor(timestamp2 / 86400000);
|
|
6
|
-
if (day1 === day2) {
|
|
7
|
-
return true;
|
|
8
|
-
}
|
|
3
|
+
if (diff < -86400000 || diff > 86400000) {
|
|
4
|
+
return false;
|
|
9
5
|
}
|
|
10
6
|
const date1 = new Date(timestamp1);
|
|
11
7
|
const date2 = new Date(timestamp2);
|
package/dist/types/run.d.ts
CHANGED
|
@@ -51,4 +51,14 @@ export declare class TimeoutError extends Error {
|
|
|
51
51
|
}
|
|
52
52
|
export declare function runTimeout<TResult, E = unknown>(fn: (deferFn: DeferFn) => Promise<TResult> | TResult, timeoutMs: number, options?: Options): Promise<Result<TResult, E>>;
|
|
53
53
|
export declare function runDebounced<TResult, TArgs extends unknown[]>(fn: (defer: DeferFn, ...args: TArgs) => Promise<TResult> | TResult, delayMs: number, options?: Options): (...args: TArgs) => Promise<Result<TResult, unknown>>;
|
|
54
|
+
export type StepFn<T> = (defer: DeferFn, signal: AbortSignal) => Promise<T> | T;
|
|
55
|
+
export type StepHandle<T> = {
|
|
56
|
+
then: Promise<T>["then"];
|
|
57
|
+
catch: Promise<T>["catch"];
|
|
58
|
+
finally: Promise<T>["finally"];
|
|
59
|
+
};
|
|
60
|
+
export declare function createAbortablePipeline(signal?: AbortSignal): {
|
|
61
|
+
step: <T>(fn: StepFn<T>) => StepHandle<T>;
|
|
62
|
+
signal: AbortSignal;
|
|
63
|
+
};
|
|
54
64
|
export default run;
|