@nomicfoundation/hardhat-utils 4.1.0 → 4.1.2

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/src/bytecode.d.ts +4 -0
  3. package/dist/src/bytecode.d.ts.map +1 -1
  4. package/dist/src/bytecode.js +12 -7
  5. package/dist/src/bytecode.js.map +1 -1
  6. package/dist/src/crypto.d.ts.map +1 -1
  7. package/dist/src/crypto.js +10 -2
  8. package/dist/src/crypto.js.map +1 -1
  9. package/dist/src/fs.d.ts.map +1 -1
  10. package/dist/src/fs.js +21 -35
  11. package/dist/src/fs.js.map +1 -1
  12. package/dist/src/internal/bytecode.d.ts +11 -0
  13. package/dist/src/internal/bytecode.d.ts.map +1 -1
  14. package/dist/src/internal/bytecode.js +39 -2
  15. package/dist/src/internal/bytecode.js.map +1 -1
  16. package/dist/src/internal/fs.d.ts +15 -0
  17. package/dist/src/internal/fs.d.ts.map +1 -1
  18. package/dist/src/internal/fs.js +44 -0
  19. package/dist/src/internal/fs.js.map +1 -1
  20. package/dist/src/internal/global-dir.d.ts +2 -2
  21. package/dist/src/internal/global-dir.d.ts.map +1 -1
  22. package/dist/src/internal/global-dir.js +7 -1
  23. package/dist/src/internal/global-dir.js.map +1 -1
  24. package/dist/src/internal/lang.d.ts +3 -2
  25. package/dist/src/internal/lang.d.ts.map +1 -1
  26. package/dist/src/internal/lang.js +12 -6
  27. package/dist/src/internal/lang.js.map +1 -1
  28. package/dist/src/lang.js +2 -2
  29. package/dist/src/lang.js.map +1 -1
  30. package/dist/src/path.d.ts +13 -0
  31. package/dist/src/path.d.ts.map +1 -1
  32. package/dist/src/path.js +20 -0
  33. package/dist/src/path.js.map +1 -1
  34. package/dist/src/request.d.ts +11 -11
  35. package/dist/src/request.d.ts.map +1 -1
  36. package/dist/src/request.js +6 -6
  37. package/dist/src/request.js.map +1 -1
  38. package/dist/src/synchronization.js +6 -6
  39. package/dist/src/synchronization.js.map +1 -1
  40. package/package.json +7 -6
  41. package/src/bytecode.ts +15 -6
  42. package/src/crypto.ts +15 -2
  43. package/src/fs.ts +33 -53
  44. package/src/internal/bytecode.ts +64 -5
  45. package/src/internal/fs.ts +70 -0
  46. package/src/internal/global-dir.ts +10 -4
  47. package/src/internal/lang.ts +15 -6
  48. package/src/lang.ts +2 -2
  49. package/src/path.ts +23 -0
  50. package/src/request.ts +16 -16
  51. package/src/synchronization.ts +6 -6
package/src/fs.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { JsonTypes, ParsedElementInfo } from "@streamparser/json-node";
1
+ import type * as StreamParserJson from "@streamparser/json-node";
2
+ import type * as JsonStreamStringify from "json-stream-stringify";
2
3
  import type { FileHandle } from "node:fs/promises";
3
4
 
4
5
  import fsPromises from "node:fs/promises";
@@ -6,9 +7,6 @@ import { tmpdir } from "node:os";
6
7
  import path from "node:path";
7
8
  import { pipeline } from "node:stream/promises";
8
9
 
9
- import { JSONParser } from "@streamparser/json-node";
10
- import { JsonStreamStringify } from "json-stream-stringify";
11
-
12
10
  import { ensureError, ensureNodeErrnoExceptionError } from "./error.js";
