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