@zenfs/core 1.7.2 → 1.8.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 (62) 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 +7 -2
  8. package/dist/backends/overlay.js +32 -9
  9. package/dist/backends/passthrough.d.ts +4 -0
  10. package/dist/backends/passthrough.js +128 -0
  11. package/dist/backends/port/fs.d.ts +9 -44
  12. package/dist/backends/port/fs.js +93 -116
  13. package/dist/backends/port/rpc.d.ts +8 -5
  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 +55 -34
  18. package/dist/backends/store/fs.js +417 -233
  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 +11 -10
  28. package/dist/devices.js +15 -11
  29. package/dist/file.d.ts +111 -7
  30. package/dist/file.js +319 -71
  31. package/dist/filesystem.d.ts +22 -4
  32. package/dist/mixins/mutexed.d.ts +7 -2
  33. package/dist/mixins/mutexed.js +56 -0
  34. package/dist/mixins/sync.d.ts +1 -1
  35. package/dist/stats.d.ts +12 -6
  36. package/dist/stats.js +14 -6
  37. package/dist/utils.d.ts +17 -3
  38. package/dist/utils.js +32 -10
  39. package/dist/vfs/constants.d.ts +2 -2
  40. package/dist/vfs/constants.js +2 -2
  41. package/dist/vfs/dir.js +3 -1
  42. package/dist/vfs/index.js +4 -1
  43. package/dist/vfs/promises.js +31 -11
  44. package/dist/vfs/shared.js +2 -0
  45. package/dist/vfs/sync.js +25 -13
  46. package/dist/vfs/types.d.ts +15 -0
  47. package/package.json +2 -3
  48. package/readme.md +2 -2
  49. package/scripts/test.js +73 -11
  50. package/tests/common/mutex.test.ts +1 -1
  51. package/tests/fetch/run.sh +16 -0
  52. package/tests/fetch/server.ts +49 -0
  53. package/tests/fetch/setup.ts +13 -0
  54. package/tests/fs/read.test.ts +10 -10
  55. package/tests/fs/times.test.ts +2 -2
  56. package/tests/setup/index.ts +38 -0
  57. package/tests/setup/port.ts +15 -0
  58. package/dist/backends/file_index.d.ts +0 -63
  59. package/dist/backends/file_index.js +0 -163
  60. package/tests/common/async.test.ts +0 -31
  61. package/tests/setup/cow+fetch.ts +0 -45
  62. /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 type { FileReadResult } from './file.js';
2
+ import type { InodeLike } from './backends/index.js';
2
3
  import { InMemoryStore } from './backends/memory.js';
3
4
  import { StoreFS } from './backends/store/fs.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
