@zenfs/core 0.9.6 → 0.9.7

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 (56) hide show
  1. package/dist/ApiError.d.ts +4 -3
  2. package/dist/ApiError.js +1 -1
  3. package/dist/backends/AsyncStore.d.ts +3 -2
  4. package/dist/backends/AsyncStore.js +12 -5
  5. package/dist/backends/InMemory.d.ts +1 -1
  6. package/dist/backends/Index.d.ts +7 -10
  7. package/dist/backends/Index.js +7 -5
  8. package/dist/backends/Overlay.js +1 -1
  9. package/dist/backends/SyncStore.d.ts +6 -6
  10. package/dist/backends/SyncStore.js +4 -4
  11. package/dist/backends/backend.d.ts +5 -4
  12. package/dist/backends/backend.js +2 -2
  13. package/dist/browser.min.js +4 -4
  14. package/dist/browser.min.js.map +3 -3
  15. package/dist/config.d.ts +1 -1
  16. package/dist/config.js +2 -2
  17. package/dist/emulation/async.d.ts +76 -77
  18. package/dist/emulation/async.js +42 -42
  19. package/dist/emulation/dir.js +6 -5
  20. package/dist/emulation/promises.d.ts +106 -102
  21. package/dist/emulation/promises.js +61 -65
  22. package/dist/emulation/shared.d.ts +1 -7
  23. package/dist/emulation/shared.js +1 -1
  24. package/dist/emulation/streams.js +3 -2
  25. package/dist/emulation/sync.d.ts +71 -64
  26. package/dist/emulation/sync.js +39 -40
  27. package/dist/file.d.ts +4 -4
  28. package/dist/file.js +7 -5
  29. package/dist/filesystem.d.ts +1 -1
  30. package/dist/filesystem.js +3 -0
  31. package/dist/mutex.js +2 -2
  32. package/dist/stats.d.ts +7 -7
  33. package/dist/stats.js +50 -10
  34. package/dist/utils.d.ts +5 -5
  35. package/dist/utils.js +4 -3
  36. package/package.json +3 -3
  37. package/readme.md +2 -2
  38. package/src/ApiError.ts +3 -1
  39. package/src/backends/AsyncStore.ts +14 -8
  40. package/src/backends/Index.ts +14 -10
  41. package/src/backends/Overlay.ts +3 -3
  42. package/src/backends/SyncStore.ts +8 -8
  43. package/src/backends/backend.ts +7 -5
  44. package/src/config.ts +5 -5
  45. package/src/emulation/async.ts +188 -196
  46. package/src/emulation/dir.ts +6 -6
  47. package/src/emulation/promises.ts +181 -173
  48. package/src/emulation/shared.ts +2 -9
  49. package/src/emulation/streams.ts +9 -8
  50. package/src/emulation/sync.ts +159 -159
  51. package/src/file.ts +11 -9
  52. package/src/filesystem.ts +11 -7
  53. package/src/mutex.ts +3 -3
  54. package/src/stats.ts +32 -23
  55. package/src/utils.ts +10 -9
  56. package/tsconfig.json +2 -1
package/src/file.ts CHANGED
@@ -181,12 +181,12 @@ export abstract class File {
181
181
  /**
182
182
  * Get the current file position.
183
183
  */
184
- public abstract position?: number;
184
+ public abstract position: number;
185
185
 
186
186
  /**
187
187
  * The path to the file
188
188
  */
189
- public abstract readonly path?: string;
189
+ public abstract readonly path: string;
190
190
 
191
191
  /**
192
192
  * Asynchronous `stat`.
@@ -241,7 +241,7 @@ export abstract class File {
241
241
  * the current position.
242
242
  * @returns Promise resolving to the new length of the buffer
243
243
  */
244
- public abstract write(buffer: Uint8Array, offset?: number, length?: number, position?: number): Promise<number>;
244
+ public abstract write(buffer: Uint8Array, offset?: number, length?: number, position?: number | null): Promise<number>;
245
245
 
246
246
  /**
247
247
  * Write buffer to the file.
@@ -255,7 +255,7 @@ export abstract class File {
255
255
  * data should be written. If position is null, the data will be written at
256
256
  * the current position.
257
257
  */
258
- public abstract writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number): number;
258
+ public abstract writeSync(buffer: Uint8Array, offset?: number, length?: number, position?: number | null): number;
259
259
 
