@knime/utils 1.11.1 → 1.12.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/CHANGELOG.md +16 -0
- package/README.md +67 -14
- package/dist/globals.d.ts +8 -0
- package/dist/index.js +751 -0
- package/dist/index.js.map +1 -0
- package/dist/src/capitalize.d.ts +20 -0
- package/dist/src/capitalize.d.ts.map +1 -0
- package/dist/src/dateMinMaxCheck.d.ts +19 -0
- package/dist/src/dateMinMaxCheck.d.ts.map +1 -0
- package/dist/src/debounce.d.ts +4 -0
- package/dist/src/debounce.d.ts.map +1 -0
- package/dist/src/fileExtensions.d.ts +33 -0
- package/dist/src/fileExtensions.d.ts.map +1 -0
- package/dist/src/filters.d.ts +13 -0
- package/dist/src/filters.d.ts.map +1 -0
- package/dist/src/format.d.ts +39 -0
- package/dist/src/format.d.ts.map +1 -0
- package/dist/src/getDeepActiveElement.d.ts +3 -0
- package/dist/src/getDeepActiveElement.d.ts.map +1 -0
- package/{src/getWrappedAroundIndex.ts → dist/src/getWrappedAroundIndex.d.ts} +3 -2
- package/dist/src/getWrappedAroundIndex.d.ts.map +1 -0
- package/dist/src/hotkeys/enums.d.ts +11 -0
- package/dist/src/hotkeys/enums.d.ts.map +1 -0
- package/dist/src/hotkeys/format.d.ts +15 -0
- package/dist/src/hotkeys/format.d.ts.map +1 -0
- package/dist/src/hotkeys/index.d.ts +19 -0
- package/dist/src/hotkeys/index.d.ts.map +1 -0
- package/dist/src/hotkeys/match.d.ts +12 -0
- package/dist/src/hotkeys/match.d.ts.map +1 -0
- package/dist/src/hotkeys/modifiers.d.ts +18 -0
- package/dist/src/hotkeys/modifiers.d.ts.map +1 -0
- package/dist/src/hotkeys/types.d.ts +10 -0
- package/dist/src/hotkeys/types.d.ts.map +1 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/intervalUtils.d.ts +114 -0
- package/dist/src/intervalUtils.d.ts.map +1 -0
- package/{src/localTimezone.ts → dist/src/localTimezone.d.ts} +3 -2
- package/dist/src/localTimezone.d.ts.map +1 -0
- package/{src/numIntegerDigits.ts → dist/src/numIntegerDigits.d.ts} +3 -2
- package/dist/src/numIntegerDigits.d.ts.map +1 -0
- package/dist/src/platform/index.d.ts +2 -0
- package/dist/src/platform/index.d.ts.map +1 -0
- package/dist/src/platform/navigator.d.ts +11 -0
- package/dist/src/platform/navigator.d.ts.map +1 -0
- package/dist/src/promise/createAbortablePromise.d.ts +32 -0
- package/dist/src/promise/createAbortablePromise.d.ts.map +1 -0
- package/dist/src/promise/createUnwrappedPromise.d.ts +7 -0
- package/dist/src/promise/createUnwrappedPromise.d.ts.map +1 -0
- package/dist/src/promise/index.d.ts +4 -0
- package/dist/src/promise/index.d.ts.map +1 -0
- package/dist/src/promise/retryPromise.d.ts +16 -0
- package/dist/src/promise/retryPromise.d.ts.map +1 -0
- package/dist/src/sanitization.d.ts +8 -0
- package/dist/src/sanitization.d.ts.map +1 -0
- package/dist/src/sleep.d.ts +5 -0
- package/dist/src/sleep.d.ts.map +1 -0
- package/dist/src/truncateString.d.ts +3 -0
- package/dist/src/truncateString.d.ts.map +1 -0
- package/dist/src/updateDate.d.ts +11 -0
- package/dist/src/updateDate.d.ts.map +1 -0
- package/{src/updateTime.ts → dist/src/updateTime.d.ts} +3 -11
- package/dist/src/updateTime.d.ts.map +1 -0
- package/dist/test-utils/index.d.ts +3 -0
- package/dist/test-utils/index.d.ts.map +1 -0
- package/dist/test-utils/index.js +40 -0
- package/dist/test-utils/index.js.map +1 -0
- package/dist/test-utils/muteConsole.d.ts +8 -0
- package/dist/test-utils/muteConsole.d.ts.map +1 -0
- package/package.json +51 -33
- package/src/capitalize.ts +0 -45
- package/src/dateMinMaxCheck.ts +0 -68
- package/src/debounce.ts +0 -28
- package/src/fileExtensions.ts +0 -87
- package/src/filters.ts +0 -114
- package/src/format.ts +0 -113
- package/src/formatHotkeys.ts +0 -98
- package/src/getDeepActiveElement.ts +0 -9
- package/src/hotkeys.ts +0 -32
- package/src/index.ts +0 -76
- package/src/intervalUtils.ts +0 -434
- package/src/navigator.ts +0 -13
- package/src/promise/createAbortablePromise.ts +0 -56
- package/src/promise/createUnwrappedPromise.ts +0 -17
- package/src/promise/index.ts +0 -3
- package/src/promise/retryPromise.ts +0 -45
- package/src/sanitization.ts +0 -72
- package/src/sleep.ts +0 -6
- package/src/truncateString.ts +0 -7
- package/src/updateDate.ts +0 -23
- package/src/uploadManager/index.ts +0 -370
- package/test-utils/index.ts +0 -3
- package/test-utils/muteConsole.ts +0 -54
- /package/{src/audit → audit}/README.md +0 -0
- /package/{src/audit → audit}/bulkAudit.js +0 -0
- /package/{src/audit → audit}/cli.js +0 -0
- /package/{src/config/globals.d.ts → globals.d.ts} +0 -0
|
@@ -1,370 +0,0 @@
|
|
|
1
|
-
import { AbortError, createAbortablePromise, retryPromise } from "../promise";
|
|
2
|
-
|
|
3
|
-
// eslint-disable-next-line no-magic-numbers
|
|
4
|
-
const CHUNK_SIZE = 50 * 1024 * 1024; // 50 MB per chunk
|
|
5
|
-
|
|
6
|
-
const DEFAULT_RETRY_COUNT = 5;
|
|
7
|
-
const DEFAULT_RETRY_DELAY_MS = 50;
|
|
8
|
-
|
|
9
|
-
export type UploadStateName =
|
|
10
|
-
| "idle"
|
|
11
|
-
| "inprogress"
|
|
12
|
-
| "cancelled"
|
|
13
|
-
| "failed"
|
|
14
|
-
| "complete";
|
|
15
|
-
|
|
16
|
-
export type PartUploadResponse = {
|
|
17
|
-
partId: string;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const uploadChunkWithProgress = (params: {
|
|
21
|
-
method: string;
|
|
22
|
-
url: string;
|
|
23
|
-
chunk: Blob;
|
|
24
|
-
chunkIndex: number;
|
|
25
|
-
onProgress: (progress: number) => void;
|
|
26
|
-
abortSignal: AbortSignal;
|
|
27
|
-
}) => {
|
|
28
|
-
const { method, url, chunk, chunkIndex, onProgress, abortSignal } = params;
|
|
29
|
-
|
|
30
|
-
const OK = 200;
|
|
31
|
-
const CREATED = 201;
|
|
32
|
-
|
|
33
|
-
return new Promise<{ partId: string }>((resolve, reject) => {
|
|
34
|
-
const xhr = new XMLHttpRequest();
|
|
35
|
-
|
|
36
|
-
xhr.open(method, url, true);
|
|
37
|
-
|
|
38
|
-
abortSignal.addEventListener("abort", () => xhr.abort());
|
|
39
|
-
|
|
40
|
-
// Track the upload progress of the current chunk
|
|
41
|
-
xhr.upload.onprogress = (event) => {
|
|
42
|
-
if (event.lengthComputable) {
|
|
43
|
-
onProgress(event.loaded);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
xhr.onload = () => {
|
|
48
|
-
if (xhr.status === OK || xhr.status === CREATED) {
|
|
49
|
-
const etag = xhr.getResponseHeader("ETag");
|
|
50
|
-
|
|
51
|
-
// 1. note that some backends don't return the etag header, then we just set an empty string
|
|
52
|
-
// 2. remove possible doublequotes (") around the etag and/or weak identifier (if either is present)
|
|
53
|
-
// https://datatracker.ietf.org/doc/html/rfc7232#section-2.3
|
|
54
|
-
resolve({ partId: etag?.replace(/^(?:W\/)?"|"$/g, "") ?? "" });
|
|
55
|
-
} else {
|
|
56
|
-
consola.error("Failed or unexpected XHR response", {
|
|
57
|
-
xhrStatus: xhr.status,
|
|
58
|
-
xhrResponse: xhr.response,
|
|
59
|
-
chunkIndex,
|
|
60
|
-
});
|
|
61
|
-
reject(new Error("Failed to upload file"));
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
xhr.onerror = (event) => {
|
|
66
|
-
consola.error("Failed to upload chunk", {
|
|
67
|
-
xhrErrorEvent: event,
|
|
68
|
-
chunkIndex,
|
|
69
|
-
});
|
|
70
|
-
reject(new Error("Failed to upload file"));
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
xhr.send(chunk);
|
|
74
|
-
});
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
export type UploaderManagerConfig = {
|
|
78
|
-
/**
|
|
79
|
-
* Function to resolve the metadata for a request to upload a file part
|
|
80
|
-
* @param uploadId
|
|
81
|
-
* @param partNumber
|
|
82
|
-
* @returns
|
|
83
|
-
*/
|
|
84
|
-
resolveFilePartUploadURL: (
|
|
85
|
-
uploadId: string,
|
|
86
|
-
partNumber: number,
|
|
87
|
-
) => Promise<{ method: string; url: string }>;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Callback that gets triggered when the whole file is uploaded.
|
|
91
|
-
* @param
|
|
92
|
-
* @returns
|
|
93
|
-
*/
|
|
94
|
-
onFileUploadComplete?: (payload: {
|
|
95
|
-
/**
|
|
96
|
-
* Identifier of the upload for this file (must be unique)
|
|
97
|
-
*/
|
|
98
|
-
uploadId: string;
|
|
99
|
-
/**
|
|
100
|
-
* Ids of all the uploaded file parts
|
|
101
|
-
*/
|
|
102
|
-
filePartIds: Record<number, string>;
|
|
103
|
-
}) => void;
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Callback that gets triggered when an upload has failed.
|
|
107
|
-
* @param uploadId
|
|
108
|
-
* @param error the error that cause the failure if it exists
|
|
109
|
-
* @returns
|
|
110
|
-
*/
|
|
111
|
-
onFileUploadFailed?: (payload: { uploadId: string; error: Error }) => void;
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Callback that gets triggered when the progress of a file part upload
|
|
115
|
-
* for a specific upload id is updated
|
|
116
|
-
* @param uploadId
|
|
117
|
-
* @param progress
|
|
118
|
-
* @returns
|
|
119
|
-
*/
|
|
120
|
-
onProgress?: (uploadId: string, progress: number) => void;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
type UploadState = {
|
|
124
|
-
uploadId: string;
|
|
125
|
-
file: File;
|
|
126
|
-
completedChunkCount: number;
|
|
127
|
-
uploadedByteCount: number;
|
|
128
|
-
state: UploadStateName;
|
|
129
|
-
abortController: AbortController;
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Creates and returns an `uploadManager`, a comprehensive multi-file, multi-part upload handler.
|
|
134
|
-
*
|
|
135
|
-
* The `uploadManager` offers functionality for handling file uploads in parts and provides
|
|
136
|
-
* several built-in mechanisms to ensure the process is reliable and adaptable.
|
|
137
|
-
*
|
|
138
|
-
* Key features include:
|
|
139
|
-
*
|
|
140
|
-
* - **Chunked File Uploads**: Splits provided files into manageable chunks and initiates the upload
|
|
141
|
-
* for each part using the `resolveFilePartUploadURL` function provided in the configuration.
|
|
142
|
-
*
|
|
143
|
-
* - **Retry Mechanism**: Automatically retries failed upload attempts up to a maximum of 5 times
|
|
144
|
-
* per failed request.
|
|
145
|
-
*
|
|
146
|
-
* - **Upload Cancellation**: Allows cancellation of ongoing uploads, giving users control over the process.
|
|
147
|
-
*
|
|
148
|
-
* - **Progress Tracking**: Monitors the progress of each file part upload and triggers the `onProgress`
|
|
149
|
-
* callback to provide updates.
|
|
150
|
-
*
|
|
151
|
-
* - **Error Handling**: The returned `uploadFiles` function does not throw errors directly. Instead,
|
|
152
|
-
* it manages retries and stops any failed uploads after the retry limit is reached, marking them as failed.
|
|
153
|
-
* This ensures that the promise it returns completes gracefully without uncaught exceptions.
|
|
154
|
-
*
|
|
155
|
-
*/
|
|
156
|
-
export const createUploadManager = (config: UploaderManagerConfig) => {
|
|
157
|
-
const {
|
|
158
|
-
resolveFilePartUploadURL: getUploadFilePartUrl,
|
|
159
|
-
onFileUploadComplete,
|
|
160
|
-
onFileUploadFailed,
|
|
161
|
-
} = config;
|
|
162
|
-
const uploadStateMap = new Map<string, UploadState>();
|
|
163
|
-
|
|
164
|
-
const completedUploads = new Set<string>();
|
|
165
|
-
const cancelledUploads = new Set<string>();
|
|
166
|
-
const failedUploads = new Set<string>();
|
|
167
|
-
|
|
168
|
-
const assertState = (uploadId: string, state: UploadStateName) =>
|
|
169
|
-
uploadStateMap.has(uploadId) &&
|
|
170
|
-
uploadStateMap.get(uploadId)!.state === state;
|
|
171
|
-
|
|
172
|
-
const getUploadState = (uploadId: string) => uploadStateMap.get(uploadId);
|
|
173
|
-
const setUploadState = (uploadId: string, state: Partial<UploadState>) => {
|
|
174
|
-
uploadStateMap.set(uploadId, {
|
|
175
|
-
...uploadStateMap.get(uploadId)!,
|
|
176
|
-
...state,
|
|
177
|
-
});
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
const isFailed = (uploadId: string) => assertState(uploadId, "failed");
|
|
181
|
-
const isCancelled = (uploadId: string) => assertState(uploadId, "cancelled");
|
|
182
|
-
|
|
183
|
-
const getTotalFileParts = (file: File) => Math.ceil(file.size / CHUNK_SIZE);
|
|
184
|
-
|
|
185
|
-
const abortInFlightUpload = (uploadId: string, reason: string) => {
|
|
186
|
-
const currentState = uploadStateMap.get(uploadId);
|
|
187
|
-
|
|
188
|
-
if (!currentState) {
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
currentState.abortController.abort(
|
|
193
|
-
new AbortError(
|
|
194
|
-
`Upload (${currentState.uploadId}) for file "${currentState.file.name}" aborted. Reason: "${reason}"`,
|
|
195
|
-
),
|
|
196
|
-
);
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
const cancel = (uploadId: string) => {
|
|
200
|
-
if (!uploadStateMap.has(uploadId)) {
|
|
201
|
-
consola.error("cancel:: Invalid upload id");
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
setUploadState(uploadId, { state: "cancelled" });
|
|
206
|
-
|
|
207
|
-
abortInFlightUpload(uploadId, "upload cancelled");
|
|
208
|
-
cancelledUploads.add(uploadId);
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
const setFailed = (uploadId: string, error: Error) => {
|
|
212
|
-
if (!uploadStateMap.has(uploadId)) {
|
|
213
|
-
consola.error("failed:: Invalid upload id");
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
setUploadState(uploadId, { state: "failed" });
|
|
218
|
-
onFileUploadFailed?.({ uploadId, error });
|
|
219
|
-
failedUploads.add(uploadId);
|
|
220
|
-
|
|
221
|
-
if (completedUploads.has(uploadId)) {
|
|
222
|
-
completedUploads.delete(uploadId);
|
|
223
|
-
}
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
const uploadFileFromChunkIndex = async (
|
|
227
|
-
uploadId: string,
|
|
228
|
-
file: File,
|
|
229
|
-
initialChunkIndex = 0,
|
|
230
|
-
) => {
|
|
231
|
-
const totalChunks = getTotalFileParts(file);
|
|
232
|
-
const totalBytes = file.size;
|
|
233
|
-
const completedPartIds: Record<number, string> = {};
|
|
234
|
-
|
|
235
|
-
const { abortController, runAbortablePromise } = createAbortablePromise();
|
|
236
|
-
|
|
237
|
-
uploadStateMap.set(uploadId, {
|
|
238
|
-
uploadId,
|
|
239
|
-
file,
|
|
240
|
-
state: "inprogress",
|
|
241
|
-
uploadedByteCount: uploadStateMap.get(uploadId)?.uploadedByteCount ?? 0,
|
|
242
|
-
completedChunkCount:
|
|
243
|
-
uploadStateMap.get(uploadId)?.completedChunkCount ?? 0,
|
|
244
|
-
abortController,
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
let chunkIndex = initialChunkIndex;
|
|
248
|
-
let uploadedBytes = uploadStateMap.get(uploadId)?.uploadedByteCount;
|
|
249
|
-
|
|
250
|
-
while (chunkIndex < totalChunks) {
|
|
251
|
-
if (isCancelled(uploadId) || isFailed(uploadId)) {
|
|
252
|
-
break;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const start = chunkIndex * CHUNK_SIZE;
|
|
256
|
-
const end = Math.min(start + CHUNK_SIZE, file.size);
|
|
257
|
-
|
|
258
|
-
const chunk = file.slice(start, end);
|
|
259
|
-
|
|
260
|
-
try {
|
|
261
|
-
const { method, url } = await retryPromise({
|
|
262
|
-
fn: () => getUploadFilePartUrl(uploadId, chunkIndex + 1),
|
|
263
|
-
retryCount: DEFAULT_RETRY_COUNT,
|
|
264
|
-
retryDelayMS: DEFAULT_RETRY_DELAY_MS,
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
consola.trace("File part upload url resolved", { method, url });
|
|
268
|
-
|
|
269
|
-
const onChunkUploadProgress = (uploadedChunkBytes: number) => {
|
|
270
|
-
uploadedBytes = uploadedChunkBytes + start;
|
|
271
|
-
setUploadState(uploadId, { uploadedByteCount: uploadedBytes });
|
|
272
|
-
|
|
273
|
-
const progress = Math.round((uploadedBytes / totalBytes) * 100);
|
|
274
|
-
|
|
275
|
-
config.onProgress?.(uploadId, progress);
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
const filePartResponse = await runAbortablePromise(() =>
|
|
279
|
-
retryPromise({
|
|
280
|
-
fn: () =>
|
|
281
|
-
uploadChunkWithProgress({
|
|
282
|
-
method,
|
|
283
|
-
url,
|
|
284
|
-
chunk,
|
|
285
|
-
chunkIndex,
|
|
286
|
-
onProgress: onChunkUploadProgress,
|
|
287
|
-
abortSignal: abortController.signal,
|
|
288
|
-
}),
|
|
289
|
-
retryCount: DEFAULT_RETRY_COUNT,
|
|
290
|
-
retryDelayMS: DEFAULT_RETRY_DELAY_MS,
|
|
291
|
-
}),
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
consola.trace(
|
|
295
|
-
`${file.name}: Chunk ${chunkIndex + 1} of ${totalChunks} uploaded successfully`,
|
|
296
|
-
);
|
|
297
|
-
|
|
298
|
-
completedPartIds[chunkIndex + 1] = filePartResponse.partId;
|
|
299
|
-
|
|
300
|
-
setUploadState(uploadId, {
|
|
301
|
-
completedChunkCount:
|
|
302
|
-
uploadStateMap.get(uploadId)!.completedChunkCount + 1,
|
|
303
|
-
});
|
|
304
|
-
} catch (error) {
|
|
305
|
-
if (error instanceof AbortError) {
|
|
306
|
-
consola.info("Aborted::", error);
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
setFailed(
|
|
311
|
-
uploadId,
|
|
312
|
-
error instanceof Error ? error : new Error(error as string),
|
|
313
|
-
);
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
chunkIndex++;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
if (isCancelled(uploadId) || isFailed(uploadId)) {
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
setUploadState(uploadId, {
|
|
325
|
-
completedChunkCount: totalChunks,
|
|
326
|
-
state: "complete",
|
|
327
|
-
});
|
|
328
|
-
completedUploads.add(uploadId);
|
|
329
|
-
onFileUploadComplete?.({ uploadId, filePartIds: completedPartIds });
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
const uploadFiles = (files: Array<{ uploadId: string; file: File }>) => {
|
|
333
|
-
const result: Array<Promise<unknown>> = [];
|
|
334
|
-
|
|
335
|
-
for (const { uploadId, file } of files) {
|
|
336
|
-
result.push(uploadFileFromChunkIndex(uploadId, file));
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
return Promise.allSettled(result).then(() => {
|
|
340
|
-
// state cleanup
|
|
341
|
-
const completed = [...completedUploads.values()];
|
|
342
|
-
const cancelled = [...cancelledUploads.values()];
|
|
343
|
-
const failed = [...failedUploads.values()];
|
|
344
|
-
|
|
345
|
-
[...completed, ...cancelled, ...failed].forEach((uploadId) =>
|
|
346
|
-
uploadStateMap.delete(uploadId),
|
|
347
|
-
);
|
|
348
|
-
|
|
349
|
-
completedUploads.clear();
|
|
350
|
-
cancelledUploads.clear();
|
|
351
|
-
failedUploads.clear();
|
|
352
|
-
|
|
353
|
-
return {
|
|
354
|
-
completed,
|
|
355
|
-
cancelled,
|
|
356
|
-
failed,
|
|
357
|
-
};
|
|
358
|
-
});
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
return {
|
|
362
|
-
uploadFiles,
|
|
363
|
-
|
|
364
|
-
getUploadState,
|
|
365
|
-
isFailed,
|
|
366
|
-
isCancelled,
|
|
367
|
-
cancel,
|
|
368
|
-
setFailed,
|
|
369
|
-
};
|
|
370
|
-
};
|
package/test-utils/index.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
type ConsoleMethod = "log" | "warn" | "error" | "info";
|
|
4
|
-
const methods: ConsoleMethod[] = ["log", "warn", "error", "info"];
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Helper function to run code suppressing all console output
|
|
8
|
-
* @param f The function to run. Can be async.
|
|
9
|
-
* @returns The original function's return value
|
|
10
|
-
*/
|
|
11
|
-
export default (f: (...args: never[]) => Promise<unknown>) => {
|
|
12
|
-
const originals = methods.map((method) => console[method]);
|
|
13
|
-
methods.forEach((method) => {
|
|
14
|
-
console[method] = () => {};
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
let originalConsola: typeof consola;
|
|
18
|
-
// @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.
|
|
19
|
-
if (global.consola) {
|
|
20
|
-
// @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.
|
|
21
|
-
originalConsola = global.consola;
|
|
22
|
-
// @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.
|
|
23
|
-
global.consola = consola.create({
|
|
24
|
-
level: -1,
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const restoreOriginals = () => {
|
|
29
|
-
methods.forEach((method, i) => {
|
|
30
|
-
console[method] = originals[i];
|
|
31
|
-
});
|
|
32
|
-
if (originalConsola) {
|
|
33
|
-
// @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.
|
|
34
|
-
global.consola = originalConsola;
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
if (f.constructor.name === "AsyncFunction") {
|
|
39
|
-
// async
|
|
40
|
-
const result = f();
|
|
41
|
-
if (result instanceof Promise) {
|
|
42
|
-
return result.finally(restoreOriginals);
|
|
43
|
-
}
|
|
44
|
-
} else {
|
|
45
|
-
// sync
|
|
46
|
-
try {
|
|
47
|
-
return f();
|
|
48
|
-
} catch (e) {
|
|
49
|
-
throw e;
|
|
50
|
-
} finally {
|
|
51
|
-
restoreOriginals();
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|