13
11
  import {
14
12
  FileNotFoundError,
@@ -21,10 +19,18 @@ import {
21
19
  DirectoryNotEmptyError,
22
20
  } from "./errors/fs.js";
23
21
  import {
24
- isDirectoryDirentAware,
25
- readdirWithFileTypesOrEmpty,
22
+ collectAllDirectoriesMatching,
23
+ collectAllFilesMatching,
26
24
  } from "./internal/fs.js";
27
25
 
26
+ // We don't load @streamparser/json-node on startup because it's only
27
+ // used by readJsonFileAsStream for very large JSON files.
28
+ let streamParserJson: typeof StreamParserJson | undefined;
29
+
30
+ // We don't load json-stream-stringify on startup because it's only
31
+ // used by writeJsonFileAsStream for very large JSON objects.
32
+ let jsonStreamStringify: typeof JsonStreamStringify | undefined;
33
+
28
34
  const AMBIGUOUS_CASING_DIR_ENTRY = Symbol("ambiguous");
29
35
 
30
36
  type CaseFoldedEntry = string | typeof AMBIGUOUS_CASING_DIR_ENTRY;
@@ -310,33 +316,10 @@ export async function getAllFilesMatching(
310
316
  matches?: (absolutePathToFile: string) => Promise<boolean> | boolean,
311
317
  directoryFilter?: (absolutePathToDir: string) => Promise<boolean> | boolean,
312
318
  ): Promise<string[]> {
313
- const dirContent = await readdirWithFileTypesOrEmpty(dirFrom);
314
-
315
- const results = await Promise.all(
316
- dirContent.map(async (dirent) => {
317
- const absolutePathToFile = path.join(dirFrom, dirent.name);
318
- if (await isDirectoryDirentAware(absolutePathToFile, dirent)) {
319
- if (
320
- directoryFilter === undefined ||
321
- (await directoryFilter(absolutePathToFile))
322
- ) {
323
- return await getAllFilesMatching(
324
- absolutePathToFile,
325
- matches,
326
- directoryFilter,
327
- );
328
- }
319
+ const results: string[] = [];
320
+ await collectAllFilesMatching(dirFrom, results, matches, directoryFilter);
329
321
 
330
- return [];
331
- } else if (matches === undefined || (await matches(absolutePathToFile))) {
332
- return absolutePathToFile;
333
- } else {
334
- return [];
335
- }
336
- }),
337
- );
338
-
339
- return results.flat();
322
+ return results;
340
323
  }
341
324
 
342
325
  /**
@@ -358,24 +341,10 @@ export async function getAllDirectoriesMatching(
358
341
  dirFrom: string,
359
342
  matches?: (absolutePathToDir: string) => Promise<boolean> | boolean,
360
343
  ): Promise<string[]> {
361
- const dirContent = await readdirWithFileTypesOrEmpty(dirFrom);
362
-
363
- const results = await Promise.all(
364
- dirContent.map(async (dirent) => {
365
- const absolutePathToFile = path.join(dirFrom, dirent.name);
366
- if (!(await isDirectoryDirentAware(absolutePathToFile, dirent))) {
367
- return [];
368
- }
344
+ const results: string[] = [];
345
+ await collectAllDirectoriesMatching(dirFrom, results, matches);
369
346
 
370
- if (matches === undefined || (await matches(absolutePathToFile))) {
371
- return absolutePathToFile;
372
- }
373
-
374
- return await getAllDirectoriesMatching(absolutePathToFile, matches);
375
- }),
376
- );
377
-
378
- return results.flat();
347
+ return results;
379
348
  }
380
349
 
381
350
  /**
@@ -459,9 +428,13 @@ export async function readJsonFileAsStream<T>(
459
428
 
460
429
  const fileReadStream = fileHandle.createReadStream();
461
430
 
431
+ if (streamParserJson === undefined) {
432
+ streamParserJson = await import("@streamparser/json-node");
433
+ }
434
+
462
435
  // NOTE: We set a separator to disable self-closing to be able to use the parser
463
436
  // in the stream.pipeline context; see https://github.com/juanjoDiaz/streamparser-json/issues/47
464
- const jsonParser = new JSONParser({
437
+ const jsonParser = new streamParserJson.JSONParser({
465
438
  separator: "",
466
439
  });
467
440
 
@@ -469,9 +442,12 @@ export async function readJsonFileAsStream<T>(
469
442
  fileReadStream,
470
443
  jsonParser,
471
444
  async (
472
- elements: AsyncIterable<ParsedElementInfo.ParsedElementInfo>,
445
+ elements: AsyncIterable<StreamParserJson.ParsedElementInfo.ParsedElementInfo>,
473
446
  ): Promise<any | undefined> => {
474
- let value: JsonTypes.JsonPrimitive | JsonTypes.JsonStruct | undefined;
447
+ let value:
448
+ | StreamParserJson.JsonTypes.JsonPrimitive
449
+ | StreamParserJson.JsonTypes.JsonStruct
450
+ | undefined;
475
451
  for await (const element of elements) {
476
452
  value = element.value;
477
453
  }
@@ -560,7 +536,11 @@ export async function writeJsonFileAsStream<T>(
560
536
  try {
561
537
  fileHandle = await fsPromises.open(absolutePathToFile, "w");
562
538
 
563
- const jsonStream = new JsonStreamStringify(object);
539
+ if (jsonStreamStringify === undefined) {
540
+ jsonStreamStringify = await import("json-stream-stringify");
541
+ }
542
+
543
+ const jsonStream = new jsonStreamStringify.JsonStreamStringify(object);
564
544
  const fileWriteStream = fileHandle.createWriteStream();
565
545
 
566
546
  await pipeline(jsonStream, fileWriteStream);
@@ -29,6 +29,17 @@ export interface LibraryAddresses {
29
29
  [contractName: string]: PrefixedHexString;
30
30
  }
31
31
 
32
+ export interface BytecodeReplacement {
33
+ start: number;
34
+ length: number;
35
+ value: string;
36
+ }
37
+
38
+ interface LibraryLinksIndex {
39
+ byName: Map<string, LibraryLink[]>;
40
+ byFqn: Map<string, LibraryLink>;
41
+ }
42
+
32
43
  /**
33
44
  * Check that the provided library addresses are valid Ethereum addresses.
34
45
  * If any of them are not, an InvalidLibraryAddressError is thrown.
@@ -61,13 +72,15 @@ export function checkAmbiguousOrUnnecessaryLinks(
61
72
  ): void {
62
73
  const ambiguousLibraries: Record<string, LibraryLink[]> = {};
63
74
  const unnecessaryLibraries: string[] = [];
75
+ const neededLibrariesIndex = indexLibraryLinks(neededLibraries);
64
76
 
65
77
  for (const providedLibraryName of Object.keys(providedLibraries)) {
66
- const matchingLibraries = neededLibraries.filter(
67
- ({ libraryName, libraryFqn }) =>
68
- libraryName === providedLibraryName ||
69
- libraryFqn === providedLibraryName,
70
- );
78
+ const matchingLibraryByFqn =
79
+ neededLibrariesIndex.byFqn.get(providedLibraryName);
80
+ const matchingLibraries =
81
+ matchingLibraryByFqn !== undefined
82
+ ? [matchingLibraryByFqn]
83
+ : neededLibrariesIndex.byName.get(providedLibraryName) ?? [];
71
84
 
72
85
  if (matchingLibraries.length > 1) {
73
86
  ambiguousLibraries[providedLibraryName] = matchingLibraries;
@@ -85,6 +98,24 @@ export function checkAmbiguousOrUnnecessaryLinks(
85
98
  }
86
99
  }
87
100
 
101
+ function indexLibraryLinks(neededLibraries: LibraryLink[]): LibraryLinksIndex {
102
+ const byName = new Map<string, LibraryLink[]>();
103
+ const byFqn = new Map<string, LibraryLink>();
104
+
105
+ for (const neededLibrary of neededLibraries) {
106
+ byFqn.set(neededLibrary.libraryFqn, neededLibrary);
107
+
108
+ const sameNameLibraries = byName.get(neededLibrary.libraryName);
109
+ if (sameNameLibraries === undefined) {
110
+ byName.set(neededLibrary.libraryName, [neededLibrary]);
111
+ } else {
112
+ sameNameLibraries.push(neededLibrary);
113
+ }
114
+ }
115
+
116
+ return { byName, byFqn };
117
+ }
118
+
88
119
  /**
89
120
  * Check that each library is only provided once, either by its name or its
90
121
  * fully qualified name. If a library is provided more than once, an
@@ -127,3 +158,31 @@ export function checkMissingLibraryAddresses(
127
158
 
128
159
  throw new MissingLibrariesError(missingLibraries);
129
160
  }
161
+
162
+ /**
163
+ * Apply a set of replacements to a bytecode string, returning the resulting
164
+ * bytecode. Each replacement overwrites `length` characters starting at
165
+ * `start` with `value`. Replacements must not overlap.
166
+ */
167
+ export function applyBytecodeReplacements(
168
+ bytecode: string,
169
+ replacements: BytecodeReplacement[],
170
+ ): string {
171
+ if (replacements.length === 0) {
172
+ return bytecode;
173
+ }
174
+
175
+ replacements.sort((a, b) => a.start - b.start);
176
+
177
+ const parts: string[] = [];
178
+ let position = 0;
179
+
180
+ for (const { start, length, value } of replacements) {
181
+ parts.push(bytecode.slice(position, start), value);
182
+ position = start + length;
183
+ }
184
+
185
+ parts.push(bytecode.slice(position));
186
+
187
+ return parts.join("");
188
+ }
@@ -1,6 +1,7 @@
1
1
  import type { Dirent } from "node:fs";
2
2
 
3
3
  import fsPromises from "node:fs/promises";
4
+ import path from "node:path";
4
5
 
5
6
  import { ensureNodeErrnoExceptionError } from "../error.js";
6
7
  import { FileSystemAccessError, NotADirectoryError } from "../errors/fs.js";
@@ -55,3 +56,72 @@ export async function isDirectoryDirentAware(
55
56
 
56
57
  return await isDirectory(absolutePath);
57
58
  }
59
+
60
+ /**
61
+ * Recursively walk the directory tree rooted at `dirFrom`, appending the
62
+ * absolute paths of every file accepted by `matches` to `results`. Descent
63
+ * into a subdirectory is gated by `directoryFilter`. When either callback is
64
+ * omitted, every file or directory is accepted.
65
+ */
66
+ export async function collectAllFilesMatching(
67
+ dirFrom: string,
68
+ results: string[],
69
+ matches?: (absolutePathToFile: string) => Promise<boolean> | boolean,
70
+ directoryFilter?: (absolutePathToDir: string) => Promise<boolean> | boolean,
71
+ ): Promise<void> {
72
+ const dirContent = await readdirWithFileTypesOrEmpty(dirFrom);
73
+
74
+ await Promise.all(
75
+ dirContent.map(async (dirent) => {
76
+ const absolutePathToFile = path.join(dirFrom, dirent.name);
77
+ if (await isDirectoryDirentAware(absolutePathToFile, dirent)) {
78
+ if (
79
+ directoryFilter === undefined ||
80
+ (await directoryFilter(absolutePathToFile))
81
+ ) {
82
+ await collectAllFilesMatching(
83
+ absolutePathToFile,
84
+ results,
85
+ matches,
86
+ directoryFilter,
87
+ );
88
+ }
89
+
90
+ return;
91
+ } else if (matches === undefined || (await matches(absolutePathToFile))) {
92
+ results.push(absolutePathToFile);
93
+ }
94
+ }),
95
+ );
96
+ }
97
+
98
+ /**
99
+ * Recursively walk the directory tree rooted at `dirFrom`, appending the
100
+ * absolute paths of every directory accepted by `matches` to `results`. When
101
+ * a directory matches, its descendants are not explored; when it does not,
102
+ * the walk continues into its subdirectories. When `matches` is omitted,
103
+ * every directory is accepted and recursion stops at the top level.
104
+ */
105
+ export async function collectAllDirectoriesMatching(
106
+ dirFrom: string,
107
+ results: string[],
108
+ matches?: (absolutePathToDir: string) => Promise<boolean> | boolean,
109
+ ): Promise<void> {
110
+ const dirContent = await readdirWithFileTypesOrEmpty(dirFrom);
111
+
112
+ await Promise.all(
113
+ dirContent.map(async (dirent) => {
114
+ const absolutePathToFile = path.join(dirFrom, dirent.name);
115
+ if (!(await isDirectoryDirentAware(absolutePathToFile, dirent))) {
116
+ return;
117
+ }
118
+
119
+ if (matches === undefined || (await matches(absolutePathToFile))) {
120
+ results.push(absolutePathToFile);
121
+ return;
122
+ }
123
+
124
+ await collectAllDirectoriesMatching(absolutePathToFile, results, matches);
125
+ }),
126
+ );
127
+ }
@@ -1,9 +1,15 @@
1
- import envPaths from "env-paths";
1
+ import type { Paths } from "env-paths";
2
2
 
3
3
  export const HARDHAT_PACKAGE_NAME = "hardhat";
4
4
 
5
- export async function generatePaths(
6
- packageName: string,
7
- ): Promise<envPaths.Paths> {
5
+ // We don't load env-paths on startup because this module is transitively
6
+ // imported from many places but generatePaths is rarely called during
7
+ // bootstrap.
8
+ let envPaths: ((name: string) => Paths) | undefined;
9
+
10
+ export async function generatePaths(packageName: string): Promise<Paths> {
11
+ if (envPaths === undefined) {
12
+ ({ default: envPaths } = await import("env-paths"));
13
+ }
8
14
  return envPaths(packageName);
9
15
  }
@@ -1,11 +1,15 @@
1
- import { createCustomEqual } from "fast-equals";
2
- import rfdc from "rfdc";
1
+ import type Rfdc from "rfdc";
3
2
 
4
3
  import { isObject } from "../lang.js";
5
4
 
6
- let clone: ReturnType<typeof rfdc> | null = null;
7
- export function getDeepCloneFunction(): <T>(input: T) => T {
8
- if (clone === null) {
5
+ // We don't load rfdc on startup because it adds unnecessary
6
+ // overhead when this module is transitively imported but deep clone
7
+ // is not used.
8
+ let clone: ReturnType<typeof Rfdc> | undefined;
9
+
10
+ export async function getDeepCloneFunction(): Promise<ReturnType<typeof Rfdc>> {
11
+ if (clone === undefined) {
12
+ const { default: rfdc } = await import("rfdc");
9
13
  clone = rfdc();
10
14
  }
11
15
 
@@ -53,6 +57,9 @@ export function deepMergeImpl<T extends object, S extends object>(
53
57
  return result;
54
58
  }
55
59
 
60
+ // We don't load fast-equals on startup because it adds unnecessary
61
+ // overhead when this module is transitively imported but deep equal
62
+ // is not used.
56
63
  let cachedCustomEqual: ((a: unknown, b: unknown) => boolean) | undefined;
57
64
 
58
65
  /**
@@ -62,11 +69,13 @@ let cachedCustomEqual: ((a: unknown, b: unknown) => boolean) | undefined;
62
69
  * @param y The second value to compare.
63
70
  * @returns True if the values are deeply equal, false otherwise.
64
71
  */
65
- export function customFastEqual<T>(x: T, y: T): boolean {
72
+ export async function customFastEqual<T>(x: T, y: T): Promise<boolean> {
66
73
  if (cachedCustomEqual !== undefined) {
67
74
  return cachedCustomEqual(x, y);
68
75
  }
69
76
 
77
+ const { createCustomEqual } = await import("fast-equals");
78
+
70
79
  cachedCustomEqual = createCustomEqual({
71
80
  createCustomConfig: (defaultConfig) => ({
72
81
  areTypedArraysEqual: (a, b, state) => {
package/src/lang.ts CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  * @returns The deep clone of the provided value.
12
12
  */
13
13
  export async function deepClone<T>(value: T): Promise<T> {
14
- const _deepClone = getDeepCloneFunction();
14
+ const _deepClone = await getDeepCloneFunction();
15
15
 
16
16
  return _deepClone<T>(value);
17
17
  }
@@ -24,7 +24,7 @@ export async function deepClone<T>(value: T): Promise<T> {
24
24
  * @returns True if the values are deeply equal, false otherwise.
25
25
  */
26
26
  export async function deepEqual<T>(x: T, y: T): Promise<boolean> {
27
- return customFastEqual(x, y);
27
+ return await customFastEqual(x, y);
28
28
  }
29
29
 
30
30
  /**
package/src/path.ts CHANGED
@@ -53,3 +53,26 @@ export function shortenPath(absolutePath: string): string {
53
53
 
54
54
  return absolutePath;
55
55
  }
56
+
57
+ /**
58
+ * Returns a version of {@link name} that is safe to use as a single filename
59
+ * component on POSIX, macOS, and Windows.
60
+ *
61
+ * Strips characters that are reserved on at least one of those platforms
62
+ * (`<>:"/\|?*` and ASCII control chars), trims trailing dots and whitespace
63
+ * (Windows silently strips them on write), and falls back to `_` if the
64
+ * result is empty or one of the path-traversal literals `.` / `..`.
65
+ *
66
+ * @param name The string to sanitize.
67
+ * @returns A non-empty filename-safe string.
68
+ */
69
+ export function sanitizeFilename(name: string): string {
70
+ let result = name.replace(/[<>:"/\\|?*\x00-\x1F\x7F]/g, "");
71
+ result = result.replace(/[\s.]+$/, "");
72
+
73
+ if (result === "" || result === "." || result === "..") {
74
+ result = "_";
75
+ }
76
+
77
+ return result;
78
+ }
package/src/request.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import type EventEmitter from "node:events";
2
2
  import type { FileHandle } from "node:fs/promises";
3
3
  import type { ParsedUrlQueryInput } from "node:querystring";
4
- import type * as UndiciT from "undici";
4
+ import type * as Undici from "undici";
5
5
 
6
6
  import { open } from "node:fs/promises";
7
7
  import querystring from "node:querystring";
8
- import stream from "node:stream/promises";
8
+ import { pipeline } from "node:stream/promises";
9
9
 
10
10
  import { ensureError } from "./error.js";
11
11
  import {
@@ -24,18 +24,18 @@ import {
24
24
  handleError,
25
25
  } from "./internal/request.js";
26
26
 
27
- export const DEFAULT_TIMEOUT_IN_MILLISECONDS = 300_000; // Aligned with unidici
27
+ export const DEFAULT_TIMEOUT_IN_MILLISECONDS = 300_000; // Aligned with undici
28
28
  export const DEFAULT_MAX_REDIRECTS = 10;
29
29
  export const DEFAULT_POOL_MAX_CONNECTIONS = 128;
30
30
  export const DEFAULT_USER_AGENT = "Hardhat";
31
31
 
32
- export type Dispatcher = UndiciT.Dispatcher;
33
- export type TestDispatcher = UndiciT.MockAgent;
34
- export type Interceptable = UndiciT.Interceptable;
32
+ export type Dispatcher = Undici.Dispatcher;
33
+ export type TestDispatcher = Undici.MockAgent;
34
+ export type Interceptable = Undici.Interceptable;
35
35
 
36
36
  // We don't load undici on startup because this package is transitively imported
37
37
  // from too many places and it's too complex to optimize case by case.
38
- let undici: typeof UndiciT | undefined;
38
+ let undici: typeof Undici | undefined;
39
39
 
40
40
  /**
41
41
  * Options to configure the dispatcher.
@@ -90,7 +90,7 @@ export interface HttpResponse {
90
90
  export async function getRequest(
91
91
  url: string,
92
92
  requestOptions: RequestOptions = {},
93
- dispatcherOrDispatcherOptions?: UndiciT.Dispatcher | DispatcherOptions,
93
+ dispatcherOrDispatcherOptions?: Undici.Dispatcher | DispatcherOptions,
94
94
  ): Promise<HttpResponse> {
95
95
  if (undici === undefined) {
96
96
  undici = await import("undici");
@@ -132,7 +132,7 @@ export async function postJsonRequest(
132
132
  url: string,
133
133
  body: unknown,
134
134
  requestOptions: RequestOptions = {},
135
- dispatcherOrDispatcherOptions?: UndiciT.Dispatcher | DispatcherOptions,
135
+ dispatcherOrDispatcherOptions?: Undici.Dispatcher | DispatcherOptions,
136
136
  ): Promise<HttpResponse> {
137
137
  if (undici === undefined) {
138
138
  undici = await import("undici");
@@ -179,7 +179,7 @@ export async function postFormRequest(
179
179
  url: string,
180
180
  body: unknown,
181
181
  requestOptions: RequestOptions = {},
182
- dispatcherOrDispatcherOptions?: UndiciT.Dispatcher | DispatcherOptions,
182
+ dispatcherOrDispatcherOptions?: Undici.Dispatcher | DispatcherOptions,
183
183
  ): Promise<HttpResponse> {
184
184
  if (undici === undefined) {
185
185
  undici = await import("undici");
@@ -225,7 +225,7 @@ export async function download(
225
225
  url: string,
226
226
  destination: string,
227
227
  requestOptions: RequestOptions = {},
228
- dispatcherOrDispatcherOptions?: UndiciT.Dispatcher | DispatcherOptions,
228
+ dispatcherOrDispatcherOptions?: Undici.Dispatcher | DispatcherOptions,
229
229
  ): Promise<void> {
230
230
  let statusCode: number | undefined;
231
231
  let tempFilePath: string | undefined;
@@ -240,7 +240,7 @@ export async function download(
240
240
  url,
241
241
  requestOptions,
242
242
  dispatcherOrDispatcherOptions,
243
- )) as UndiciT.Dispatcher.ResponseData;
243
+ )) as Undici.Dispatcher.ResponseData;
244
244
  const { body } = response;
245
245
  statusCode = response.statusCode;
246
246
 
@@ -257,7 +257,7 @@ export async function download(
257
257
 
258
258
  const fileStream = fileHandle.createWriteStream();
259
259
 
260
- await stream.pipeline(body, fileStream);
260
+ await pipeline(body, fileStream);
261
261
  } finally {
262
262
  // NOTE: Historically, not closing the file handle caused issues on Windows,
263
263
  // for example, when trying to move the file previously written to by this function
@@ -284,9 +284,9 @@ export async function download(
284
284
 
285
285
  /**
286
286
  * Creates a dispatcher based on the provided options.
287
- * If the `proxy` option is set, it creates a {@link UndiciT.ProxyAgent} dispatcher.
288
- * If the `pool` option is set to `true`, it creates a {@link UndiciT.Pool} dispatcher.
289
- * Otherwise, it creates a basic {@link UndiciT.Agent} dispatcher.
287
+ * If the `proxy` option is set, it creates a {@link Undici.ProxyAgent} dispatcher.
288
+ * If the `pool` option is set to `true`, it creates a {@link Undici.Pool} dispatcher.
289
+ * Otherwise, it creates a basic {@link Undici.Agent} dispatcher.
290
290
  *
291
291
  * @param url The url to make requests to.
292
292
  * @param options The options to configure the dispatcher. See {@link DispatcherOptions}.
@@ -1,7 +1,7 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import * as fs from "node:fs";
3
- import * as os from "node:os";
4
- import * as path from "node:path";
2
+ import fs from "node:fs";
3
+ import { hostname } from "node:os";
4
+ import path from "node:path";
5
5
 
6
6
  import { createDebug } from "./debug.js";
7
7
  import { ensureError, ensureNodeErrnoExceptionError } from "./error.js";
@@ -382,11 +382,11 @@ export class MultiProcessMutex {
382
382
  }
383
383
 
384
384
  // Different hostname — can't verify PID remotely
385
- if (metadata.hostname !== os.hostname()) {
385
+ if (metadata.hostname !== hostname()) {
386
386
  throw new IncompatibleHostnameMultiProcessMutexError(
387
387
  lockPath,
388
388
  metadata.hostname,
389
- os.hostname(),
389
+ hostname(),
390
390
  );
391
391
  }
392
392
 
@@ -475,7 +475,7 @@ export class MultiProcessMutex {
475
475
  #buildMetadata(): LockMetadata {
476
476
  return {
477
477
  pid: process.pid,
478
- hostname: os.hostname(),
478
+ hostname: hostname(),
479
479
  createdAt: Date.now(),
480
480
  ...(process.getuid !== undefined ? { uid: process.getuid() } : {}),
481
481
  platform: process.platform,