@zenfs/core 1.7.2 → 1.8.1

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 (68) hide show
  1. package/dist/backends/backend.js +3 -4
  2. package/dist/backends/fetch.d.ts +17 -18
  3. package/dist/backends/fetch.js +95 -58
  4. package/dist/backends/index.d.ts +2 -1
  5. package/dist/backends/index.js +2 -1
  6. package/dist/backends/memory.d.ts +1 -1
  7. package/dist/backends/overlay.d.ts +8 -14
  8. package/dist/backends/overlay.js +38 -31
  9. package/dist/backends/passthrough.d.ts +8 -3
  10. package/dist/backends/passthrough.js +148 -4
  11. package/dist/backends/port/fs.d.ts +15 -49
  12. package/dist/backends/port/fs.js +28 -116
  13. package/dist/backends/port/rpc.d.ts +13 -6
  14. package/dist/backends/port/rpc.js +9 -7
  15. package/dist/backends/store/file_index.d.ts +38 -0
  16. package/dist/backends/store/file_index.js +76 -0
  17. package/dist/backends/store/fs.d.ts +39 -34
  18. package/dist/backends/store/fs.js +407 -238
  19. package/dist/backends/store/index_fs.d.ts +34 -0
  20. package/dist/backends/store/index_fs.js +67 -0
  21. package/dist/backends/store/inode.d.ts +26 -8
  22. package/dist/backends/store/inode.js +92 -91
  23. package/dist/backends/store/simple.d.ts +20 -20
  24. package/dist/backends/store/simple.js +3 -4
  25. package/dist/backends/store/store.d.ts +12 -12
  26. package/dist/backends/store/store.js +4 -6
  27. package/dist/devices.d.ts +44 -21
  28. package/dist/devices.js +110 -55
  29. package/dist/file.d.ts +111 -7
  30. package/dist/file.js +324 -92
  31. package/dist/filesystem.d.ts +44 -4
  32. package/dist/mixins/async.js +12 -6
  33. package/dist/mixins/mutexed.d.ts +8 -3
  34. package/dist/mixins/mutexed.js +57 -1
  35. package/dist/mixins/readonly.d.ts +17 -16
  36. package/dist/mixins/readonly.js +6 -0
  37. package/dist/mixins/sync.d.ts +1 -1
  38. package/dist/stats.d.ts +12 -6
  39. package/dist/stats.js +14 -6
  40. package/dist/utils.d.ts +23 -3
  41. package/dist/utils.js +58 -10
  42. package/dist/vfs/async.js +1 -1
  43. package/dist/vfs/constants.d.ts +2 -2
  44. package/dist/vfs/constants.js +2 -2
  45. package/dist/vfs/dir.js +3 -1
  46. package/dist/vfs/index.js +4 -1
  47. package/dist/vfs/promises.js +33 -13
  48. package/dist/vfs/shared.js +2 -0
  49. package/dist/vfs/sync.js +25 -13
  50. package/dist/vfs/types.d.ts +15 -0
  51. package/eslint.shared.js +1 -0
  52. package/package.json +2 -3
  53. package/readme.md +2 -2
  54. package/scripts/test.js +73 -11
  55. package/tests/common/mutex.test.ts +1 -1
  56. package/tests/fetch/run.sh +16 -0
  57. package/tests/fetch/server.ts +49 -0
  58. package/tests/fetch/setup.ts +13 -0
  59. package/tests/fs/read.test.ts +10 -10
  60. package/tests/fs/times.test.ts +2 -2
  61. package/tests/fs/write.test.ts +6 -11
  62. package/tests/setup/index.ts +38 -0
  63. package/tests/setup/port.ts +15 -0
  64. package/dist/backends/file_index.d.ts +0 -63
  65. package/dist/backends/file_index.js +0 -163
  66. package/tests/common/async.test.ts +0 -31
  67. package/tests/setup/cow+fetch.ts +0 -45
  68. /package/tests/fs/{appendFile.test.ts → append.test.ts} +0 -0