@@ -18,7 +19,7 @@ export interface Device<TData = any> {
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.
@@ -55,7 +56,7 @@ export interface DeviceDriver<TData = any> {
55
56
  * Initializes a new device.
56
57
  * @returns `Device.data`
57
58
  */
58
- init?(ino: bigint, options: object): {
59
+ init?(ino: number, options: object): {
59
60
  data?: TData;
60
61
  minor?: number;
61
62
  major?: number;
@@ -94,11 +95,11 @@ export declare class DeviceFile<TData = any> extends File {
94
95
  position: number;
95
96
  constructor(fs: DeviceFS, path: string, device: Device<TData>);
96
97
  get driver(): DeviceDriver<TData>;
97
- protected get stats(): Partial<StatsLike>;
98
+ protected get stats(): Partial<InodeLike>;
98
99
  stat(): Promise<Stats>;
99
100
  statSync(): Stats;
100
101
  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>>;
102
+ read<TBuffer extends ArrayBufferView>(buffer: TBuffer, offset?: number, length?: number): Promise<FileReadResult<TBuffer>>;
102
103
  writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number): number;
103
104
  write(buffer: Uint8Array, offset?: number, length?: number, position?: number): Promise<number>;
104
105
  truncate(length: number): Promise<void>;
@@ -142,14 +143,14 @@ export declare class DeviceFS extends StoreFS<InMemoryStore> {
142
143
  statSync(path: string): Stats;
143
144
  openFile(path: string, flag: string): Promise<File>;
144
145
  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;
146
+ createFile(path: string, flag: string, mode: number, options: CreationOptions): Promise<File>;
147
+ createFileSync(path: string, flag: string, mode: number, options: CreationOptions): File;
147
148
  unlink(path: string): Promise<void>;
148
149
  unlinkSync(path: string): void;
149
150
  rmdir(path: string): Promise<void>;
150
151
  rmdirSync(path: string): void;
151
- mkdir(path: string, mode: number): Promise<void>;
152
- mkdirSync(path: string, mode: number): void;
152
+ mkdir(path: string, mode: number, options: CreationOptions): Promise<void>;
153
+ mkdirSync(path: string, mode: number, options: CreationOptions): void;
153
154
  readdir(path: string): Promise<string[]>;
154
155
  readdirSync(path: string): string[];
155
156
  link(target: string, link: string): Promise<void>;
package/dist/devices.js CHANGED
@@ -58,7 +58,7 @@ import { StoreFS } from './backends/store/fs.js';
58
58
  import { Errno, ErrnoError } from './error.js';
59
59
  import { File } from './file.js';
60
60
  import { Stats } from './stats.js';
61
- import { decodeUTF8 } from './utils.js';
61
+ import { canary, decodeUTF8 } from './utils.js';
62
62
  import { S_IFBLK, S_IFCHR } from './vfs/constants.js';
63
63
  import { basename, dirname } from './vfs/path.js';
64
64
  /**
@@ -159,14 +159,17 @@ export class DeviceFS extends StoreFS {
159
159
  * Creates a new device at `path` relative to the `DeviceFS` root.
160
160
  * @deprecated
161
161
  */
162
+ /* node:coverage disable */
162
163
  createDevice(path, driver, options = {}) {
163
164
  var _a;
164
165
  if (this.existsSync(path)) {
165
166
  throw ErrnoError.With('EEXIST', path, 'mknod');
166
167
  }
167
- let ino = BigInt(1);
168
+ let ino = 1;
169
+ const silence = canary(path, 'mknod');
168
170
  while (this.store.has(ino))
169
171
  ino++;
172
+ silence();
170
173
  const dev = {
171
174
  driver,
172
175
  ino,
@@ -178,6 +181,7 @@ export class DeviceFS extends StoreFS {
178
181
  this.devices.set(path, dev);
179
182
  return dev;
180
183
  }
184
+ /* node:coverage enable */
181
185
  devicesWithDriver(driver, forceIdentity) {
182
186
  if (forceIdentity && typeof driver == 'string') {
183
187
  throw new ErrnoError(Errno.EINVAL, 'Can not fetch devices using only a driver name');
@@ -197,7 +201,7 @@ export class DeviceFS extends StoreFS {
197
201
  */
198
202
  _createDevice(driver, options = {}) {
199
203
  var _a;
200
- let ino = BigInt(1);
204
+ let ino = 1;
201
205
  while (this.store.has(ino))
202
206
  ino++;
203
207
  const dev = {
@@ -295,17 +299,17 @@ export class DeviceFS extends StoreFS {
295
299
  }
296
300
  return super.openFileSync(path, flag);
297
301
  }
298
- async createFile(path, flag, mode) {
302
+ async createFile(path, flag, mode, options) {
299
303
  if (this.devices.has(path)) {
300
304
  throw ErrnoError.With('EEXIST', path, 'createFile');
301
305
  }
302
- return super.createFile(path, flag, mode);
306
+ return super.createFile(path, flag, mode, options);
303
307
  }
304
- createFileSync(path, flag, mode) {
308
+ createFileSync(path, flag, mode, options) {
305
309
  if (this.devices.has(path)) {
306
310
  throw ErrnoError.With('EEXIST', path, 'createFile');
307
311
  }
308
- return super.createFileSync(path, flag, mode);
312
+ return super.createFileSync(path, flag, mode, options);
309
313
  }
310
314
  async unlink(path) {
311
315
  if (this.devices.has(path)) {
@@ -325,17 +329,17 @@ export class DeviceFS extends StoreFS {
325
329
  rmdirSync(path) {
326
330
  return super.rmdirSync(path);
327
331
  }
328
- async mkdir(path, mode) {
332
+ async mkdir(path, mode, options) {
329
333
  if (this.devices.has(path)) {
330
334
  throw ErrnoError.With('EEXIST', path, 'mkdir');
331
335
  }
332
- return super.mkdir(path, mode);
336
+ return super.mkdir(path, mode, options);
333
337
  }
334
- mkdirSync(path, mode) {
338
+ mkdirSync(path, mode, options) {
335
339
  if (this.devices.has(path)) {
336
340
  throw ErrnoError.With('EEXIST', path, 'mkdir');
337
341
  }
338
- return super.mkdirSync(path, mode);
342
+ return super.mkdirSync(path, mode, options);
339
343
  }
340
344
  async readdir(path) {
341
345
  const entries = await super.readdir(path);
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
+ }