260
260
  /**
261
261
  * Read data from the file.
@@ -468,7 +468,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
468
468
  * Asynchronous truncate.
469
469
  * @param len
470
470
  */
471
- public truncate(len: number): Promise<void> {
471
+ public async truncate(len: number): Promise<void> {
472
472
  this.truncateSync(len);
473
473
  if (isSynchronous(this.flag)) {
474
474
  return this.sync();
@@ -515,7 +515,9 @@ export class PreloadFile<FS extends FileSystem> extends File {
515
515
  * the current position.
516
516
  */
517
517
  public async write(buffer: Uint8Array, offset: number = 0, length: number = this.stats.size, position: number = 0): Promise<number> {
518
- return this.writeSync(buffer, offset, length, position);
518
+ const bytesWritten = this.writeSync(buffer, offset, length, position);
519
+ await this.sync();
520
+ return bytesWritten;
519
521
  }
520
522
 
521
523
  /**
@@ -541,7 +543,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
541
543
  if (endFp > this.stats.size) {
542
544
  this.stats.size = endFp;
543
545
  if (endFp > this._buffer.byteLength) {
544
- if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength <= endFp) {
546
+ if (this._buffer.buffer.resizable && this._buffer.buffer.maxByteLength! <= endFp) {
545
547
  this._buffer.buffer.resize(endFp);
546
548
  } else {
547
549
  // Extend the buffer!
@@ -594,7 +596,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
594
596
  * position.
595
597
  * @returns number of bytes written
596
598
  */
597
- public readSync(buffer: ArrayBufferView, offset: number = 0, length: number = this.stats.size, position: number = 0): number {
599
+ public readSync(buffer: ArrayBufferView, offset: number = 0, length: number = this.stats.size, position?: number): number {
598
600
  if (!isReadable(this.flag)) {
599
601
  throw new ApiError(ErrorCode.EPERM, 'File not opened with a readable mode.');
600
602
  }
@@ -610,7 +612,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
610
612
  // No copy/read. Return immediatly for better performance
611
613
  return bytesRead;
612
614
  }
613
- new Uint8Array(buffer.buffer).set(this._buffer.slice(position, end), offset);
615
+ new Uint8Array(buffer.buffer, 0, length).set(this._buffer.slice(position, end), offset);
614
616
  return bytesRead;
615
617
  }
616
618
 
package/src/filesystem.ts CHANGED
@@ -5,7 +5,7 @@ import { join } from './emulation/path.js';
5
5
  import { PreloadFile, parseFlag, type File } from './file.js';
6
6
  import type { Stats } from './stats.js';
7
7
 
8
- export type FileContents = Uint8Array | string;
8
+ export type FileContents = ArrayBufferView | string;
9
9
 
10
10
  /**
11
11
  * Metadata about a FileSystem
@@ -218,7 +218,8 @@ declare abstract class SyncFileSystem extends FileSystem {
218
218
  /**
219
219
  * Implements the asynchronous API in terms of the synchronous API.
220
220
  */
221
- export function Sync<T extends abstract new (...args) => FileSystem>(FS: T): (abstract new (...args) => SyncFileSystem) & T {
221
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
222
+ export function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => SyncFileSystem) & T {
222
223
  abstract class _SyncFileSystem extends FS implements SyncFileSystem {
223
224
  public async exists(path: string, cred: Cred): Promise<boolean> {
224
225
  return this.existsSync(path, cred);
@@ -290,7 +291,8 @@ declare abstract class AsyncFileSystem extends FileSystem {
290
291
  syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
291
292
  }
292
293
 
293
- type AsyncMethods = ExtractProperties<FileSystem, (...args) => Promise<unknown>>;
294
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
295
+ type AsyncMethods = ExtractProperties<FileSystem, (...args: any[]) => Promise<unknown>>;
294
296
 
295
297
  /**
296
298
  * @internal
@@ -311,7 +313,8 @@ type AsyncOperation = {
311
313
  * the synchronous store, if desired.
312
314
  *
313
315
  */
314
- export function Async<T extends abstract new (...args) => FileSystem>(FS: T): (abstract new (...args) => AsyncFileSystem) & T {
316
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
317
+ export function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => AsyncFileSystem) & T {
315
318
  abstract class _AsyncFileSystem extends FS implements AsyncFileSystem {
316
319
  /**
317
320
  * Queue of pending asynchronous operations.
@@ -323,7 +326,7 @@ export function Async<T extends abstract new (...args) => FileSystem>(FS: T): (a
323
326
 
324
327
  public queueDone(): Promise<void> {
325
328
  return new Promise(resolve => {
326
- const check = () => (this._queueRunning ? setTimeout(check) : resolve());
329
+ const check = (): unknown => (this._queueRunning ? setTimeout(check) : resolve());
327
330
  check();
328
331
  });
329
332
  }
@@ -440,7 +443,7 @@ export function Async<T extends abstract new (...args) => FileSystem>(FS: T): (a
440
443
  return;
441
444
  }
442
445
 
443
- const [method, ...args] = this._queue.shift();
446
+ const [method, ...args] = this._queue.shift()!;
444
447
  // @ts-expect-error 2556 (since ...args is not correctly picked up as being a tuple)
445
448
  await this[method](...args);
446
449
  await this._next();
@@ -482,7 +485,8 @@ declare abstract class ReadonlyFileSystem extends FileSystem {
482
485
  /**
483
486
  * Implements the non-readonly methods to throw `EROFS`
484
487
  */
485
- export function Readonly<T extends abstract new (...args) => FileSystem>(FS: T): (abstract new (...args) => ReadonlyFileSystem) & T {
488
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
489
+ export function Readonly<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => ReadonlyFileSystem) & T {
486
490
  abstract class _ReadonlyFileSystem extends FS implements ReadonlyFileSystem {
487
491
  public metadata(): FileSystemMetadata {
488
492
  return { ...super.metadata(), readonly: true };
package/src/mutex.ts CHANGED
@@ -8,9 +8,9 @@ export class Mutex {
8
8
  public lock(path: string): Promise<void> {
9
9
  return new Promise(resolve => {
10
10
  if (this._locks.has(path)) {
11
- this._locks.get(path).push(resolve);
11
+ this._locks.get(path)!.push(resolve);
12
12
  } else {
13
- this._locks.set(path, []);
13
+ this._locks.set(path, [resolve]);
14
14
  }
15
15
  });
16
16
  }
@@ -20,7 +20,7 @@ export class Mutex {
20
20
  throw new Error('unlock of a non-locked mutex');
21
21
  }
22
22
 
23
- const next = this._locks.get(path).shift();
23
+ const next = this._locks.get(path)?.shift();
24
24
  /*
25
25
  don't unlock - we want to queue up next for the
26
26
  end of the current task execution, but we don't
package/src/stats.ts CHANGED
@@ -120,7 +120,7 @@ export abstract class StatsCommon<T extends number | bigint> implements Node.Sta
120
120
  /**
121
121
  * Some file systems stash data on stats objects.
122
122
  */
123
- public fileData?: Uint8Array = null;
123
+ public fileData?: Uint8Array;
124
124
 
125
125
  /**
126
126
  * time of last access, in milliseconds since epoch
@@ -185,15 +185,16 @@ export abstract class StatsCommon<T extends number | bigint> implements Node.Sta
185
185
  */
186
186
  constructor({ atimeMs, mtimeMs, ctimeMs, birthtimeMs, uid, gid, size, mode, ino }: Partial<StatsLike> = {}) {
187
187
  const currentTime = Date.now();
188
- const resolveT = (val: number | bigint, _default: number) => <T>(typeof val == this._typename ? val : this._convert(typeof val == this._typename_inverse ? val : _default));
188
+ const resolveT = (val: number | bigint | undefined, _default: number) =>
189
+ <T>(typeof val == this._typename ? val : this._convert(typeof val == this._typename_inverse ? val! : _default));
189
190
  this.atimeMs = resolveT(atimeMs, currentTime);
190
191
  this.mtimeMs = resolveT(mtimeMs, currentTime);
191
192
  this.ctimeMs = resolveT(ctimeMs, currentTime);
192
193
  this.birthtimeMs = resolveT(birthtimeMs, currentTime);
193
194
  this.uid = resolveT(uid, 0);
194
195
  this.gid = resolveT(gid, 0);
195
- this.size = this._convert(size);
196
- this.ino = this._convert(ino);
196
+ this.size = resolveT(size, 0);
197
+ this.ino = resolveT(ino, 0);
197
198
  const itemType: FileType = Number(mode) & S_IFMT || FileType.FILE;
198
199
 
199
200
  if (mode) {
@@ -312,6 +313,19 @@ export abstract class StatsCommon<T extends number | bigint> implements Node.Sta
312
313
  this.gid = this._convert(gid);
313
314
  }
314
315
  }
316
+
317
+ public get atimeNs(): bigint {
318
+ return BigInt(this.atimeMs);
319
+ }
320
+ public get mtimeNs(): bigint {
321
+ return BigInt(this.mtimeMs);
322
+ }
323
+ public get ctimeNs(): bigint {
324
+ return BigInt(this.ctimeMs);
325
+ }
326
+ public get birthtimeNs(): bigint {
327
+ return BigInt(this.birthtimeMs);
328
+ }
315
329
  }
316
330
 
317
331
  /**
@@ -341,11 +355,6 @@ Stats satisfies typeof Node.Stats;
341
355
  export class BigIntStats extends StatsCommon<bigint> implements Node.BigIntStats, StatsLike {
342
356
  protected _isBigint = true;
343
357
 
344
- public atimeNs: bigint;
345
- public mtimeNs: bigint;
346
- public ctimeNs: bigint;
347
- public birthtimeNs: bigint;
348
-
349
358
  /**
350
359
  * Clone a stats object.
351
360
  * @deprecated use `new BigIntStats(stats)`
@@ -357,34 +366,34 @@ export class BigIntStats extends StatsCommon<bigint> implements Node.BigIntStats
357
366
 
358
367
  export class StatsFs implements Node.StatsFsBase<number> {
359
368
  /** Type of file system. */
360
- public type: number;
369
+ public type: number = 0;
361
370
  /** Optimal transfer block size. */
362
- public bsize: number;
371
+ public bsize: number = 0;
363
372
  /** Total data blocks in file system. */
364
- public blocks: number;
373
+ public blocks: number = 0;
365
374
  /** Free blocks in file system. */
366
- public bfree: number;
375
+ public bfree: number = 0;
367
376
  /** Available blocks for unprivileged users */
368
- public bavail: number;
377
+ public bavail: number = 0;
369
378
  /** Total file nodes in file system. */
370
- public files: number;
379
+ public files: number = 0;
371
380
  /** Free file nodes in file system. */
372
- public ffree: number;
381
+ public ffree: number = 0;
373
382
  }
374
383
 
375
384
  export class BigIntStatsFs implements Node.StatsFsBase<bigint> {
376
385
  /** Type of file system. */
377
- public type: bigint;
386
+ public type: bigint = 0n;
378
387
  /** Optimal transfer block size. */
379
- public bsize: bigint;
388
+ public bsize: bigint = 0n;
380
389
  /** Total data blocks in file system. */
381
- public blocks: bigint;
390
+ public blocks: bigint = 0n;
382
391
  /** Free blocks in file system. */
383
- public bfree: bigint;
392
+ public bfree: bigint = 0n;
384
393
  /** Available blocks for unprivileged users */
385
- public bavail: bigint;
394
+ public bavail: bigint = 0n;
386
395
  /** Total file nodes in file system. */
387
- public files: bigint;
396
+ public files: bigint = 0n;
388
397
  /** Free file nodes in file system. */
389
- public ffree: bigint;
398
+ public ffree: bigint = 0n;
390
399
  }
package/src/utils.ts CHANGED
@@ -114,7 +114,7 @@ export function levenshtein(a: string, b: string): number {
114
114
  /**
115
115
  * @hidden
116
116
  */
117
- export const setImmediate = typeof globalThis.setImmediate == 'function' ? globalThis.setImmediate : cb => setTimeout(cb, 0);
117
+ export const setImmediate = typeof globalThis.setImmediate == 'function' ? globalThis.setImmediate : (cb: () => unknown) => setTimeout(cb, 0);
118
118
 
119
119
  /**
120
120
  * Encodes a string into a buffer
@@ -173,7 +173,7 @@ export function encodeDirListing(data: Record<string, bigint>): Uint8Array {
173
173
 
174
174
  export type Callback<Args extends unknown[] = []> = (e?: ApiError, ...args: OptionalTuple<Args>) => unknown;
175
175
 
176
- import type { EncodingOption, OpenMode, WriteFileOptions } from 'node:fs';
176
+ import type { EncodingOption, OpenMode, PathLike, WriteFileOptions } from 'node:fs';
177
177
 
178
178
  /**
179
179
  * converts Date or number to a integer UNIX timestamp
@@ -238,7 +238,8 @@ export function normalizeTime(time: string | number | Date): Date {
238
238
  * Normalizes a path
239
239
  * @internal
240
240
  */
241
- export function normalizePath(p: string): string {
241
+ export function normalizePath(p: PathLike): string {
242
+ p = p.toString();
242
243
  // Node doesn't allow null characters in paths.
243
244
  if (p.includes('\x00')) {
244
245
  throw new ApiError(ErrorCode.EINVAL, 'Path must be a string without null bytes.');
@@ -258,21 +259,21 @@ export function normalizePath(p: string): string {
258
259
  * @internal
259
260
  */
260
261
  export function normalizeOptions(
261
- options?: WriteFileOptions | (EncodingOption & { flag?: OpenMode }),
262
- encoding: BufferEncoding = 'utf8',
263
- flag?: string,
262
+ options: WriteFileOptions | (EncodingOption & { flag?: OpenMode }) | undefined,
263
+ encoding: BufferEncoding | null = 'utf8',
264
+ flag: string,
264
265
  mode: number = 0
265
- ): { encoding: BufferEncoding; flag: string; mode: number } {
266
+ ): { encoding?: BufferEncoding | null; flag: string; mode: number } {
266
267
  if (typeof options != 'object' || options === null) {
267
268
  return {
268
- encoding: typeof options == 'string' ? options : encoding,
269
+ encoding: typeof options == 'string' ? options : encoding ?? null,
269
270
  flag,
270
271
  mode,
271
272
  };
272
273
  }
273
274
 
274
275
  return {
275
- encoding: typeof options?.encoding == 'string' ? options.encoding : encoding,
276
+ encoding: typeof options?.encoding == 'string' ? options.encoding : encoding ?? null,
276
277
  flag: typeof options?.flag == 'string' ? options.flag : flag,
277
278
  mode: normalizeMode('mode' in options ? options?.mode : null, mode),
278
279
  };
package/tsconfig.json CHANGED
@@ -5,7 +5,8 @@
5
5
  "outDir": "dist",
6
6
  "lib": ["ESNext"],
7
7
  "moduleResolution": "NodeNext",
8
- "declaration": true
8
+ "declaration": true,
9
+ "strict": true
9
10
  },
10
11
  "include": ["src/**/*"],
11
12
  "exclude": ["node_modules"]