package/dist/devices.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import type { FileReadResult } from 'node:fs/promises';
1
+ import { Inode } from './backends/index.js';
2
2
  import { InMemoryStore } from './backends/memory.js';
3
3
  import { StoreFS } from './backends/store/fs.js';
4
+ import type { FileReadResult } from './file.js';
4
5
  import { File } from './file.js';
5
- import type { StatsLike } from './stats.js';
6
+ import type { CreationOptions } from './filesystem.js';
6
7
  import { Stats } from './stats.js';
7
8
  /**
8
9
  * A device
@@ -14,11 +15,11 @@ export interface Device<TData = any> {
14
15
  /**
15
16
  * The device's driver
16
17
  */
17
- driver: DeviceDriver;
18
+ driver: DeviceDriver<TData>;
18
19
  /**
19
20
  * Which inode the device is assigned
20
21
  */
21
- ino: bigint;
22
+ ino: number;
22
23
  /**
23
24
  * Data associated with a device.
24
25
  * This is meant to be used by device drivers.
@@ -33,6 +34,12 @@ export interface Device<TData = any> {
33
34
  */
34
35
  minor: number;
35
36
  }
37
+ export interface DeviceInit<TData = any> {
38
+ data?: TData;
39
+ minor?: number;
40
+ major?: number;
41
+ name?: string;
42
+ }
36
43
  /**
37
44
  * A device driver
38
45
  */
