@zenfs/core 0.9.2 → 0.9.3

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.
@@ -0,0 +1,910 @@
1
+ import type * as Node from 'fs';
2
+ import { ApiError, ErrorCode } from '../ApiError.js';
3
+ import type { FileContents } from '../filesystem.js';
4
+ import { BigIntStats, type BigIntStatsFs, type Stats, type StatsFs } from '../stats.js';
5
+ import { nop, normalizeMode, type Callback } from '../utils.js';
6
+ import { R_OK } from './constants.js';
7
+ import { Dirent, type Dir } from './dir.js';
8
+ import * as promises from './promises.js';
9
+ import { PathLike, fd2file } from './shared.js';
10
+ import { ReadStream, WriteStream } from './streams.js';
11
+
12
+ /**
13
+ * Asynchronous rename. No arguments other than a possible exception are given
14
+ * to the completion callback.
15
+ * @param oldPath
16
+ * @param newPath
17
+ * @param callback
18
+ */
19
+ export function rename(oldPath: PathLike, newPath: PathLike, cb: Callback = nop): void {
20
+ promises
21
+ .rename(oldPath, newPath)
22
+ .then(() => cb())
23
+ .catch(cb);
24
+ }
25
+ rename satisfies Omit<typeof Node.rename, '__promisify__'>;
26
+
27
+ /**
28
+ * Test whether or not the given path exists by checking with the file system.
29
+ * Then call the callback argument with either true or false.
30
+ * @param path
31
+ * @param callback
32
+ * @deprecated Use {@link stat} or {@link access} instead.
33
+ */
34
+ export function exists(path: PathLike, cb: (exists: boolean) => unknown = nop): void {
35
+ promises
36
+ .exists(path)
37
+ .then(cb)
38
+ .catch(() => cb(false));
39
+ }
40
+ exists satisfies Omit<typeof Node.exists, '__promisify__'>;
41
+
42
+ /**
43
+ * Asynchronous `stat`.
44
+ * @param path
45
+ * @param callback
46
+ */
47
+ export function stat(path: PathLike, callback: Callback<[Stats]>): void;
48
+ export function stat(path: PathLike, options: { bigint?: false }, callback: Callback<[Stats]>): void;
49
+ export function stat(path: PathLike, options: { bigint: true }, callback: Callback<[BigIntStats]>): void;
50
+ export function stat(path: PathLike, options: Node.StatOptions, callback: Callback<[Stats] | [BigIntStats]>): void;
51
+ export function stat(path: PathLike, options?: Node.StatOptions | Callback<[Stats]>, callback: Callback<[Stats]> | Callback<[BigIntStats]> = nop): void {
52
+ callback = typeof options == 'function' ? options : callback;
53
+ promises
54
+ .stat(path, typeof options != 'function' ? options : {})
55
+ .then((stats: Stats & BigIntStats) => (<Callback<[Stats] | [BigIntStats]>>callback)(null, stats))
56
+ .catch(callback);
57
+ }
58
+ stat satisfies Omit<typeof Node.stat, '__promisify__'>;
59
+
60
+ /**
61
+ * Asynchronous `lstat`.
62
+ * `lstat()` is identical to `stat()`, except that if path is a symbolic link,
63
+ * then the link itself is stat-ed, not the file that it refers to.
64
+ * @param path
65
+ * @param callback
66
+ */
67
+ export function lstat(path: PathLike, callback: Callback<[Stats]>): void;
68
+ export function lstat(path: PathLike, options: Node.StatOptions & { bigint?: false }, callback: Callback<[Stats]>): void;
69
+ export function lstat(path: PathLike, options: Node.StatOptions & { bigint: true }, callback: Callback<[BigIntStats]>): void;
70
+ export function lstat(path: PathLike, options: Node.StatOptions, callback: Callback<[Stats | BigIntStats]>): void;
71
+ export function lstat(path: PathLike, options?: Node.StatOptions | Callback<[Stats]>, callback: Callback<[Stats]> | Callback<[BigIntStats]> = nop): void {
72
+ callback = typeof options == 'function' ? options : callback;
73
+ promises
74
+ .lstat(path, typeof options != 'function' ? options : <object>{})
75
+ .then(stats => (<Callback<[Stats] | [BigIntStats]>>callback)(null, stats))
76
+ .catch(callback);
77
+ }
78
+ lstat satisfies Omit<typeof Node.lstat, '__promisify__'>;
79
+
80
+ /**
81
+ * Asynchronous `truncate`.
82
+ * @param path
83
+ * @param len
84
+ * @param callback
85
+ */
86
+ export function truncate(path: PathLike, cb?: Callback): void;
87
+ export function truncate(path: PathLike, len: number, cb?: Callback): void;
88
+ export function truncate(path: PathLike, cbLen: number | Callback = 0, cb: Callback = nop): void {
89
+ cb = typeof cbLen === 'function' ? cbLen : cb;
90
+ const len = typeof cbLen === 'number' ? cbLen : 0;
91
+ promises
92
+ .truncate(path, len)
93
+ .then(() => cb())
94
+ .catch(cb);
95
+ }
96
+ truncate satisfies Omit<typeof Node.truncate, '__promisify__'>;
97
+
98
+ /**
99
+ * Asynchronous `unlink`.
100
+ * @param path
101
+ * @param callback
102
+ */
103
+ export function unlink(path: PathLike, cb: Callback = nop): void {
104
+ promises
105
+ .unlink(path)
106
+ .then(() => cb())
107
+ .catch(cb);
108
+ }
109
+ unlink satisfies Omit<typeof Node.unlink, '__promisify__'>;
110
+
111
+ /**
112
+ * Asynchronous file open.
113
+ * Exclusive mode ensures that path is newly created.
114
+ *
115
+ * `flags` can be:
116
+ *
117
+ * * `'r'` - Open file for reading. An exception occurs if the file does not exist.
118
+ * * `'r+'` - Open file for reading and writing. An exception occurs if the file does not exist.
119
+ * * `'rs'` - Open file for reading in synchronous mode. Instructs the filesystem to not cache writes.
120
+ * * `'rs+'` - Open file for reading and writing, and opens the file in synchronous mode.
121
+ * * `'w'` - Open file for writing. The file is created (if it does not exist) or truncated (if it exists).
122
+ * * `'wx'` - Like 'w' but opens the file in exclusive mode.
123
+ * * `'w+'` - Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists).
124
+ * * `'wx+'` - Like 'w+' but opens the file in exclusive mode.
125
+ * * `'a'` - Open file for appending. The file is created if it does not exist.
126
+ * * `'ax'` - Like 'a' but opens the file in exclusive mode.
127
+ * * `'a+'` - Open file for reading and appending. The file is created if it does not exist.
128
+ * * `'ax+'` - Like 'a+' but opens the file in exclusive mode.
129
+ *
130
+ * @see http://www.manpagez.com/man/2/open/
131
+ * @param path
132
+ * @param flags
133
+ * @param mode defaults to `0644`
134
+ * @param callback
135
+ */
136
+ export function open(path: PathLike, flag: string, cb?: Callback<[number]>): void;
137
+ export function open(path: PathLike, flag: string, mode: number | string, cb?: Callback<[number]>): void;
138
+ export function open(path: PathLike, flag: string, cbMode?: number | string | Callback<[number]>, cb: Callback<[number]> = nop): void {
139
+ const mode = normalizeMode(cbMode, 0o644);
140
+ cb = typeof cbMode === 'function' ? cbMode : cb;
141
+ promises
142
+ .open(path, flag, mode)
143
+ .then(handle => cb(null, handle.fd))
144
+ .catch(cb);
145
+ }
146
+ open satisfies Omit<typeof Node.open, '__promisify__'>;
147
+
148
+ /**
149
+ * Asynchronously reads the entire contents of a file.
150
+ * @param filename
151
+ * @param options
152
+ * @option options encoding The string encoding for the file contents. Defaults to `null`.
153
+ * @option options flag Defaults to `'r'`.
154
+ * @param callback If no encoding is specified, then the raw buffer is returned.
155
+ */
156
+ export function readFile(filename: PathLike, cb: Callback<[Uint8Array]>): void;
157
+ export function readFile(filename: PathLike, options: { flag?: string }, callback?: Callback<[Uint8Array]>): void;
158
+ export function readFile(filename: PathLike, options: { encoding: BufferEncoding; flag?: string } | BufferEncoding, cb: Callback<[string]>): void;
159
+ export function readFile(filename: PathLike, options?: Node.WriteFileOptions | BufferEncoding | Callback<[Uint8Array]>, cb: Callback<[string]> | Callback<[Uint8Array]> = nop) {
160
+ cb = typeof options === 'function' ? options : cb;
161
+
162
+ promises
163
+ .readFile(filename, typeof options === 'function' ? null : options)
164
+ .then(data => (<Callback<[string | Uint8Array]>>cb)(null, data))
165
+ .catch(cb);
166
+ }
167
+ readFile satisfies Omit<typeof Node.readFile, '__promisify__'>;
168
+
169
+ /**
170
+ * Asynchronously writes data to a file, replacing the file if it already
171
+ * exists.
172
+ *
173
+ * The encoding option is ignored if data is a buffer.
174
+ *
175
+ * @param filename
176
+ * @param data
177
+ * @param options
178
+ * @option encoding Defaults to `'utf8'`.
179
+ * @option mode Defaults to `0644`.
180
+ * @option flag Defaults to `'w'`.
181
+ * @param callback
182
+ */
183
+ export function writeFile(filename: PathLike, data: FileContents, cb?: Callback): void;
184
+ export function writeFile(filename: PathLike, data: FileContents, encoding?: BufferEncoding, cb?: Callback): void;
185
+ export function writeFile(filename: PathLike, data: FileContents, options?: Node.WriteFileOptions, cb?: Callback): void;
186
+ export function writeFile(filename: PathLike, data: FileContents, cbEncOpts?: Node.WriteFileOptions | Callback, cb: Callback = nop): void {
187
+ cb = typeof cbEncOpts === 'function' ? cbEncOpts : cb;
188
+ promises
189
+ .writeFile(filename, data, typeof cbEncOpts != 'function' ? cbEncOpts : null)
190
+ .then(() => cb(null))
191
+ .catch(cb);
192
+ }
193
+ writeFile satisfies Omit<typeof Node.writeFile, '__promisify__'>;
194
+
195
+ /**
196
+ * Asynchronously append data to a file, creating the file if it not yet
197
+ * exists.
198
+ *
199
+ * @param filename
200
+ * @param data
201
+ * @param options
202
+ * @option encoding Defaults to `'utf8'`.
203
+ * @option mode Defaults to `0644`.
204
+ * @option flag Defaults to `'a'`.
205
+ * @param callback
206
+ */
207
+ export function appendFile(filename: PathLike, data: FileContents, cb?: Callback): void;
208
+ export function appendFile(filename: PathLike, data: FileContents, options?: { encoding?: string; mode?: number | string; flag?: string }, cb?: Callback): void;
209
+ export function appendFile(filename: PathLike, data: FileContents, encoding?: string, cb?: Callback): void;
210
+ export function appendFile(filename: PathLike, data: FileContents, cbEncOpts?, cb: Callback = nop): void {
211
+ cb = typeof cbEncOpts === 'function' ? cbEncOpts : cb;
212
+ promises
213
+ .appendFile(filename, data, typeof cbEncOpts === 'function' ? null : cbEncOpts)
214
+ .then(() => cb())
215
+ .catch(cb);
216
+ }
217
+ appendFile satisfies Omit<typeof Node.appendFile, '__promisify__'>;
218
+
219
+ /**
220
+ * Asynchronous `fstat`.
221
+ * `fstat()` is identical to `stat()`, except that the file to be stat-ed is
222
+ * specified by the file descriptor `fd`.
223
+ * @param fd
224
+ * @param callback
225
+ */
226
+ export function fstat(fd: number, cb: Callback<[Stats]>): void;
227
+ export function fstat(fd: number, options: Node.StatOptions & { bigint?: false }, cb: Callback<[Stats]>): void;
228
+ export function fstat(fd: number, options: Node.StatOptions & { bigint: true }, cb: Callback<[BigIntStats]>): void;
229
+ export function fstat(fd: number, options?: Node.StatOptions | Callback<[Stats]>, cb: Callback<[Stats]> | Callback<[BigIntStats]> = nop): void {
230
+ cb = typeof options == 'function' ? options : cb;
231
+
232
+ fd2file(fd)
233
+ .stat()
234
+ .then(stats => (<Callback<[Stats | BigIntStats]>>cb)(null, typeof options == 'object' && options?.bigint ? new BigIntStats(stats) : stats))
235
+ .catch(cb);
236
+ }
237
+ fstat satisfies Omit<typeof Node.fstat, '__promisify__'>;
238
+
239
+ /**
240
+ * Asynchronous close.
241
+ * @param fd
242
+ * @param callback
243
+ */
244
+ export function close(fd: number, cb: Callback = nop): void {
245
+ new promises.FileHandle(fd)
246
+ .close()
247
+ .then(() => cb())
248
+ .catch(cb);
249
+ }
250
+ close satisfies Omit<typeof Node.close, '__promisify__'>;
251
+
252
+ /**
253
+ * Asynchronous ftruncate.
254
+ * @param fd
255
+ * @param len
256
+ * @param callback
257
+ */
258
+ export function ftruncate(fd: number, cb?: Callback): void;
259
+ export function ftruncate(fd: number, len?: number, cb?: Callback): void;
260
+ export function ftruncate(fd: number, lenOrCB?, cb: Callback = nop): void {
261
+ const length = typeof lenOrCB === 'number' ? lenOrCB : 0;
262
+ cb = typeof lenOrCB === 'function' ? lenOrCB : cb;
263
+ const file = fd2file(fd);
264
+ if (length < 0) {
265
+ throw new ApiError(ErrorCode.EINVAL);
266
+ }
267
+ file.truncate(length)
268
+ .then(() => cb())
269
+ .catch(cb);
270
+ }
271
+ ftruncate satisfies Omit<typeof Node.ftruncate, '__promisify__'>;
272
+
273
+ /**
274
+ * Asynchronous fsync.
275
+ * @param fd
276
+ * @param callback
277
+ */
278
+ export function fsync(fd: number, cb: Callback = nop): void {
279
+ fd2file(fd)
280
+ .sync()
281
+ .then(() => cb())
282
+ .catch(cb);
283
+ }
284
+ fsync satisfies Omit<typeof Node.fsync, '__promisify__'>;
285
+
286
+ /**
287
+ * Asynchronous fdatasync.
288
+ * @param fd
289
+ * @param callback
290
+ */
291
+ export function fdatasync(fd: number, cb: Callback = nop): void {
292
+ fd2file(fd)
293
+ .datasync()
294
+ .then(() => cb())
295
+ .catch(cb);
296
+ }
297
+ fdatasync satisfies Omit<typeof Node.fdatasync, '__promisify__'>;
298
+
299
+ /**
300
+ * Write buffer to the file specified by `fd`.
301
+ * Note that it is unsafe to use fs.write multiple times on the same file
302
+ * without waiting for the callback.
303
+ * @param fd
304
+ * @param buffer Uint8Array containing the data to write to
305
+ * the file.
306
+ * @param offset Offset in the buffer to start reading data from.
307
+ * @param length The amount of bytes to write to the file.
308
+ * @param position Offset from the beginning of the file where this
309
+ * data should be written. If position is null, the data will be written at
310
+ * the current position.
311
+ * @param callback The number specifies the number of bytes written into the file.
312
+ */
313
+ export function write(fd: number, buffer: Uint8Array, offset: number, length: number, cb?: Callback<[number, Uint8Array]>): void;
314
+ export function write(fd: number, buffer: Uint8Array, offset: number, length: number, position?: number, cb?: Callback<[number, Uint8Array]>): void;
315
+ export function write(fd: number, data: FileContents, cb?: Callback<[number, string]>): void;
316
+ export function write(fd: number, data: FileContents, position?: number, cb?: Callback<[number, string]>): void;
317
+ export function write(fd: number, data: FileContents, position: number | null, encoding: BufferEncoding, cb?: Callback<[number, string]>): void;
318
+ export function write(fd: number, data: FileContents, cbPosOff?, cbLenEnc?, cbPos?, cb: Callback<[number, Uint8Array]> | Callback<[number, string]> = nop): void {
319
+ let buffer: Buffer,
320
+ offset: number,
321
+ length: number,
322
+ position: number | null = null,
323
+ encoding: BufferEncoding;
324
+ const handle = new promises.FileHandle(fd);
325
+ if (typeof data === 'string') {
326
+ // Signature 1: (fd, string, [position?, [encoding?]], cb?)
327
+ encoding = 'utf8';
328
+ switch (typeof cbPosOff) {
329
+ case 'function':
330
+ // (fd, string, cb)
331
+ cb = cbPosOff;
332
+ break;
333
+ case 'number':
334
+ // (fd, string, position, encoding?, cb?)
335
+ position = cbPosOff;
336
+ encoding = <BufferEncoding>(typeof cbLenEnc === 'string' ? cbLenEnc : 'utf8');
337
+ cb = typeof cbPos === 'function' ? cbPos : cb;
338
+ break;
339
+ default:
340
+ // ...try to find the callback and get out of here!
341
+ cb = typeof cbLenEnc === 'function' ? cbLenEnc : typeof cbPos === 'function' ? cbPos : cb;
342
+ (<Callback<[number, Uint8Array | string]>>cb)(new ApiError(ErrorCode.EINVAL, 'Invalid arguments.'));
343
+ return;
344
+ }
345
+ buffer = Buffer.from(data);
346
+ offset = 0;
347
+ length = buffer.length;
348
+
349
+ const _cb = <Callback<[number, string]>>cb;
350
+
351
+ handle
352
+ .write(buffer, offset, length, position)
353
+ .then(({ bytesWritten }) => _cb(null, bytesWritten, buffer.toString(encoding)))
354
+ .catch(_cb);
355
+ } else {
356
+ // Signature 2: (fd, buffer, offset, length, position?, cb?)
357
+ buffer = Buffer.from(data);
358
+ offset = cbPosOff;
359
+ length = cbLenEnc;
360
+ position = typeof cbPos === 'number' ? cbPos : null;
361
+ const _cb = <Callback<[number, Uint8Array]>>(typeof cbPos === 'function' ? cbPos : cb);
362
+ handle
363
+ .write(buffer, offset, length, position)
364
+ .then(({ bytesWritten }) => _cb(null, bytesWritten, buffer))
365
+ .catch(_cb);
366
+ }
367
+ }
368
+ write satisfies Omit<typeof Node.write, '__promisify__'>;
369
+
370
+ /**
371
+ * Read data from the file specified by `fd`.
372
+ * @param buffer The buffer that the data will be
373
+ * written to.
374
+ * @param offset The offset within the buffer where writing will
375
+ * start.
376
+ * @param length An integer specifying the number of bytes to read.
377
+ * @param position An integer specifying where to begin reading from
378
+ * in the file. If position is null, data will be read from the current file
379
+ * position.
380
+ * @param callback The number is the number of bytes read
381
+ */
382
+ export function read(fd: number, buffer: Uint8Array, offset: number, length: number, position?: number, cb: Callback<[number, Uint8Array]> = nop): void {
383
+ new promises.FileHandle(fd)
384
+ .read(buffer, offset, length, position)
385
+ .then(({ bytesRead, buffer }) => cb(null, bytesRead, buffer))
386
+ .catch(cb);
387
+ }
388
+ read satisfies Omit<typeof Node.read, '__promisify__'>;
389
+
390
+ /**
391
+ * Asynchronous `fchown`.
392
+ * @param fd
393
+ * @param uid
394
+ * @param gid
395
+ * @param callback
396
+ */
397
+ export function fchown(fd: number, uid: number, gid: number, cb: Callback = nop): void {
398
+ new promises.FileHandle(fd)
399
+ .chown(uid, gid)
400
+ .then(() => cb())
401
+ .catch(cb);
402
+ }
403
+ fchown satisfies Omit<typeof Node.fchown, '__promisify__'>;
404
+
405
+ /**
406
+ * Asynchronous `fchmod`.
407
+ * @param fd
408
+ * @param mode
409
+ * @param callback
410
+ */
411
+ export function fchmod(fd: number, mode: string | number, cb: Callback): void {
412
+ new promises.FileHandle(fd)
413
+ .chmod(mode)
414
+ .then(() => cb())
415
+ .catch(cb);
416
+ }
417
+ fchmod satisfies Omit<typeof Node.fchmod, '__promisify__'>;
418
+
419
+ /**
420
+ * Change the file timestamps of a file referenced by the supplied file
421
+ * descriptor.
422
+ * @param fd
423
+ * @param atime
424
+ * @param mtime
425
+ * @param callback
426
+ */
427
+ export function futimes(fd: number, atime: number | Date, mtime: number | Date, cb: Callback = nop): void {
428
+ new promises.FileHandle(fd)
429
+ .utimes(atime, mtime)
430
+ .then(() => cb())
431
+ .catch(cb);
432
+ }
433
+ futimes satisfies Omit<typeof Node.futimes, '__promisify__'>;
434
+
435
+ /**
436
+ * Asynchronous `rmdir`.
437
+ * @param path
438
+ * @param callback
439
+ */
440
+ export function rmdir(path: PathLike, cb: Callback = nop): void {
441
+ promises
442
+ .rmdir(path)
443
+ .then(() => cb())
444
+ .catch(cb);
445
+ }
446
+ rmdir satisfies Omit<typeof Node.rmdir, '__promisify__'>;
447
+
448
+ /**
449
+ * Asynchronous `mkdir`.
450
+ * @param path
451
+ * @param mode defaults to `0777`
452
+ * @param callback
453
+ */
454
+ export function mkdir(path: PathLike, mode?: Node.Mode, cb: Callback = nop): void {
455
+ promises
456
+ .mkdir(path, mode)
457
+ .then(() => cb())
458
+ .catch(cb);
459
+ }
460
+ mkdir satisfies Omit<typeof Node.mkdir, '__promisify__'>;
461
+
462
+ /**
463
+ * Asynchronous `readdir`. Reads the contents of a directory.
464
+ * The callback gets two arguments `(err, files)` where `files` is an array of
465
+ * the names of the files in the directory excluding `'.'` and `'..'`.
466
+ * @param path
467
+ * @param callback
468
+ */
469
+ export function readdir(path: PathLike, cb: Callback<[string[]]>): void;
470
+ export function readdir(path: PathLike, options: { withFileTypes?: false }, cb: Callback<[string[]]>): void;
471
+ export function readdir(path: PathLike, options: { withFileTypes: true }, cb: Callback<[Dirent[]]>): void;
472
+ export function readdir(path: PathLike, _options: { withFileTypes?: boolean } | Callback<[string[]]>, cb: Callback<[string[]]> | Callback<[Dirent[]]> = nop): void {
473
+ cb = typeof _options == 'function' ? _options : cb;
474
+ const options = typeof _options != 'function' ? _options : {};
475
+ promises
476
+ .readdir(path, options as object)
477
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
478
+ .then(entries => cb(null, entries as any))
479
+ .catch(cb);
480
+ }
481
+ readdir satisfies Omit<typeof Node.readdir, '__promisify__'>;
482
+
483
+ /**
484
+ * Asynchronous `link`.
485
+ * @param existing
486
+ * @param newpath
487
+ * @param callback
488
+ */
489
+ export function link(existing: PathLike, newpath: PathLike, cb: Callback = nop): void {
490
+ promises
491
+ .link(existing, newpath)
492
+ .then(() => cb())
493
+ .catch(cb);
494
+ }
495
+ link satisfies Omit<typeof Node.link, '__promisify__'>;
496
+
497
+ /**
498
+ * Asynchronous `symlink`.
499
+ * @param target target path
500
+ * @param path link path
501
+ * @param type can be either `'dir'` or `'file'` (default is `'file'`)
502
+ * @param callback
503
+ */
504
+ export function symlink(target: PathLike, path: PathLike, cb?: Callback): void;
505
+ export function symlink(target: PathLike, path: PathLike, type?: Node.symlink.Type, cb?: Callback): void;
506
+ export function symlink(target: PathLike, path: PathLike, typeOrCB?: Node.symlink.Type | Callback, cb: Callback = nop): void {
507
+ const type = typeof typeOrCB === 'string' ? typeOrCB : 'file';
508
+ cb = typeof typeOrCB === 'function' ? typeOrCB : cb;
509
+ promises
510
+ .symlink(target, path, type)
511
+ .then(() => cb())
512
+ .catch(cb);
513
+ }
514
+ symlink satisfies Omit<typeof Node.symlink, '__promisify__'>;
515
+
516
+ /**
517
+ * Asynchronous readlink.
518
+ * @param path
519
+ * @param callback
520
+ */
521
+ export function readlink(path: PathLike, callback: Callback<[string]> & any): void;
522
+ export function readlink(path: PathLike, options: Node.BufferEncodingOption, callback: Callback<[Uint8Array]>): void;
523
+ export function readlink(path: PathLike, options: Node.EncodingOption, callback: Callback<[string | Uint8Array]>): void;
524
+ export function readlink(path: PathLike, options: Node.EncodingOption, callback: Callback<[string]>): void;
525
+ export function readlink(
526
+ path: PathLike,
527
+ options: Node.BufferEncodingOption | Node.EncodingOption | Callback<[string]>,
528
+ callback: Callback<[string]> | Callback<[Uint8Array]> = nop
529
+ ): void {
530
+ callback = typeof options == 'function' ? options : callback;
531
+ promises
532
+ .readlink(path)
533
+ .then(result => (<Callback<[string | Uint8Array]>>callback)(null, result))
534
+ .catch(callback);
535
+ }
536
+ readlink satisfies Omit<typeof Node.readlink, '__promisify__'>;
537
+
538
+ /**
539
+ * Asynchronous `chown`.
540
+ * @param path
541
+ * @param uid
542
+ * @param gid
543
+ * @param callback
544
+ */
545
+ export function chown(path: PathLike, uid: number, gid: number, cb: Callback = nop): void {
546
+ promises
547
+ .chown(path, uid, gid)
548
+ .then(() => cb())
549
+ .catch(cb);
550
+ }
551
+ chown satisfies Omit<typeof Node.chown, '__promisify__'>;
552
+
553
+ /**
554
+ * Asynchronous `lchown`.
555
+ * @param path
556
+ * @param uid
557
+ * @param gid
558
+ * @param callback
559
+ */
560
+ export function lchown(path: PathLike, uid: number, gid: number, cb: Callback = nop): void {
561
+ promises
562
+ .lchown(path, uid, gid)
563
+ .then(() => cb())
564
+ .catch(cb);
565
+ }
566
+ lchown satisfies Omit<typeof Node.lchown, '__promisify__'>;
567
+
568
+ /**
569
+ * Asynchronous `chmod`.
570
+ * @param path
571
+ * @param mode
572
+ * @param callback
573
+ */
574
+ export function chmod(path: PathLike, mode: number | string, cb: Callback = nop): void {
575
+ promises
576
+ .chmod(path, mode)
577
+ .then(() => cb())
578
+ .catch(cb);
579
+ }
580
+ chmod satisfies Omit<typeof Node.chmod, '__promisify__'>;
581
+
582
+ /**
583
+ * Asynchronous `lchmod`.
584
+ * @param path
585
+ * @param mode
586
+ * @param callback
587
+ */
588
+ export function lchmod(path: PathLike, mode: number | string, cb: Callback = nop): void {
589
+ promises
590
+ .lchmod(path, mode)
591
+ .then(() => cb())
592
+ .catch(cb);
593
+ }
594
+ lchmod satisfies Omit<typeof Node.lchmod, '__promisify__'>;
595
+
596
+ /**
597
+ * Change file timestamps of the file referenced by the supplied path.
598
+ * @param path
599
+ * @param atime
600
+ * @param mtime
601
+ * @param callback
602
+ */
603
+ export function utimes(path: PathLike, atime: number | Date, mtime: number | Date, cb: Callback = nop): void {
604
+ promises
605
+ .utimes(path, atime, mtime)
606
+ .then(() => cb())
607
+ .catch(cb);
608
+ }
609
+ utimes satisfies Omit<typeof Node.utimes, '__promisify__'>;
610
+
611
+ /**
612
+ * Change file timestamps of the file referenced by the supplied path.
613
+ * @param path
614
+ * @param atime
615
+ * @param mtime
616
+ * @param callback
617
+ */
618
+ export function lutimes(path: PathLike, atime: number | Date, mtime: number | Date, cb: Callback = nop): void {
619
+ promises
620
+ .lutimes(path, atime, mtime)
621
+ .then(() => cb())
622
+ .catch(cb);
623
+ }
624
+ lutimes satisfies Omit<typeof Node.lutimes, '__promisify__'>;
625
+
626
+ /**
627
+ * Asynchronous `realpath`. The callback gets two arguments
628
+ * `(err, resolvedPath)`. May use `process.cwd` to resolve relative paths.
629
+ *
630
+ * @param path
631
+ * @param callback
632
+ */
633
+ export function realpath(path: PathLike, cb?: Callback<[string]>): void;
634
+ export function realpath(path: PathLike, options: Node.EncodingOption, cb: Callback<[string]>): void;
635
+ export function realpath(path: PathLike, arg2?: Callback<[string]> | Node.EncodingOption, cb: Callback<[string]> = nop): void {
636
+ cb = typeof arg2 === 'function' ? arg2 : cb;
637
+ promises
638
+ .realpath(path, typeof arg2 === 'function' ? null : arg2)
639
+ .then(result => cb(null, result))
640
+ .catch(cb);
641
+ }
642
+ realpath satisfies Omit<typeof Node.realpath, '__promisify__' | 'native'>;
643
+
644
+ /**
645
+ * Asynchronous `access`.
646
+ * @param path
647
+ * @param mode
648
+ * @param callback
649
+ */
650
+ export function access(path: PathLike, cb: Callback): void;
651
+ export function access(path: PathLike, mode: number, cb: Callback): void;
652
+ export function access(path: PathLike, cbMode, cb: Callback = nop): void {
653
+ const mode = typeof cbMode === 'number' ? cbMode : R_OK;
654
+ cb = typeof cbMode === 'function' ? cbMode : cb;
655
+ promises
656
+ .access(path, typeof cbMode === 'function' ? null : cbMode)
657
+ .then(() => cb())
658
+ .catch(cb);
659
+ }
660
+ access satisfies Omit<typeof Node.access, '__promisify__'>;
661
+
662
+ /**
663
+ * @todo Implement
664
+ */
665
+ export function watchFile(filename: PathLike, listener: (curr: Stats, prev: Stats) => void): void;
666
+ export function watchFile(filename: PathLike, options: { persistent?: boolean; interval?: number }, listener: (curr: Stats, prev: Stats) => void): void;
667
+ export function watchFile(filename: PathLike, optsListener, listener: (curr: Stats, prev: Stats) => void = nop): void {
668
+ throw ApiError.With('ENOSYS', filename, 'watchFile');
669
+ }
670
+ watchFile satisfies Omit<typeof Node.watchFile, '__promisify__'>;
671
+
672
+ /**
673
+ * @todo Implement
674
+ */
675
+ export function unwatchFile(filename: PathLike, listener: (curr: Stats, prev: Stats) => void = nop): void {
676
+ throw ApiError.With('ENOSYS', filename, 'unwatchFile');
677
+ }
678
+ unwatchFile satisfies Omit<typeof Node.unwatchFile, '__promisify__'>;
679
+
680
+ /**
681
+ * @todo Implement
682
+ */
683
+ export function watch(filename: PathLike, listener?: (event: string, filename: string) => any): Node.FSWatcher;
684
+ export function watch(filename: PathLike, options: { persistent?: boolean }, listener?: (event: string, filename: string) => any): Node.FSWatcher;
685
+ export function watch(filename: PathLike, options, listener: (event: string, filename: string) => any = nop): Node.FSWatcher {
686
+ throw ApiError.With('ENOSYS', filename, 'watch');
687
+ }
688
+ watch satisfies Omit<typeof Node.watch, '__promisify__'>;
689
+
690
+ // From @types/node/fs (these types are not exported)
691
+ interface StreamOptions {
692
+ flags?: string;
693
+ encoding?: BufferEncoding;
694
+ fd?: number | promises.FileHandle;
695
+ mode?: number;
696
+ autoClose?: boolean;
697
+ emitClose?: boolean;
698
+ start?: number;
699
+ signal?: AbortSignal;
700
+ highWaterMark?: number;
701
+ }
702
+ interface FSImplementation {
703
+ open?: (...args) => unknown;
704
+ close?: (...args) => unknown;
705
+ }
706
+ interface ReadStreamOptions extends StreamOptions {
707
+ fs?: FSImplementation & {
708
+ read: (...args) => unknown;
709
+ };
710
+ end?: number;
711
+ }
712
+ interface WriteStreamOptions extends StreamOptions {
713
+ fs?: FSImplementation & {
714
+ write: (...args) => unknown;
715
+ writev?: (...args) => unknown;
716
+ };
717
+ flush?: boolean;
718
+ }
719
+
720
+ /**
721
+ * Opens a file in read mode and creates a Node.js-like ReadStream.
722
+ *
723
+ * @param path The path to the file to be opened.
724
+ * @param options Options for the ReadStream and file opening (e.g., `encoding`, `highWaterMark`, `mode`).
725
+ * @returns A ReadStream object for interacting with the file's contents.
726
+ */
727
+ export function createReadStream(path: PathLike, _options?: BufferEncoding | ReadStreamOptions): ReadStream {
728
+ const options = typeof _options == 'object' ? _options : { encoding: _options };
729
+ let handle: promises.FileHandle;
730
+ const stream = new ReadStream({
731
+ highWaterMark: options.highWaterMark || 64 * 1024,
732
+ encoding: options.encoding || 'utf8',
733
+ async read(size: number) {
734
+ try {
735
+ handle ||= await promises.open(path, 'r', options?.mode);
736
+ const result = await handle.read(new Uint8Array(size), 0, size, handle.file.position);
737
+ stream.push(!result.bytesRead ? null : result.buffer.slice(0, result.bytesRead));
738
+ handle.file.position += result.bytesRead;
739
+ if (!result.bytesRead) {
740
+ await handle.close();
741
+ }
742
+ } catch (error) {
743
+ await handle?.close();
744
+ stream.destroy(error);
745
+ }
746
+ },
747
+ destroy(error, callback) {
748
+ handle
749
+ ?.close()
750
+ .then(() => callback(error))
751
+ .catch(callback);
752
+ },
753
+ });
754
+
755
+ stream.path = path;
756
+ return stream;
757
+ }
758
+ createReadStream satisfies Omit<typeof Node.createReadStream, '__promisify__'>;
759
+
760
+ /**
761
+ * Opens a file in write mode and creates a Node.js-like WriteStream.
762
+ *
763
+ * @param path The path to the file to be opened.
764
+ * @param options Options for the WriteStream and file opening (e.g., `encoding`, `highWaterMark`, `mode`).
765
+ * @returns A WriteStream object for writing to the file.
766
+ */
767
+ export function createWriteStream(path: PathLike, _options?: BufferEncoding | WriteStreamOptions): WriteStream {
768
+ const options = typeof _options == 'object' ? _options : { encoding: _options };
769
+ let handle: promises.FileHandle;
770
+ const stream = new WriteStream({
771
+ highWaterMark: options?.highWaterMark,
772
+ async write(chunk: Uint8Array, encoding: BufferEncoding, callback: (error?: Error) => void) {
773
+ try {
774
+ handle ||= await promises.open(path, 'w', options?.mode || 0o666);
775
+ await handle.write(chunk, null, encoding);
776
+ callback(null);
777
+ } catch (error) {
778
+ await handle?.close();
779
+ callback(error);
780
+ }
781
+ },
782
+ destroy(error, callback) {
783
+ callback(error);
784
+ handle
785
+ ?.close()
786
+ .then(() => callback(error))
787
+ .catch(callback);
788
+ },
789
+ final(callback) {
790
+ handle
791
+ ?.close()
792
+ .then(() => callback())
793
+ .catch(callback);
794
+ },
795
+ });
796
+
797
+ stream.path = path;
798
+ return stream;
799
+ }
800
+ createWriteStream satisfies Omit<typeof Node.createWriteStream, '__promisify__'>;
801
+
802
+ export function rm(path: PathLike, callback: Callback): void;
803
+ export function rm(path: PathLike, options: Node.RmOptions, callback: Callback): void;
804
+ export function rm(path: PathLike, options: Node.RmOptions | Callback, callback: Callback = nop): void {
805
+ callback = typeof options === 'function' ? options : callback;
806
+ promises
807
+ .rm(path, typeof options === 'function' ? null : options)
808
+ .then(() => callback(null))
809
+ .catch(callback);
810
+ }
811
+ rm satisfies Omit<typeof Node.rm, '__promisify__'>;
812
+
813
+ /**
814
+ * Asynchronously creates a unique temporary directory.
815
+ * Generates six random characters to be appended behind a required prefix to create a unique temporary directory.
816
+ */
817
+ export function mkdtemp(prefix: string, callback: Callback<[string]>): void;
818
+ export function mkdtemp(prefix: string, options: Node.EncodingOption, callback: Callback<[string]>): void;
819
+ export function mkdtemp(prefix: string, options: Node.BufferEncodingOption, callback: Callback<[Buffer]>): void;
820
+ export function mkdtemp(
821
+ prefix: string,
822
+ options: Node.EncodingOption | Node.BufferEncodingOption | Callback<[string]>,
823
+ callback: Callback<[Buffer]> | Callback<[string]> = nop
824
+ ): void {
825
+ callback = typeof options === 'function' ? options : callback;
826
+ promises
827
+ .mkdtemp(prefix, typeof options != 'function' ? <Node.EncodingOption>options : null)
828
+ .then(result => (<Callback<[string | Buffer]>>callback)(null, result))
829
+ .catch(callback);
830
+ }
831
+ mkdtemp satisfies Omit<typeof Node.mkdtemp, '__promisify__'>;
832
+
833
+ export function copyFile(src: PathLike, dest: PathLike, callback: Callback): void;
834
+ export function copyFile(src: PathLike, dest: PathLike, flags: number, callback: Callback): void;
835
+ export function copyFile(src: PathLike, dest: PathLike, flags: number | Callback, callback?: Callback): void {
836
+ callback = typeof flags === 'function' ? flags : callback;
837
+ promises
838
+ .copyFile(src, dest, typeof flags === 'function' ? null : flags)
839
+ .then(() => callback(null))
840
+ .catch(callback);
841
+ }
842
+ copyFile satisfies Omit<typeof Node.copyFile, '__promisify__'>;
843
+
844
+ type readvCb = Callback<[number, NodeJS.ArrayBufferView[]]>;
845
+
846
+ export function readv(fd: number, buffers: NodeJS.ArrayBufferView[], cb: readvCb): void;
847
+ export function readv(fd: number, buffers: NodeJS.ArrayBufferView[], position: number, cb: readvCb): void;
848
+ export function readv(fd: number, buffers: NodeJS.ArrayBufferView[], position: number | readvCb, cb: readvCb = nop): void {
849
+ cb = typeof position === 'function' ? position : cb;
850
+ new promises.FileHandle(fd)
851
+ .readv(buffers, typeof position === 'function' ? null : position)
852
+ .then(({ buffers, bytesRead }) => cb(null, bytesRead, buffers))
853
+ .catch(cb);
854
+ }
855
+ readv satisfies Omit<typeof Node.readv, '__promisify__'>;
856
+
857
+ type writevCb = Callback<[number, NodeJS.ArrayBufferView[]]>;
858
+
859
+ export function writev(fd: number, buffers: Uint8Array[], cb: writevCb): void;
860
+ export function writev(fd: number, buffers: Uint8Array[], position: number, cb: writevCb): void;
861
+ export function writev(fd: number, buffers: Uint8Array[], position: number | writevCb, cb: writevCb = nop) {
862
+ cb = typeof position === 'function' ? position : cb;
863
+ new promises.FileHandle(fd)
864
+ .writev(buffers, typeof position === 'function' ? null : position)
865
+ .then(({ buffers, bytesWritten }) => cb(null, bytesWritten, buffers))
866
+ .catch(cb);
867
+ }
868
+ writev satisfies Omit<typeof Node.writev, '__promisify__'>;
869
+
870
+ export function opendir(path: PathLike, cb: Callback<[Dir]>): void;
871
+ export function opendir(path: PathLike, options: Node.OpenDirOptions, cb: Callback<[Dir]>): void;
872
+ export function opendir(path: PathLike, options: Node.OpenDirOptions | Callback<[Dir]>, cb: Callback<[Dir]> = nop): void {
873
+ cb = typeof options === 'function' ? options : cb;
874
+ promises
875
+ .opendir(path, typeof options === 'function' ? null : options)
876
+ .then(result => cb(null, result))
877
+ .catch(cb);
878
+ }
879
+ opendir satisfies Omit<typeof Node.opendir, '__promisify__'>;
880
+
881
+ export function cp(source: PathLike, destination: PathLike, callback: Callback): void;
882
+ export function cp(source: PathLike, destination: PathLike, opts: Node.CopyOptions, callback: Callback): void;
883
+ export function cp(source: PathLike, destination: PathLike, opts: Node.CopyOptions | Callback, callback?: Callback): void {
884
+ callback = typeof opts === 'function' ? opts : callback;
885
+ promises
886
+ .cp(source, destination, typeof opts === 'function' ? null : opts)
887
+ .then(() => callback(null))
888
+ .catch(callback);
889
+ }
890
+ cp satisfies Omit<typeof Node.cp, '__promisify__'>;
891
+
892
+ export function statfs(path: PathLike, callback: Callback<[StatsFs]>): void;
893
+ export function statfs(path: PathLike, options: Node.StatFsOptions & { bigint?: false }, callback: Callback<[StatsFs]>): void;
894
+ export function statfs(path: PathLike, options: Node.StatFsOptions & { bigint: true }, callback: Callback<[BigIntStatsFs]>): void;
895
+ export function statfs(path: PathLike, options?: Node.StatFsOptions | Callback<[StatsFs]>, callback: Callback<[StatsFs]> | Callback<[BigIntStatsFs]> = nop): void {
896
+ callback = typeof options === 'function' ? options : callback;
897
+ promises
898
+ .statfs(path, typeof options === 'function' ? null : options)
899
+ .then(result => (<Callback<[StatsFs | BigIntStatsFs]>>callback)(null, result))
900
+ .catch(callback);
901
+ }
902
+ statfs satisfies Omit<typeof Node.statfs, '__promisify__'>;
903
+
904
+ export async function openAsBlob(path: PathLike, options?: Node.OpenAsBlobOptions): Promise<Blob> {
905
+ const handle = await promises.open(path, 'r');
906
+ const buffer = await handle.readFile();
907
+ await handle.close();
908
+ return new Blob([buffer], options);
909
+ }
910
+ openAsBlob satisfies typeof Node.openAsBlob;