@nomicfoundation/hardhat-utils 3.0.0-next.3 → 3.0.0-next.30
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/README.md +3 -3
- package/dist/src/bigint.d.ts.map +1 -1
- package/dist/src/bigint.js +1 -0
- package/dist/src/bigint.js.map +1 -1
- package/dist/src/crypto.d.ts +7 -0
- package/dist/src/crypto.d.ts.map +1 -1
- package/dist/src/crypto.js +10 -0
- package/dist/src/crypto.js.map +1 -1
- package/dist/src/debug.d.ts.map +1 -1
- package/dist/src/error.d.ts +19 -2
- package/dist/src/error.d.ts.map +1 -1
- package/dist/src/error.js +22 -2
- package/dist/src/error.js.map +1 -1
- package/dist/src/fs.d.ts +12 -3
- package/dist/src/fs.d.ts.map +1 -1
- package/dist/src/fs.js +60 -34
- package/dist/src/fs.js.map +1 -1
- package/dist/src/internal/bytecode.d.ts +1 -1
- package/dist/src/internal/bytecode.d.ts.map +1 -1
- package/dist/src/package.d.ts +12 -0
- package/dist/src/package.d.ts.map +1 -1
- package/dist/src/package.js.map +1 -1
- package/dist/src/path.d.ts +2 -2
- package/dist/src/path.d.ts.map +1 -1
- package/dist/src/path.js +12 -3
- package/dist/src/path.js.map +1 -1
- package/dist/src/request.d.ts +16 -6
- package/dist/src/request.d.ts.map +1 -1
- package/dist/src/request.js +12 -4
- package/dist/src/request.js.map +1 -1
- package/dist/src/stream.d.ts +1 -1
- package/dist/src/stream.js +1 -1
- package/dist/src/subprocess.js +1 -1
- package/dist/src/subprocess.js.map +1 -1
- package/dist/src/synchronization.js +4 -4
- package/dist/src/synchronization.js.map +1 -1
- package/package.json +5 -13
- package/src/bigint.ts +1 -0
- package/src/crypto.ts +11 -0
- package/src/error.ts +26 -2
- package/src/fs.ts +76 -40
- package/src/internal/bytecode.ts +1 -1
- package/src/package.ts +26 -0
- package/src/path.ts +16 -6
- package/src/request.ts +24 -8
- package/src/stream.ts +1 -1
- package/src/subprocess.ts +1 -1
- package/src/synchronization.ts +4 -4
package/src/fs.ts
CHANGED
|
@@ -2,13 +2,14 @@ import type { JsonTypes, ParsedElementInfo } from "@streamparser/json-node";
|
|
|
2
2
|
import type { FileHandle } from "node:fs/promises";
|
|
3
3
|
|
|
4
4
|
import fsPromises from "node:fs/promises";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
5
6
|
import path from "node:path";
|
|
6
7
|
import { pipeline } from "node:stream/promises";
|
|
7
8
|
|
|
8
9
|
import { JSONParser } from "@streamparser/json-node";
|
|
9
10
|
import { JsonStreamStringify } from "json-stream-stringify";
|
|
10
11
|
|
|
11
|
-
import { ensureError } from "./error.js";
|
|
12
|
+
import { ensureError, ensureNodeErrnoExceptionError } from "./error.js";
|
|
12
13
|
import {
|
|
13
14
|
FileNotFoundError,
|
|
14
15
|
FileSystemAccessError,
|
|
@@ -31,7 +32,7 @@ export async function getRealPath(absolutePath: string): Promise<string> {
|
|
|
31
32
|
try {
|
|
32
33
|
return await fsPromises.realpath(path.normalize(absolutePath));
|
|
33
34
|
} catch (e) {
|
|
34
|
-
|
|
35
|
+
ensureNodeErrnoExceptionError(e);
|
|
35
36
|
if (e.code === "ENOENT") {
|
|
36
37
|
throw new FileNotFoundError(absolutePath, e);
|
|
37
38
|
}
|
|
@@ -46,6 +47,7 @@ export async function getRealPath(absolutePath: string): Promise<string> {
|
|
|
46
47
|
*
|
|
47
48
|
* @param dirFrom The absolute path of the directory to start the search from.
|
|
48
49
|
* @param matches A function to filter files (not directories).
|
|
50
|
+
* @param directoryFilter A function to filter which directories to recurse into
|
|
49
51
|
* @returns An array of absolute paths. Each file has its true case, except
|
|
50
52
|
* for the initial dirFrom part, which preserves the given casing.
|
|
51
53
|
* No order is guaranteed. If dirFrom doesn't exist `[]` is returned.
|
|
@@ -54,7 +56,8 @@ export async function getRealPath(absolutePath: string): Promise<string> {
|
|
|
54
56
|
*/
|
|
55
57
|
export async function getAllFilesMatching(
|
|
56
58
|
dirFrom: string,
|
|
57
|
-
matches?: (absolutePathToFile: string) => boolean,
|
|
59
|
+
matches?: (absolutePathToFile: string) => Promise<boolean> | boolean,
|
|
60
|
+
directoryFilter?: (absolutePathToDir: string) => Promise<boolean> | boolean,
|
|
58
61
|
): Promise<string[]> {
|
|
59
62
|
const dirContent = await readdirOrEmpty(dirFrom);
|
|
60
63
|
|
|
@@ -62,8 +65,19 @@ export async function getAllFilesMatching(
|
|
|
62
65
|
dirContent.map(async (file) => {
|
|
63
66
|
const absolutePathToFile = path.join(dirFrom, file);
|
|
64
67
|
if (await isDirectory(absolutePathToFile)) {
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
if (
|
|
69
|
+
directoryFilter === undefined ||
|
|
70
|
+
(await directoryFilter(absolutePathToFile))
|
|
71
|
+
) {
|
|
72
|
+
return getAllFilesMatching(
|
|
73
|
+
absolutePathToFile,
|
|
74
|
+
matches,
|
|
75
|
+
directoryFilter,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return [];
|
|
80
|
+
} else if (matches === undefined || (await matches(absolutePathToFile))) {
|
|
67
81
|
return absolutePathToFile;
|
|
68
82
|
} else {
|
|
69
83
|
return [];
|
|
@@ -79,7 +93,7 @@ export async function getAllFilesMatching(
|
|
|
79
93
|
* satisfy the specified condition, returning their absolute paths. Once a
|
|
80
94
|
* directory is found, its subdirectories are not searched.
|
|
81
95
|
*
|
|
82
|
-
* Note: dirFrom is never returned, nor `matches`
|
|
96
|
+
* Note: dirFrom is never returned, nor is `matches` called on it.
|
|
83
97
|
*
|
|
84
98
|
* @param dirFrom The absolute path of the directory to start the search from.
|
|
85
99
|
* @param matches A function to filter directories (not files).
|
|
@@ -91,7 +105,7 @@ export async function getAllFilesMatching(
|
|
|
91
105
|
*/
|
|
92
106
|
export async function getAllDirectoriesMatching(
|
|
93
107
|
dirFrom: string,
|
|
94
|
-
matches?: (absolutePathToDir: string) => boolean,
|
|
108
|
+
matches?: (absolutePathToDir: string) => Promise<boolean> | boolean,
|
|
95
109
|
): Promise<string[]> {
|
|
96
110
|
const dirContent = await readdirOrEmpty(dirFrom);
|
|
97
111
|
|
|
@@ -102,7 +116,7 @@ export async function getAllDirectoriesMatching(
|
|
|
102
116
|
return [];
|
|
103
117
|
}
|
|
104
118
|
|
|
105
|
-
if (matches === undefined || matches(absolutePathToFile)) {
|
|
119
|
+
if (matches === undefined || (await matches(absolutePathToFile))) {
|
|
106
120
|
return absolutePathToFile;
|
|
107
121
|
}
|
|
108
122
|
|
|
@@ -165,7 +179,7 @@ export async function isDirectory(absolutePath: string): Promise<boolean> {
|
|
|
165
179
|
try {
|
|
166
180
|
return (await fsPromises.lstat(absolutePath)).isDirectory();
|
|
167
181
|
} catch (e) {
|
|
168
|
-
|
|
182
|
+
ensureNodeErrnoExceptionError(e);
|
|
169
183
|
if (e.code === "ENOENT") {
|
|
170
184
|
throw new FileNotFoundError(absolutePath, e);
|
|
171
185
|
}
|
|
@@ -189,7 +203,7 @@ export async function readJsonFile<T>(absolutePathToFile: string): Promise<T> {
|
|
|
189
203
|
try {
|
|
190
204
|
return JSON.parse(content.toString());
|
|
191
205
|
} catch (e) {
|
|
192
|
-
ensureError
|
|
206
|
+
ensureError(e);
|
|
193
207
|
throw new InvalidFileFormatError(absolutePathToFile, e);
|
|
194
208
|
}
|
|
195
209
|
}
|
|
@@ -241,19 +255,22 @@ export async function readJsonFileAsStream<T>(
|
|
|
241
255
|
|
|
242
256
|
return result;
|
|
243
257
|
} catch (e) {
|
|
244
|
-
ensureError
|
|
258
|
+
ensureError(e);
|
|
245
259
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
260
|
+
// If the code is defined, we assume the error to be related to the file system
|
|
261
|
+
if ("code" in e) {
|
|
262
|
+
if (e.code === "ENOENT") {
|
|
263
|
+
throw new FileNotFoundError(absolutePathToFile, e);
|
|
264
|
+
}
|
|
249
265
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
266
|
+
if (e.code === "EISDIR") {
|
|
267
|
+
throw new IsDirectoryError(absolutePathToFile, e);
|
|
268
|
+
}
|
|
253
269
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
270
|
+
// If the code is defined, we assume the error to be related to the file system
|
|
271
|
+
if (e.code !== undefined) {
|
|
272
|
+
throw new FileSystemAccessError(absolutePathToFile, e);
|
|
273
|
+
}
|
|
257
274
|
}
|
|
258
275
|
|
|
259
276
|
// Otherwise, we assume the error to be related to the file formatting
|
|
@@ -281,7 +298,7 @@ export async function writeJsonFile<T>(
|
|
|
281
298
|
try {
|
|
282
299
|
content = JSON.stringify(object, null, 2);
|
|
283
300
|
} catch (e) {
|
|
284
|
-
ensureError
|
|
301
|
+
ensureError(e);
|
|
285
302
|
throw new JsonSerializationError(absolutePathToFile, e);
|
|
286
303
|
}
|
|
287
304
|
|
|
@@ -318,17 +335,17 @@ export async function writeJsonFileAsStream<T>(
|
|
|
318
335
|
|
|
319
336
|
await pipeline(jsonStream, fileWriteStream);
|
|
320
337
|
} catch (e) {
|
|
321
|
-
ensureError
|
|
338
|
+
ensureError(e);
|
|
322
339
|
// if the directory was created, we should remove it
|
|
323
340
|
if (dirExists === false) {
|
|
324
341
|
try {
|
|
325
342
|
await remove(dirPath);
|
|
326
343
|
// we don't want to override the original error
|
|
327
|
-
} catch (
|
|
344
|
+
} catch (_error) {}
|
|
328
345
|
}
|
|
329
346
|
|
|
330
347
|
// If the code is defined, we assume the error to be related to the file system
|
|
331
|
-
if (e.code !== undefined) {
|
|
348
|
+
if ("code" in e && e.code !== undefined) {
|
|
332
349
|
throw new FileSystemAccessError(e.message, e);
|
|
333
350
|
}
|
|
334
351
|
|
|
@@ -356,7 +373,7 @@ export async function readUtf8File(
|
|
|
356
373
|
try {
|
|
357
374
|
return await fsPromises.readFile(absolutePathToFile, { encoding: "utf8" });
|
|
358
375
|
} catch (e) {
|
|
359
|
-
|
|
376
|
+
ensureNodeErrnoExceptionError(e);
|
|
360
377
|
|
|
361
378
|
if (e.code === "ENOENT") {
|
|
362
379
|
throw new FileNotFoundError(absolutePathToFile, e);
|
|
@@ -398,13 +415,13 @@ export async function writeUtf8File(
|
|
|
398
415
|
flag,
|
|
399
416
|
});
|
|
400
417
|
} catch (e) {
|
|
401
|
-
|
|
418
|
+
ensureNodeErrnoExceptionError(e);
|
|
402
419
|
// if the directory was created, we should remove it
|
|
403
420
|
if (dirExists === false) {
|
|
404
421
|
try {
|
|
405
422
|
await remove(dirPath);
|
|
406
423
|
// we don't want to override the original error
|
|
407
|
-
} catch (
|
|
424
|
+
} catch (_error) {}
|
|
408
425
|
}
|
|
409
426
|
|
|
410
427
|
if (e.code === "ENOENT") {
|
|
@@ -436,7 +453,7 @@ export async function readBinaryFile(
|
|
|
436
453
|
const buffer = await fsPromises.readFile(absolutePathToFile);
|
|
437
454
|
return new Uint8Array(buffer);
|
|
438
455
|
} catch (e) {
|
|
439
|
-
|
|
456
|
+
ensureNodeErrnoExceptionError(e);
|
|
440
457
|
|
|
441
458
|
if (e.code === "ENOENT") {
|
|
442
459
|
throw new FileNotFoundError(absolutePathToFile, e);
|
|
@@ -463,7 +480,7 @@ export async function readdir(absolutePathToDir: string): Promise<string[]> {
|
|
|
463
480
|
try {
|
|
464
481
|
return await fsPromises.readdir(absolutePathToDir);
|
|
465
482
|
} catch (e) {
|
|
466
|
-
|
|
483
|
+
ensureNodeErrnoExceptionError(e);
|
|
467
484
|
if (e.code === "ENOENT") {
|
|
468
485
|
throw new FileNotFoundError(absolutePathToDir, e);
|
|
469
486
|
}
|
|
@@ -503,7 +520,7 @@ export async function mkdir(absolutePath: string): Promise<void> {
|
|
|
503
520
|
try {
|
|
504
521
|
await fsPromises.mkdir(absolutePath, { recursive: true });
|
|
505
522
|
} catch (e) {
|
|
506
|
-
|
|
523
|
+
ensureNodeErrnoExceptionError(e);
|
|
507
524
|
throw new FileSystemAccessError(e.message, e);
|
|
508
525
|
}
|
|
509
526
|
}
|
|
@@ -514,6 +531,24 @@ export async function mkdir(absolutePath: string): Promise<void> {
|
|
|
514
531
|
*/
|
|
515
532
|
export const ensureDir: typeof mkdir = mkdir;
|
|
516
533
|
|
|
534
|
+
/**
|
|
535
|
+
* Creates a temporary directory with the specified prefix.
|
|
536
|
+
*
|
|
537
|
+
* @param prefix The prefix to use for the temporary directory.
|
|
538
|
+
* @returns The absolute path to the created temporary directory.
|
|
539
|
+
* @throws FileSystemAccessError for any error.
|
|
540
|
+
*/
|
|
541
|
+
export async function mkdtemp(prefix: string): Promise<string> {
|
|
542
|
+
try {
|
|
543
|
+
return await getRealPath(
|
|
544
|
+
await fsPromises.mkdtemp(path.join(tmpdir(), prefix)),
|
|
545
|
+
);
|
|
546
|
+
} catch (e) {
|
|
547
|
+
ensureNodeErrnoExceptionError(e);
|
|
548
|
+
throw new FileSystemAccessError(e.message, e);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
517
552
|
/**
|
|
518
553
|
* Retrieves the last change time of a file or directory's properties.
|
|
519
554
|
* This includes changes to the file's metadata or contents.
|
|
@@ -528,7 +563,7 @@ export async function getChangeTime(absolutePath: string): Promise<Date> {
|
|
|
528
563
|
const stats = await fsPromises.stat(absolutePath);
|
|
529
564
|
return stats.ctime;
|
|
530
565
|
} catch (e) {
|
|
531
|
-
|
|
566
|
+
ensureNodeErrnoExceptionError(e);
|
|
532
567
|
if (e.code === "ENOENT") {
|
|
533
568
|
throw new FileNotFoundError(absolutePath, e);
|
|
534
569
|
}
|
|
@@ -550,7 +585,7 @@ export async function getAccessTime(absolutePath: string): Promise<Date> {
|
|
|
550
585
|
const stats = await fsPromises.stat(absolutePath);
|
|
551
586
|
return stats.atime;
|
|
552
587
|
} catch (e) {
|
|
553
|
-
|
|
588
|
+
ensureNodeErrnoExceptionError(e);
|
|
554
589
|
if (e.code === "ENOENT") {
|
|
555
590
|
throw new FileNotFoundError(absolutePath, e);
|
|
556
591
|
}
|
|
@@ -572,7 +607,7 @@ export async function getFileSize(absolutePath: string): Promise<number> {
|
|
|
572
607
|
const stats = await fsPromises.stat(absolutePath);
|
|
573
608
|
return stats.size;
|
|
574
609
|
} catch (e) {
|
|
575
|
-
|
|
610
|
+
ensureNodeErrnoExceptionError(e);
|
|
576
611
|
if (e.code === "ENOENT") {
|
|
577
612
|
throw new FileNotFoundError(absolutePath, e);
|
|
578
613
|
}
|
|
@@ -591,7 +626,7 @@ export async function exists(absolutePath: string): Promise<boolean> {
|
|
|
591
626
|
try {
|
|
592
627
|
await fsPromises.access(absolutePath);
|
|
593
628
|
return true;
|
|
594
|
-
} catch (
|
|
629
|
+
} catch (_error) {
|
|
595
630
|
return false;
|
|
596
631
|
}
|
|
597
632
|
}
|
|
@@ -610,7 +645,7 @@ export async function copy(source: string, destination: string): Promise<void> {
|
|
|
610
645
|
try {
|
|
611
646
|
await fsPromises.copyFile(source, destination);
|
|
612
647
|
} catch (e) {
|
|
613
|
-
|
|
648
|
+
ensureNodeErrnoExceptionError(e);
|
|
614
649
|
if (e.code === "ENOENT") {
|
|
615
650
|
if (!(await exists(source))) {
|
|
616
651
|
throw new FileNotFoundError(source, e);
|
|
@@ -654,7 +689,7 @@ export async function move(source: string, destination: string): Promise<void> {
|
|
|
654
689
|
try {
|
|
655
690
|
await fsPromises.rename(source, destination);
|
|
656
691
|
} catch (e) {
|
|
657
|
-
|
|
692
|
+
ensureNodeErrnoExceptionError(e);
|
|
658
693
|
if (e.code === "ENOENT") {
|
|
659
694
|
if (!(await exists(source))) {
|
|
660
695
|
throw new FileNotFoundError(source, e);
|
|
@@ -689,9 +724,10 @@ export async function remove(absolutePath: string): Promise<void> {
|
|
|
689
724
|
recursive: true,
|
|
690
725
|
force: true,
|
|
691
726
|
maxRetries: 3,
|
|
727
|
+
retryDelay: 300,
|
|
692
728
|
});
|
|
693
729
|
} catch (e) {
|
|
694
|
-
|
|
730
|
+
ensureNodeErrnoExceptionError(e);
|
|
695
731
|
throw new FileSystemAccessError(e.message, e);
|
|
696
732
|
}
|
|
697
733
|
}
|
|
@@ -711,7 +747,7 @@ export async function chmod(
|
|
|
711
747
|
try {
|
|
712
748
|
await fsPromises.chmod(absolutePath, mode);
|
|
713
749
|
} catch (e) {
|
|
714
|
-
|
|
750
|
+
ensureNodeErrnoExceptionError(e);
|
|
715
751
|
if (e.code === "ENOENT") {
|
|
716
752
|
throw new FileNotFoundError(absolutePath, e);
|
|
717
753
|
}
|
|
@@ -748,7 +784,7 @@ export async function emptyDir(absolutePath: string): Promise<void> {
|
|
|
748
784
|
isDir = stats.isDirectory();
|
|
749
785
|
mode = stats.mode;
|
|
750
786
|
} catch (e) {
|
|
751
|
-
|
|
787
|
+
ensureNodeErrnoExceptionError(e);
|
|
752
788
|
if (e.code === "ENOENT") {
|
|
753
789
|
await mkdir(absolutePath);
|
|
754
790
|
return;
|
|
@@ -763,7 +799,7 @@ export async function emptyDir(absolutePath: string): Promise<void> {
|
|
|
763
799
|
|
|
764
800
|
await remove(absolutePath);
|
|
765
801
|
await mkdir(absolutePath);
|
|
766
|
-
// eslint-disable-next-line no-bitwise -- Bitwise
|
|
802
|
+
// eslint-disable-next-line no-bitwise -- Bitwise is common in fs permissions
|
|
767
803
|
await chmod(absolutePath, mode & 0o777);
|
|
768
804
|
}
|
|
769
805
|
|
package/src/internal/bytecode.ts
CHANGED
package/src/package.ts
CHANGED
|
@@ -10,6 +10,31 @@ import { exists, findUp, getRealPath, readJsonFile } from "./fs.js";
|
|
|
10
10
|
import { getFilePath } from "./internal/package.js";
|
|
11
11
|
import { ensureTrailingSlash } from "./string.js";
|
|
12
12
|
|
|
13
|
+
/* Adapted from `resolve.exports`. License: https://github.com/lukeed/resolve.exports/blob/master/license */
|
|
14
|
+
|
|
15
|
+
export type PackageExports =
|
|
16
|
+
| PackageExportPath
|
|
17
|
+
| {
|
|
18
|
+
[path: PackageExportsEntry]: PackageExportsValue;
|
|
19
|
+
[condition: string]: PackageExportsValue;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** Allows "." and "./{name}" */
|
|
23
|
+
export type PackageExportsEntry = `.${string}`;
|
|
24
|
+
|
|
25
|
+
/** Internal path */
|
|
26
|
+
export type PackageExportPath = `./${string}`;
|
|
27
|
+
|
|
28
|
+
export type PackageExportsValue =
|
|
29
|
+
| PackageExportPath
|
|
30
|
+
| null
|
|
31
|
+
| {
|
|
32
|
+
[condition: string]: PackageExportsValue;
|
|
33
|
+
}
|
|
34
|
+
| PackageExportsValue[];
|
|
35
|
+
|
|
36
|
+
/* End of `resolve.exports` adaptation */
|
|
37
|
+
|
|
13
38
|
/**
|
|
14
39
|
* The structure of a `package.json` file. This is a subset of the actual
|
|
15
40
|
* `package.json` file, if you need to access other fields you add them here.
|
|
@@ -22,6 +47,7 @@ export interface PackageJson {
|
|
|
22
47
|
engines?: {
|
|
23
48
|
node?: string;
|
|
24
49
|
};
|
|
50
|
+
exports?: PackageExports;
|
|
25
51
|
dependencies?: Record<string, string>;
|
|
26
52
|
devDependencies?: Record<string, string>;
|
|
27
53
|
peerDependencies?: Record<string, string>;
|
package/src/path.ts
CHANGED
|
@@ -22,7 +22,7 @@ export function resolveFromRoot(root: string, target: string): string {
|
|
|
22
22
|
* Tries to return a shorter version of the path if its inside the given folder.
|
|
23
23
|
*
|
|
24
24
|
* This is useful for displaying paths in the terminal, as they can be shorter
|
|
25
|
-
* when they are
|
|
25
|
+
* when they are inside the current working directory. For example, if the
|
|
26
26
|
* current working directory is `/home/user/project`, and the path is
|
|
27
27
|
* `/home/user/project/contracts/File.sol`, the shorter path is
|
|
28
28
|
* `contracts/File.sol`.
|
|
@@ -31,11 +31,21 @@ export function resolveFromRoot(root: string, target: string): string {
|
|
|
31
31
|
* @param folder The absolute path to the folder.
|
|
32
32
|
* @returns The shorter path, if possible, or the original path.
|
|
33
33
|
*/
|
|
34
|
-
export function shortenPath(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
export function shortenPath(absolutePath: string): string {
|
|
35
|
+
const cwd = process.cwd();
|
|
36
|
+
let relativePath = path.relative(cwd, absolutePath);
|
|
37
|
+
|
|
38
|
+
if (relativePath === "..") {
|
|
39
|
+
return ".." + path.sep;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (
|
|
43
|
+
!relativePath.startsWith(".." + path.sep) &&
|
|
44
|
+
!relativePath.startsWith("." + path.sep) &&
|
|
45
|
+
!path.isAbsolute(relativePath)
|
|
46
|
+
) {
|
|
47
|
+
relativePath = "." + path.sep + relativePath;
|
|
48
|
+
}
|
|
39
49
|
|
|
40
50
|
if (relativePath.length < absolutePath.length) {
|
|
41
51
|
return relativePath;
|
package/src/request.ts
CHANGED
|
@@ -62,13 +62,22 @@ export interface RequestOptions {
|
|
|
62
62
|
abortSignal?: AbortSignal | EventEmitter;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
export interface HttpResponse {
|
|
66
|
+
statusCode: number;
|
|
67
|
+
body: {
|
|
68
|
+
json(): Promise<any>;
|
|
69
|
+
text(): Promise<string>;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
65
73
|
/**
|
|
66
74
|
* Performs a HTTP request.
|
|
67
75
|
*
|
|
68
76
|
* @param url The url to make the request to.
|
|
69
77
|
* @param requestOptions The options to configure the request. See {@link RequestOptions}.
|
|
70
78
|
* @param dispatcherOrDispatcherOptions Either a dispatcher or dispatcher options. See {@link DispatcherOptions}.
|
|
71
|
-
* @returns
|
|
79
|
+
* @returns An object containing the status code and the response body. The body can be accessed as JSON or text.
|
|
80
|
+
* `body` can not be consumed twice. For example, calling `text()` after `json()` throws `TypeError`.
|
|
72
81
|
* @throws ConnectionRefusedError If the connection is refused by the server.
|
|
73
82
|
* @throws RequestTimeoutError If the request times out.
|
|
74
83
|
* @throws RequestError If the request fails for any other reason.
|
|
@@ -77,7 +86,7 @@ export async function getRequest(
|
|
|
77
86
|
url: string,
|
|
78
87
|
requestOptions: RequestOptions = {},
|
|
79
88
|
dispatcherOrDispatcherOptions?: UndiciT.Dispatcher | DispatcherOptions,
|
|
80
|
-
): Promise<
|
|
89
|
+
): Promise<HttpResponse> {
|
|
81
90
|
const { request } = await import("undici");
|
|
82
91
|
|
|
83
92
|
try {
|
|
@@ -106,7 +115,8 @@ export async function getRequest(
|
|
|
106
115
|
* @param body The body of the request, represented as an object.
|
|
107
116
|
* @param requestOptions The options to configure the request. See {@link RequestOptions}.
|
|
108
117
|
* @param dispatcherOrDispatcherOptions Either a dispatcher or dispatcher options. See {@link DispatcherOptions}.
|
|
109
|
-
* @returns
|
|
118
|
+
* @returns An object containing the status code and the response body. The body can be accessed as JSON or text.
|
|
119
|
+
* `body` can not be consumed twice. For example, calling `text()` after `json()` throws `TypeError`.
|
|
110
120
|
* @throws ConnectionRefusedError If the connection is refused by the server.
|
|
111
121
|
* @throws RequestTimeoutError If the request times out.
|
|
112
122
|
* @throws RequestError If the request fails for any other reason.
|
|
@@ -116,7 +126,7 @@ export async function postJsonRequest(
|
|
|
116
126
|
body: unknown,
|
|
117
127
|
requestOptions: RequestOptions = {},
|
|
118
128
|
dispatcherOrDispatcherOptions?: UndiciT.Dispatcher | DispatcherOptions,
|
|
119
|
-
): Promise<
|
|
129
|
+
): Promise<HttpResponse> {
|
|
120
130
|
const { request } = await import("undici");
|
|
121
131
|
|
|
122
132
|
try {
|
|
@@ -150,7 +160,8 @@ export async function postJsonRequest(
|
|
|
150
160
|
* @param body The body of the request, represented as an object.
|
|
151
161
|
* @param requestOptions The options to configure the request. See {@link RequestOptions}.
|
|
152
162
|
* @param dispatcherOrDispatcherOptions Either a dispatcher or dispatcher options. See {@link DispatcherOptions}.
|
|
153
|
-
* @returns
|
|
163
|
+
* @returns An object containing the status code and the response body. The body can be accessed as JSON or text.
|
|
164
|
+
* `body` can not be consumed twice. For example, calling `text()` after `json()` throws `TypeError`.
|
|
154
165
|
* @throws ConnectionRefusedError If the connection is refused by the server.
|
|
155
166
|
* @throws RequestTimeoutError If the request times out.
|
|
156
167
|
* @throws RequestError If the request fails for any other reason.
|
|
@@ -160,7 +171,7 @@ export async function postFormRequest(
|
|
|
160
171
|
body: unknown,
|
|
161
172
|
requestOptions: RequestOptions = {},
|
|
162
173
|
dispatcherOrDispatcherOptions?: UndiciT.Dispatcher | DispatcherOptions,
|
|
163
|
-
): Promise<
|
|
174
|
+
): Promise<HttpResponse> {
|
|
164
175
|
const { request } = await import("undici");
|
|
165
176
|
|
|
166
177
|
try {
|
|
@@ -208,11 +219,16 @@ export async function download(
|
|
|
208
219
|
let statusCode: number | undefined;
|
|
209
220
|
|
|
210
221
|
try {
|
|
211
|
-
|
|
222
|
+
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
223
|
+
-- We need the full Dispatcher.ResponseData here for stream.pipeline,
|
|
224
|
+
but HttpResponse doesn’t expose the raw ReadableStream.
|
|
225
|
+
TODO: wrap undici's request so we can keep the public API
|
|
226
|
+
strictly typed without falling back to Undici types. */
|
|
227
|
+
const response = (await getRequest(
|
|
212
228
|
url,
|
|
213
229
|
requestOptions,
|
|
214
230
|
dispatcherOrDispatcherOptions,
|
|
215
|
-
);
|
|
231
|
+
)) as UndiciT.Dispatcher.ResponseData;
|
|
216
232
|
const { body } = response;
|
|
217
233
|
statusCode = response.statusCode;
|
|
218
234
|
|
package/src/stream.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Writable } from "node:stream";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Creates a
|
|
4
|
+
* Creates a Transform that writes everything to actualWritable, without closing it
|
|
5
5
|
* when finished.
|
|
6
6
|
*
|
|
7
7
|
* This is useful to pipe things to stdout, without closing it, while being
|
package/src/subprocess.ts
CHANGED
|
@@ -33,7 +33,7 @@ export async function spawnDetachedSubProcess(
|
|
|
33
33
|
const subprocessArgs = [absolutePathToSubProcessFile, ...args];
|
|
34
34
|
|
|
35
35
|
if (absolutePathToSubProcessFile.endsWith(".ts")) {
|
|
36
|
-
subprocessArgs.unshift("--import", "tsx/esm");
|
|
36
|
+
subprocessArgs.unshift("--import", import.meta.resolve("tsx/esm"));
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const subprocess = spawn(process.execPath, subprocessArgs, {
|
package/src/synchronization.ts
CHANGED
|
@@ -13,7 +13,7 @@ import path from "node:path";
|
|
|
13
13
|
|
|
14
14
|
import debug from "debug";
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import { ensureNodeErrnoExceptionError } from "./error.js";
|
|
17
17
|
import { FileSystemAccessError } from "./errors/fs.js";
|
|
18
18
|
import { sleep } from "./lang.js";
|
|
19
19
|
|
|
@@ -62,7 +62,7 @@ export class MultiProcessMutex {
|
|
|
62
62
|
fs.writeFileSync(this.#mutexFilePath, "", { flag: "wx+" });
|
|
63
63
|
return true;
|
|
64
64
|
} catch (e) {
|
|
65
|
-
|
|
65
|
+
ensureNodeErrnoExceptionError(e);
|
|
66
66
|
|
|
67
67
|
if (e.code === "EEXIST") {
|
|
68
68
|
// File already exists, so the mutex is already acquired
|
|
@@ -91,7 +91,7 @@ export class MultiProcessMutex {
|
|
|
91
91
|
try {
|
|
92
92
|
fileStat = fs.statSync(this.#mutexFilePath);
|
|
93
93
|
} catch (e) {
|
|
94
|
-
|
|
94
|
+
ensureNodeErrnoExceptionError(e);
|
|
95
95
|
|
|
96
96
|
if (e.code === "ENOENT") {
|
|
97
97
|
// The file might have been deleted by another process while this function was trying to access it.
|
|
@@ -113,7 +113,7 @@ export class MultiProcessMutex {
|
|
|
113
113
|
log(`Deleting mutex file at path '${this.#mutexFilePath}'`);
|
|
114
114
|
fs.unlinkSync(this.#mutexFilePath);
|
|
115
115
|
} catch (e) {
|
|
116
|
-
|
|
116
|
+
ensureNodeErrnoExceptionError(e);
|
|
117
117
|
|
|
118
118
|
if (e.code === "ENOENT") {
|
|
119
119
|
// The file might have been deleted by another process while this function was trying to access it.
|