@@ -55,22 +62,36 @@ export interface DeviceDriver<TData = any> {
55
62
  * Initializes a new device.
56
63
  * @returns `Device.data`
57
64
  */
58
- init?(ino: bigint, options: object): {
59
- data?: TData;
60
- minor?: number;
61
- major?: number;
62
- name?: string;
63
- };
65
+ init?(ino: number, options: object): DeviceInit<TData>;
64
66
  /**
65
- * Synchronously read from the device
67
+ * Synchronously read from a device file
66
68
  * @group File operations
69
+ * @deprecated
70
+ * @todo [BREAKING] Remove
67
71
  */
68
72
  read(file: DeviceFile<TData>, buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
69
73
  /**
70
- * Synchronously write to the device
74
+ * Synchronously read from a device.
75
+ * @privateRemarks
76
+ * For many devices there is no concept of an offset or end.
77
+ * For example, /dev/random will be "the same" regardless of where you read from- random data.
71
78
  * @group File operations
79
+ * @todo [BREAKING] Rename to `read`
80
+ */
81
+ readD(device: Device<TData>, buffer: Uint8Array, offset: number, end: number): void;
82
+ /**
83
+ * Synchronously write to a device file
84
+ * @group File operations
85
+ * @deprecated
86
+ * @todo [BREAKING] Remove
72
87
  */
73
88
  write(file: DeviceFile<TData>, buffer: Uint8Array, offset: number, length: number, position?: number): number;
89
+ /**
90
+ * Synchronously write to a device
91
+ * @group File operations
92
+ * @todo [BREAKING] Rename to `write`
93
+ */
94
+ writeD(device: Device<TData>, buffer: Uint8Array, offset: number): void;
74
95
  /**
75
96
  * Sync the device
76
97
  * @group File operations
@@ -94,11 +115,11 @@ export declare class DeviceFile<TData = any> extends File {
94
115
  position: number;
95
116
  constructor(fs: DeviceFS, path: string, device: Device<TData>);
96
117
  get driver(): DeviceDriver<TData>;
97
- protected get stats(): Partial<StatsLike>;
118
+ protected stats: Inode;
98
119
  stat(): Promise<Stats>;
99
120
  statSync(): Stats;
100
121
  readSync(buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
101
- read<TBuffer extends NodeJS.ArrayBufferView>(buffer: TBuffer, offset?: number, length?: number): Promise<FileReadResult<TBuffer>>;
122
+ read<TBuffer extends ArrayBufferView>(buffer: TBuffer, offset?: number, length?: number): Promise<FileReadResult<TBuffer>>;
102
123
  writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number): number;
103
124
  write(buffer: Uint8Array, offset?: number, length?: number, position?: number): Promise<number>;
104
125
  truncate(length: number): Promise<void>;
@@ -113,8 +134,6 @@ export declare class DeviceFile<TData = any> extends File {
113
134
  chmodSync(): void;
114
135
  utimes(): Promise<void>;
115
136
  utimesSync(): void;
116
- _setType(): Promise<void>;
117
- _setTypeSync(): void;
118
137
  }
119
138
  /**
120
139
  * A temporary file system that manages and interfaces with devices
@@ -142,20 +161,24 @@ export declare class DeviceFS extends StoreFS<InMemoryStore> {
142
161
  statSync(path: string): Stats;
143
162
  openFile(path: string, flag: string): Promise<File>;
144
163
  openFileSync(path: string, flag: string): File;
145
- createFile(path: string, flag: string, mode: number): Promise<File>;
146
- createFileSync(path: string, flag: string, mode: number): File;
164
+ createFile(path: string, flag: string, mode: number, options: CreationOptions): Promise<File>;
165
+ createFileSync(path: string, flag: string, mode: number, options: CreationOptions): File;
147
166
  unlink(path: string): Promise<void>;
148
167
  unlinkSync(path: string): void;
149
168
  rmdir(path: string): Promise<void>;
150
169
  rmdirSync(path: string): void;
151
- mkdir(path: string, mode: number): Promise<void>;
152
- mkdirSync(path: string, mode: number): void;
170
+ mkdir(path: string, mode: number, options: CreationOptions): Promise<void>;
171
+ mkdirSync(path: string, mode: number, options: CreationOptions): void;
153
172
  readdir(path: string): Promise<string[]>;
154
173
  readdirSync(path: string): string[];
155
174
  link(target: string, link: string): Promise<void>;
156
175
  linkSync(target: string, link: string): void;
157
176
  sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
158
177
  syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
178
+ read(path: string, buffer: Uint8Array, offset: number, end: number): Promise<void>;
179
+ readSync(path: string, buffer: Uint8Array, offset: number, end: number): void;
180
+ write(path: string, data: Uint8Array, offset: number): Promise<void>;
181
+ writeSync(path: string, data: Uint8Array, offset: number): void;
159
182
  }
160
183
  /**
161
184
  * Simulates the `/dev/null` device.
@@ -198,6 +221,6 @@ export declare const devices: {
198
221
  full: DeviceDriver<any>;
199
222
  random: DeviceDriver<any>;
200
223
  console: DeviceDriver<{
201
- output: (text: string) => unknown;
224
+ output: (text: string, offset: number) => unknown;
202
225
  }>;
203
226
  };
package/dist/devices.js CHANGED
@@ -53,12 +53,13 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
53
53
  var e = new Error(message);
54
54
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
55
55
  });
56
+ import { Inode } from './backends/index.js';
56
57
  import { InMemoryStore } from './backends/memory.js';
57
58
  import { StoreFS } from './backends/store/fs.js';
58
59
  import { Errno, ErrnoError } from './error.js';
59
60
  import { File } from './file.js';
60
61
  import { Stats } from './stats.js';
61
- import { decodeUTF8 } from './utils.js';
62
+ import { canary, decodeUTF8 } from './utils.js';
62
63
  import { S_IFBLK, S_IFCHR } from './vfs/constants.js';
63
64
  import { basename, dirname } from './vfs/path.js';
64
65
  /**
@@ -73,28 +74,40 @@ export class DeviceFile extends File {
73
74
  this.fs = fs;
74
75
  this.device = device;
75
76
  this.position = 0;
77
+ this.stats = new Inode({
78
+ mode: (this.driver.isBuffered ? S_IFBLK : S_IFCHR) | 0o666,
79
+ });
76
80
  }
77
81
  get driver() {
78
82
  return this.device.driver;
79
83
  }
80
- get stats() {
81
- return { mode: (this.driver.isBuffered ? S_IFBLK : S_IFCHR) | 0o666 };
82
- }
83
84
  async stat() {
84
85
  return Promise.resolve(new Stats(this.stats));
85
86
  }
86
87
  statSync() {
87
88
  return new Stats(this.stats);
88
89
  }
89
- readSync(buffer, offset, length, position) {
90
- return this.driver.read(this, buffer, offset, length, position);
90
+ readSync(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
91
+ this.stats.atimeMs = Date.now();
92
+ const end = position + length;
93
+ this.position = end;
94
+ const uint8 = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
95
+ this.driver.readD(this.device, uint8.subarray(offset, length), position, end);
96
+ return length;
91
97
  }
92
98
  // eslint-disable-next-line @typescript-eslint/require-await
93
99
  async read(buffer, offset, length) {
94
100
  return { bytesRead: this.readSync(buffer, offset, length), buffer };
95
101
  }
96
- writeSync(buffer, offset = 0, length = buffer.length, position) {
97
- return this.driver.write(this, buffer, offset, length, position);
102
+ writeSync(buffer, offset = 0, length = buffer.byteLength - offset, position = this.position) {
103
+ const end = position + length;
104
+ if (end > this.stats.size)
105
+ this.stats.size = end;
106
+ this.stats.mtimeMs = Date.now();
107
+ this.position = end;
108
+ const data = buffer.subarray(offset, offset + length);
109
+ this.driver.writeD(this.device, data, position);
110
+ return length;
98
111
  }
99
112
  // eslint-disable-next-line @typescript-eslint/require-await
100
113
  async write(buffer, offset, length, position) {
@@ -144,12 +157,6 @@ export class DeviceFile extends File {
144
157
  utimesSync() {
145
158
  throw ErrnoError.With('ENOTSUP', this.path, 'utimes');
146
159
  }
147
- _setType() {
148
- throw ErrnoError.With('ENOTSUP', this.path, '_setType');
149
- }
150
- _setTypeSync() {
151
- throw ErrnoError.With('ENOTSUP', this.path, '_setType');
152
- }
153
160
  }
154
161
  /**
155
162
  * A temporary file system that manages and interfaces with devices
@@ -159,14 +166,17 @@ export class DeviceFS extends StoreFS {
159
166
  * Creates a new device at `path` relative to the `DeviceFS` root.
160
167
  * @deprecated
161
168
  */
169
+ /* node:coverage disable */
162
170
  createDevice(path, driver, options = {}) {
163
171
  var _a;
164
172
  if (this.existsSync(path)) {
165
173
  throw ErrnoError.With('EEXIST', path, 'mknod');
166
174
  }
167
- let ino = BigInt(1);
175
+ let ino = 1;
176
+ const silence = canary(path, 'mknod');
168
177
  while (this.store.has(ino))
169
178
  ino++;
179
+ silence();
170
180
  const dev = {
171
181
  driver,
172
182
  ino,
@@ -178,6 +188,7 @@ export class DeviceFS extends StoreFS {
178
188
  this.devices.set(path, dev);
179
189
  return dev;
180
190
  }
191
+ /* node:coverage enable */
181
192
  devicesWithDriver(driver, forceIdentity) {
182
193
  if (forceIdentity && typeof driver == 'string') {
183
194
  throw new ErrnoError(Errno.EINVAL, 'Can not fetch devices using only a driver name');
@@ -197,7 +208,7 @@ export class DeviceFS extends StoreFS {
197
208
  */
198
209
  _createDevice(driver, options = {}) {
199
210
  var _a;
200
- let ino = BigInt(1);
211
+ let ino = 1;
201
212
  while (this.store.has(ino))
202
213
  ino++;
203
214
  const dev = {
@@ -295,17 +306,17 @@ export class DeviceFS extends StoreFS {
295
306
  }
296
307
  return super.openFileSync(path, flag);
297
308
  }
298
- async createFile(path, flag, mode) {
309
+ async createFile(path, flag, mode, options) {
299
310
  if (this.devices.has(path)) {
300
311
  throw ErrnoError.With('EEXIST', path, 'createFile');
301
312
  }
302
- return super.createFile(path, flag, mode);
313
+ return super.createFile(path, flag, mode, options);
303
314
  }
304
- createFileSync(path, flag, mode) {
315
+ createFileSync(path, flag, mode, options) {
305
316
  if (this.devices.has(path)) {
306
317
  throw ErrnoError.With('EEXIST', path, 'createFile');
307
318
  }
308
- return super.createFileSync(path, flag, mode);
319
+ return super.createFileSync(path, flag, mode, options);
309
320
  }
310
321
  async unlink(path) {
311
322
  if (this.devices.has(path)) {
@@ -325,17 +336,17 @@ export class DeviceFS extends StoreFS {
325
336
  rmdirSync(path) {
326
337
  return super.rmdirSync(path);
327
338
  }
328
- async mkdir(path, mode) {
339
+ async mkdir(path, mode, options) {
329
340
  if (this.devices.has(path)) {
330
341
  throw ErrnoError.With('EEXIST', path, 'mkdir');
331
342
  }
332
- return super.mkdir(path, mode);
343
+ return super.mkdir(path, mode, options);
333
344
  }
334
- mkdirSync(path, mode) {
345
+ mkdirSync(path, mode, options) {
335
346
  if (this.devices.has(path)) {
336
347
  throw ErrnoError.With('EEXIST', path, 'mkdir');
337
348
  }
338
- return super.mkdirSync(path, mode);
349
+ return super.mkdirSync(path, mode, options);
339
350
  }
340
351
  async readdir(path) {
341
352
  const entries = await super.readdir(path);
@@ -385,11 +396,56 @@ export class DeviceFS extends StoreFS {
385
396
  }
386
397
  return super.syncSync(path, data, stats);
387
398
  }
399
+ async read(path, buffer, offset, end) {
400
+ const device = this.devices.get(path);
401
+ if (!device) {
402
+ await super.read(path, buffer, offset, end);
403
+ return;
404
+ }
405
+ device.driver.readD(device, buffer, offset, end);
406
+ }
407
+ readSync(path, buffer, offset, end) {
408
+ const device = this.devices.get(path);
409
+ if (!device) {
410
+ super.readSync(path, buffer, offset, end);
411
+ return;
412
+ }
413
+ device.driver.readD(device, buffer, offset, end);
414
+ }
415
+ async write(path, data, offset) {
416
+ const device = this.devices.get(path);
417
+ if (!device) {
418
+ return await super.write(path, data, offset);
419
+ }
420
+ device.driver.writeD(device, data, offset);
421
+ }
422
+ writeSync(path, data, offset) {
423
+ const device = this.devices.get(path);
424
+ if (!device) {
425
+ return super.writeSync(path, data, offset);
426
+ }
427
+ device.driver.writeD(device, data, offset);
428
+ }
429
+ }
430
+ function defaultWrite(file, buffer, offset, length, position) {
431
+ return file.writeSync(buffer, offset, length, position);
388
432
  }
389
- function defaultWrite(file, buffer, offset, length) {
390
- file.position += length;
391
- return length;
433
+ function defaultWriteD(device, data, offset) {
434
+ return;
392
435
  }
436
+ function defaultRead(file, buffer, offset, length, position) {
437
+ return file.readSync(buffer, offset, length, position);
438
+ }
439
+ // 512 bytes.
440
+ const blockSize = 0x200;
441
+ function alloc(bytesNeeded, existing) {
442
+ const blocksNeeded = bytesNeeded / blockSize;
443
+ const currentBocks = existing ? existing.byteLength / blockSize : 0;
444
+ if (blocksNeeded <= currentBocks && existing)
445
+ return existing;
446
+ return new Uint8Array(Math.ceil(blocksNeeded));
447
+ }
448
+ const emptyBuffer = new Uint8Array();
393
449
  /**
394
450
  * Simulates the `/dev/null` device.
395
451
  * - Reads return 0 bytes (EOF).
@@ -405,7 +461,11 @@ export const nullDevice = {
405
461
  read() {
406
462
  return 0;
407
463
  },
464
+ readD() {
465
+ return emptyBuffer;
466
+ },
408
467
  write: defaultWrite,
468
+ writeD: defaultWriteD,
409
469
  };
410
470
  /**
411
471
  * Simulates the `/dev/zero` device
@@ -423,15 +483,12 @@ export const zeroDevice = {
423
483
  init() {
424
484
  return { major: 1, minor: 5 };
425
485
  },
426
- read(file, buffer, offset = 0, length = buffer.byteLength) {
427
- const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
428
- for (let i = offset; i < offset + length; i++) {
429
- data[i] = 0;
430
- }
431
- file.position += length;
432
- return length;
486
+ read: defaultRead,
487
+ readD(device, buffer, offset, end) {
488
+ buffer.fill(0, offset, end);
433
489
  },
434
490
  write: defaultWrite,
491
+ writeD: defaultWriteD,
435
492
  };
436
493
  /**
437
494
  * Simulates the `/dev/full` device.
@@ -445,17 +502,16 @@ export const fullDevice = {
445
502
  init() {
446
503
  return { major: 1, minor: 7 };
447
504
  },
448
- read(file, buffer, offset = 0, length = buffer.byteLength) {
449
- const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
450
- for (let i = offset; i < offset + length; i++) {
451
- data[i] = 0;
452
- }
453
- file.position += length;
454
- return length;
505
+ read: defaultRead,
506
+ readD(device, buffer, offset, end) {
507
+ buffer.fill(0, offset, end);
455
508
  },
456
509
  write(file) {
457
510
  throw ErrnoError.With('ENOSPC', file.path, 'write');
458
511
  },
512
+ writeD() {
513
+ throw ErrnoError.With('ENOSPC', undefined, 'write');
514
+ },
459
515
  };
460
516
  /**
461
517
  * Simulates the `/dev/random` device.
@@ -469,15 +525,14 @@ export const randomDevice = {
469
525
  init() {
470
526
  return { major: 1, minor: 8 };
471
527
  },
472
- read(file, buffer, offset = 0, length = buffer.byteLength) {
473
- const data = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength);
474
- for (let i = offset; i < offset + length; i++) {
475
- data[i] = Math.floor(Math.random() * 256);
528
+ read: defaultRead,
529
+ readD(device, buffer) {
530
+ for (let i = 0; i < buffer.length; i++) {
531
+ buffer[i] = Math.floor(Math.random() * 256);
476
532
  }
477
- file.position += length;
478
- return length;
479
533
  },
480
534
  write: defaultWrite,
535
+ writeD: defaultWriteD,
481
536
  };
482
537
  /**
483
538
  * Simulates the `/dev/console` device.
@@ -486,17 +541,17 @@ export const randomDevice = {
486
541
  const consoleDevice = {
487
542
  name: 'console',
488
543
  singleton: true,
489
- init(ino, { output = console.log } = {}) {
544
+ init(ino, { output = text => console.log(text) } = {}) {
490
545
  return { major: 5, minor: 1, data: { output } };
491
546
  },
492
- read() {
493
- return 0;
547
+ read: defaultRead,
548
+ readD() {
549
+ return emptyBuffer;
494
550
  },
495
- write(file, buffer, offset, length) {
496
- const text = decodeUTF8(buffer.slice(offset, offset + length));
497
- file.device.data.output(text);
498
- file.position += length;
499
- return length;
551
+ write: defaultWrite,
552
+ writeD(device, buffer, offset) {
553
+ const text = decodeUTF8(buffer);
554
+ device.data.output(text, offset);
500
555
  },
501
556
  };
502
557
  /**
package/dist/file.d.ts CHANGED
@@ -1,7 +1,6 @@
1
- import type { FileReadResult } from 'node:fs/promises';
2
1
  import type { FileSystem } from './filesystem.js';
3
2
  import './polyfills.js';
4
- import { Stats } from './stats.js';
3
+ import { Stats, type StatsLike } from './stats.js';
5
4
  export declare function parseFlag(flag: string | number): string;
6
5
  export declare function flagToString(flag: number): string;
7
6
  export declare function flagToNumber(flag: string): number;
@@ -16,6 +15,10 @@ export declare function isTruncating(flag: string): boolean;
16
15
  export declare function isAppendable(flag: string): boolean;
17
16
  export declare function isSynchronous(flag: string): boolean;
18
17
  export declare function isExclusive(flag: string): boolean;
18
+ export interface FileReadResult<T extends ArrayBufferView> {
19
+ bytesRead: number;
20
+ buffer: T;
21
+ }
19
22
  export declare abstract class File<FS extends FileSystem = FileSystem> {
20
23
  /**
21
24
  * @internal
@@ -71,7 +74,7 @@ export declare abstract class File<FS extends FileSystem = FileSystem> {
71
74
  * If position is null, data will be read from the current file position.
72
75
  * @returns Promise resolving to the new length of the buffer
73
76
  */
74
- abstract read<TBuffer extends NodeJS.ArrayBufferView>(buffer: TBuffer, offset?: number, length?: number, position?: number): Promise<FileReadResult<TBuffer>>;
77
+ abstract read<TBuffer extends ArrayBufferView>(buffer: TBuffer, offset?: number, length?: number, position?: number): Promise<FileReadResult<TBuffer>>;
75
78
  /**
76
79
  * Read data from the file.
77
80
  * @param buffer The buffer that the data will be written to.
@@ -96,11 +99,11 @@ export declare abstract class File<FS extends FileSystem = FileSystem> {
96
99
  /**
97
100
  * Change the file timestamps of the file.
98
101
  */
99
- abstract utimes(atime: Date, mtime: Date): Promise<void>;
102
+ abstract utimes(atime: number, mtime: number): Promise<void>;
100
103
  /**
101
104
  * Change the file timestamps of the file.
102
105
  */
103
- abstract utimesSync(atime: Date, mtime: Date): void;
106
+ abstract utimesSync(atime: number, mtime: number): void;
104
107
  }
105
108
  /**
106
109
  * An implementation of `File` that operates completely in-memory.
@@ -209,11 +212,12 @@ export declare class PreloadFile<FS extends FileSystem> extends File<FS> {
209
212
  chmodSync(mode: number): void;
210
213
  chown(uid: number, gid: number): Promise<void>;
211
214
  chownSync(uid: number, gid: number): void;
212
- utimes(atime: Date, mtime: Date): Promise<void>;
213
- utimesSync(atime: Date, mtime: Date): void;
215
+ utimes(atime: number, mtime: number): Promise<void>;
216
+ utimesSync(atime: number, mtime: number): void;
214
217
  }
215
218
  /**
216
219
  * For the file systems which do not sync to anything.
220
+ * @deprecated
217
221
  */
218
222
  export declare class NoSyncFile<T extends FileSystem> extends PreloadFile<T> {
219
223
  sync(): Promise<void>;
@@ -221,3 +225,103 @@ export declare class NoSyncFile<T extends FileSystem> extends PreloadFile<T> {
221
225
  close(): Promise<void>;
222
226
  closeSync(): void;
223
227
  }
228
+ /**
229
+ * An implementation of `File` that uses the FS
230
+ */
231
+ export declare class LazyFile<FS extends FileSystem> extends File<FS> {
232
+ readonly flag: string;
233
+ readonly stats: StatsLike<number>;
234
+ protected _buffer?: Uint8Array;
235
+ /**
236
+ * Current position
237
+ */
238
+ protected _position: number;
239
+ /**
240
+ * Get the current file position.
241
+ *
242
+ * We emulate the following bug mentioned in the Node documentation:
243
+ *
244
+ * On Linux, positional writes don't work when the file is opened in append mode.
245
+ * The kernel ignores the position argument and always appends the data to the end of the file.
246
+ * @returns The current file position.
247
+ */
248
+ get position(): number;
249
+ set position(value: number);
250
+ /**
251
+ * Whether the file has changes which have not been written to the FS
252
+ */
253
+ protected dirty: boolean;
254
+ /**
255
+ * Whether the file is open or closed
256
+ */
257
+ protected closed: boolean;
258
+ /**
259
+ * Creates a file with `path` and, optionally, the given contents.
260
+ * Note that, if contents is specified, it will be mutated by the file.
261
+ */
262
+ constructor(fs: FS, path: string, flag: string, stats: StatsLike<number>);
263
+ sync(): Promise<void>;
264
+ syncSync(): void;
265
+ close(): Promise<void>;
266
+ closeSync(): void;
267
+ /**
268
+ * Cleans up. This will *not* sync the file data to the FS
269
+ */
270
+ protected dispose(force?: boolean): void;
271
+ stat(): Promise<Stats>;
272
+ statSync(): Stats;
273
+ truncate(length: number): Promise<void>;
274
+ truncateSync(length: number): void;
275
+ protected prepareWrite(buffer: Uint8Array, offset: number, length: number, position: number): Uint8Array;
276
+ /**
277
+ * Write buffer to the file.
278
+ * @param buffer Uint8Array containing the data to write to the file.
279
+ * @param offset Offset in the buffer to start reading data from.
280
+ * @param length The amount of bytes to write to the file.
281
+ * @param position Offset from the beginning of the file where this data should be written.
282
+ * If position is null, the data will be written at the current position.
283
+ */
284
+ write(buffer: Uint8Array, offset?: number, length?: number, position?: number): Promise<number>;
285
+ /**
286
+ * Write buffer to the file.
287
+ * @param buffer Uint8Array containing the data to write to the file.
288
+ * @param offset Offset in the buffer to start reading data from.
289
+ * @param length The amount of bytes to write to the file.
290
+ * @param position Offset from the beginning of the file where this data should be written.
291
+ * If position is null, the data will be written at the current position.
292
+ * @returns bytes written
293
+ */
294
+ writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number): number;
295
+ /**
296
+ * Computes position information for reading
297
+ */
298
+ protected prepareRead(length: number, position: number): number;
299
+ /**
300
+ * Read data from the file.
301
+ * @param buffer The buffer that the data will be written to.
302
+ * @param offset The offset within the buffer where writing will start.
303
+ * @param length An integer specifying the number of bytes to read.
304
+ * @param position An integer specifying where to begin reading from in the file.
305
+ * If position is unset, data will be read from the current file position.
306
+ */
307
+ read<TBuffer extends ArrayBufferView>(buffer: TBuffer, offset?: number, length?: number, position?: number): Promise<{
308
+ bytesRead: number;
309
+ buffer: TBuffer;
310
+ }>;
311
+ /**
312
+ * Read data from the file.
313
+ * @param buffer The buffer that the data will be written to.
314
+ * @param offset The offset within the buffer where writing will start.
315
+ * @param length An integer specifying the number of bytes to read.
316
+ * @param position An integer specifying where to begin reading from in the file.
317
+ * If position is null, data will be read from the current file position.
318
+ * @returns number of bytes written
319
+ */
320
+ readSync(buffer: ArrayBufferView, offset?: number, length?: number, position?: number): number;
321
+ chmod(mode: number): Promise<void>;
322
+ chmodSync(mode: number): void;
323
+ chown(uid: number, gid: number): Promise<void>;
324
+ chownSync(uid: number, gid: number): void;
325
+ utimes(atime: number, mtime: number): Promise<void>;
326
+ utimesSync(atime: number, mtime: number): void;
327
+ }