@zenfs/core 0.11.1 → 0.12.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 (48) hide show
  1. package/dist/backends/fetch.d.ts +20 -33
  2. package/dist/backends/fetch.js +48 -93
  3. package/dist/backends/index/fs.d.ts +49 -0
  4. package/dist/backends/index/fs.js +86 -0
  5. package/dist/backends/index/index.d.ts +37 -0
  6. package/dist/backends/index/index.js +82 -0
  7. package/dist/backends/locked.d.ts +1 -1
  8. package/dist/backends/locked.js +34 -34
  9. package/dist/backends/memory.d.ts +1 -1
  10. package/dist/backends/port/fs.d.ts +1 -1
  11. package/dist/backends/port/fs.js +2 -1
  12. package/dist/backends/port/rpc.js +3 -1
  13. package/dist/backends/store/fs.d.ts +5 -5
  14. package/dist/backends/store/fs.js +1 -1
  15. package/dist/browser.min.js +4 -4
  16. package/dist/browser.min.js.map +4 -4
  17. package/dist/emulation/promises.js +1 -2
  18. package/dist/emulation/sync.js +24 -40
  19. package/dist/file.d.ts +1 -1
  20. package/dist/file.js +2 -2
  21. package/dist/filesystem.d.ts +6 -6
  22. package/dist/filesystem.js +11 -10
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/mutex.d.ts +1 -1
  26. package/dist/mutex.js +11 -11
  27. package/dist/stats.d.ts +10 -10
  28. package/package.json +1 -1
  29. package/scripts/make-index.js +39 -24
  30. package/src/backends/fetch.ts +52 -110
  31. package/src/backends/index/fs.ts +113 -0
  32. package/src/backends/index/index.ts +98 -0
  33. package/src/backends/index/readme.md +3 -0
  34. package/src/backends/locked.ts +34 -34
  35. package/src/backends/memory.ts +1 -1
  36. package/src/backends/port/fs.ts +2 -1
  37. package/src/backends/port/rpc.ts +2 -1
  38. package/src/backends/store/fs.ts +5 -5
  39. package/src/emulation/promises.ts +1 -2
  40. package/src/emulation/sync.ts +23 -41
  41. package/src/file.ts +2 -2
  42. package/src/filesystem.ts +18 -17
  43. package/src/index.ts +1 -1
  44. package/src/mutex.ts +11 -11
  45. package/src/stats.ts +10 -10
  46. package/dist/backends/Index.d.ts +0 -204
  47. package/dist/backends/Index.js +0 -410
  48. package/src/backends/Index.ts +0 -504
@@ -85,10 +85,11 @@ export function request<const TRequest extends Request, TValue>(
85
85
  const id = Math.random().toString(16).slice(10);
86
86
  executors.set(id, { resolve, reject, fs });
87
87
  port.postMessage({ ...request, _zenfs: true, id, stack });
88
- setTimeout(() => {
88
+ const _ = setTimeout(() => {
89
89
  const error = new ErrnoError(Errno.EIO, 'RPC Failed');
90
90
  error.stack += stack;
91
91
  reject(error);
92
+ if (typeof _ == 'object') _.unref();
92
93
  }, timeout);
93
94
  });
94
95
  }
@@ -12,22 +12,22 @@ import type { Store, Transaction } from './store.js';
12
12
  const maxInodeAllocTries = 5;
13
13
 
14
14
  /**
15
- * A synchronous key-value file system. Uses a SyncStore to store the data.
15
+ * A file system which uses a key-value store.
16
16
  *
17
17
  * We use a unique ID for each node in the file system. The root node has a fixed ID.
18
18
  * @todo Introduce Node ID caching.
19
19
  * @todo Check modes.
20
20
  * @internal
21
21
  */
22
- export class StoreFS extends FileSystem {
23
- protected get store(): Store {
22
+ export class StoreFS<T extends Store = Store> extends FileSystem {
23
+ protected get store(): T {
24
24
  if (!this._store) {
25
25
  throw new ErrnoError(Errno.ENODATA, 'No store attached');
26
26
  }
27
27
  return this._store;
28
28
  }
29
29
 
30
- protected _store?: Store;
30
+ protected _store?: T;
31
31
 
32
32
  private _initialized: boolean = false;
33
33
 
@@ -40,7 +40,7 @@ export class StoreFS extends FileSystem {
40
40
  this._store = await this.$store;
41
41
  }
42
42
 
43
- constructor(private $store: Store | Promise<Store>) {
43
+ constructor(private $store: T | Promise<T>) {
44
44
  super();
45
45
 
46
46
  if (!($store instanceof Promise)) {
@@ -144,8 +144,7 @@ export class FileHandle implements promises.FileHandle {
144
144
  }
145
145
 
146
146
  const { size } = await this.stat();
147
- const data = new Uint8Array(size);
148
- await this.file.read(data, 0, size, 0);
147
+ const { buffer: data } = await this.file.read(new Uint8Array(size), 0, size, 0);
149
148
  const buffer = Buffer.from(data);
150
149
  return options.encoding ? buffer.toString(options.encoding) : buffer;
151
150
  }
@@ -16,7 +16,7 @@ type FileSystemMethod = {
16
16
  : never;
17
17
  }[keyof FileSystem]; // https://stackoverflow.com/a/76335220/17637456
18
18
 
19
- function doOp<M extends FileSystemMethod, RT extends ReturnType<M>>(...[name, resolveSymlinks, path, ...args]: Parameters<M>): RT {
19
+ function wrap<M extends FileSystemMethod, RT extends ReturnType<M>>(...[name, resolveSymlinks, path, ...args]: Parameters<M>): RT {
20
20
  path = normalizePath(path!);
21
21
  const { fs, path: resolvedPath } = resolveMount(resolveSymlinks && existsSync(path) ? realpathSync(path) : path);
22
22
  try {
@@ -78,7 +78,7 @@ existsSync satisfies typeof fs.existsSync;
78
78
  export function statSync(path: fs.PathLike, options?: { bigint?: boolean }): Stats;
79
79
  export function statSync(path: fs.PathLike, options: { bigint: true }): BigIntStats;
80
80
  export function statSync(path: fs.PathLike, options?: fs.StatOptions): Stats | BigIntStats {
81
- const stats: Stats = doOp('statSync', true, path.toString(), cred);
81
+ const stats: Stats = wrap('statSync', true, path.toString(), cred);
82
82
  return options?.bigint ? new BigIntStats(stats) : stats;
83
83
  }
84
84
  statSync satisfies typeof fs.statSync;
@@ -92,7 +92,7 @@ statSync satisfies typeof fs.statSync;
92
92
  export function lstatSync(path: fs.PathLike, options?: { bigint?: boolean }): Stats;
93
93
  export function lstatSync(path: fs.PathLike, options: { bigint: true }): BigIntStats;
94
94
  export function lstatSync(path: fs.PathLike, options?: fs.StatOptions): Stats | BigIntStats {
95
- const stats: Stats = doOp('statSync', false, path.toString(), cred);
95
+ const stats: Stats = wrap('statSync', false, path.toString(), cred);
96
96
  return options?.bigint ? new BigIntStats(stats) : stats;
97
97
  }
98
98
  lstatSync satisfies typeof fs.lstatSync;
@@ -117,7 +117,7 @@ truncateSync satisfies typeof fs.truncateSync;
117
117
  * @param path
118
118
  */
119
119
  export function unlinkSync(path: fs.PathLike): void {
120
- return doOp('unlinkSync', false, path.toString(), cred);
120
+ return wrap('unlinkSync', false, path.toString(), cred);
121
121
  }
122
122
  unlinkSync satisfies typeof fs.unlinkSync;
123
123
 
@@ -128,17 +128,17 @@ function _openSync(_path: fs.PathLike, _flag: fs.OpenMode, _mode?: fs.Mode | nul
128
128
  // Check if the path exists, and is a file.
129
129
  let stats: Stats;
130
130
  try {
131
- stats = doOp('statSync', resolveSymlinks, path, cred);
131
+ stats = wrap('statSync', resolveSymlinks, path, cred);
132
132
  } catch (e) {
133
133
  // File does not exist.
134
134
  switch (pathNotExistsAction(flag)) {
135
135
  case ActionType.CREATE:
136
136
  // Ensure parent exists.
137
- const parentStats: Stats = doOp('statSync', resolveSymlinks, dirname(path), cred);
137
+ const parentStats: Stats = wrap('statSync', resolveSymlinks, dirname(path), cred);
138
138
  if (!parentStats.isDirectory()) {
139
139
  throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
140
140
  }
141
- return doOp('createFileSync', resolveSymlinks, path, flag, mode, cred);
141
+ return wrap('createFileSync', resolveSymlinks, path, flag, mode, cred);
142
142
  case ActionType.THROW:
143
143
  throw ErrnoError.With('ENOENT', path, '_open');
144
144
  default:
@@ -155,16 +155,16 @@ function _openSync(_path: fs.PathLike, _flag: fs.OpenMode, _mode?: fs.Mode | nul
155
155
  throw ErrnoError.With('EEXIST', path, '_open');
156
156
  case ActionType.TRUNCATE:
157
157
  // Delete file.
158
- doOp('unlinkSync', resolveSymlinks, path, cred);
158
+ wrap('unlinkSync', resolveSymlinks, path, cred);
159
159
  /*
160
160
  Create file. Use the same mode as the old file.
161
161
  Node itself modifies the ctime when this occurs, so this action
162
162
  will preserve that behavior if the underlying file system
163
163
  supports those properties.
164
164
  */
165
- return doOp('createFileSync', resolveSymlinks, path, flag, stats.mode, cred);
165
+ return wrap('createFileSync', resolveSymlinks, path, flag, stats.mode, cred);
166
166
  case ActionType.NOP:
167
- return doOp('openFileSync', resolveSymlinks, path, flag, cred);
167
+ return wrap('openFileSync', resolveSymlinks, path, flag, cred);
168
168
  default:
169
169
  throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');
170
170
  }
@@ -230,21 +230,6 @@ export function readFileSync(path: fs.PathOrFileDescriptor, _options: fs.WriteFi
230
230
  }
231
231
  readFileSync satisfies typeof fs.readFileSync;
232
232
 
233
- /**
234
- * Synchronously writes data to a file, replacing the file
235
- * if it already exists.
236
- *
237
- * The encoding option is ignored if data is a buffer.
238
- */
239
- function _writeFileSync(fname: string, data: Uint8Array, flag: string, mode: number, resolveSymlinks: boolean): void {
240
- const file = _openSync(fname, flag, mode, resolveSymlinks);
241
- try {
242
- file.writeSync(data, 0, data.byteLength, 0);
243
- } finally {
244
- file.closeSync();
245
- }
246
- }
247
-
248
233
  /**
249
234
  * Synchronously writes data to a file, replacing the file if it already
250
235
  * exists.
@@ -272,22 +257,14 @@ export function writeFileSync(path: fs.PathOrFileDescriptor, data: FileContents,
272
257
  if (!encodedData) {
273
258
  throw new ErrnoError(Errno.EINVAL, 'Data not specified');
274
259
  }
275
- _writeFileSync(typeof path == 'number' ? fd2file(path).path! : path.toString(), encodedData, options.flag, options.mode, true);
276
- }
277
- writeFileSync satisfies typeof fs.writeFileSync;
278
-
279
- /**
280
- * Synchronously append data to a file, creating the file if
281
- * it not yet exists.
282
- */
283
- function _appendFileSync(fname: string, data: Uint8Array, flag: string, mode: number, resolveSymlinks: boolean): void {
284
- const file = _openSync(fname, flag, mode, resolveSymlinks);
260
+ const file = _openSync(typeof path == 'number' ? fd2file(path).path! : path.toString(), flag, options.mode, true);
285
261
  try {
286
- file.writeSync(data, 0, data.byteLength, null);
262
+ file.writeSync(encodedData, 0, encodedData.byteLength, 0);
287
263
  } finally {
288
264
  file.closeSync();
289
265
  }
290
266
  }
267
+ writeFileSync satisfies typeof fs.writeFileSync;
291
268
 
292
269
  /**
293
270
  * Asynchronously append data to a file, creating the file if it not yet
@@ -310,7 +287,12 @@ export function appendFileSync(filename: fs.PathOrFileDescriptor, data: FileCont
310
287
  throw new ErrnoError(Errno.EINVAL, 'Encoding not specified');
311
288
  }
312
289
  const encodedData = typeof data == 'string' ? Buffer.from(data, options.encoding!) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
313
- _appendFileSync(typeof filename == 'number' ? fd2file(filename).path! : filename.toString(), encodedData, options.flag, options.mode, true);
290
+ const file = _openSync(typeof filename == 'number' ? fd2file(filename).path! : filename.toString(), flag, options.mode, true);
291
+ try {
292
+ file.writeSync(encodedData, 0, encodedData.byteLength, null);
293
+ } finally {
294
+ file.closeSync();
295
+ }
314
296
  }
315
297
  appendFileSync satisfies typeof fs.appendFileSync;
316
298
 
@@ -481,7 +463,7 @@ futimesSync satisfies typeof fs.futimesSync;
481
463
  * @param path
482
464
  */
483
465
  export function rmdirSync(path: fs.PathLike): void {
484
- return doOp('rmdirSync', true, path.toString(), cred);
466
+ return wrap('rmdirSync', true, path.toString(), cred);
485
467
  }
486
468
  rmdirSync satisfies typeof fs.rmdirSync;
487
469
 
@@ -497,7 +479,7 @@ export function mkdirSync(path: fs.PathLike, options?: fs.Mode | fs.MakeDirector
497
479
  export function mkdirSync(path: fs.PathLike, options?: fs.Mode | fs.MakeDirectoryOptions | null): string | undefined | void {
498
480
  const mode: fs.Mode | undefined = typeof options == 'number' || typeof options == 'string' ? options : options?.mode;
499
481
  const recursive = typeof options == 'object' && options?.recursive;
500
- doOp('mkdirSync', true, path.toString(), normalizeMode(mode, 0o777), cred);
482
+ wrap('mkdirSync', true, path.toString(), normalizeMode(mode, 0o777), cred);
501
483
  }
502
484
  mkdirSync satisfies typeof fs.mkdirSync;
503
485
 
@@ -514,7 +496,7 @@ export function readdirSync(
514
496
  options?: { recursive?: boolean; encoding?: BufferEncoding | 'buffer' | null; withFileTypes?: boolean } | BufferEncoding | 'buffer' | null
515
497
  ): string[] | Dirent[] | Buffer[] {
516
498
  path = normalizePath(path);
517
- const entries: string[] = doOp('readdirSync', true, path, cred);
499
+ const entries: string[] = wrap('readdirSync', true, path, cred);
518
500
  for (const mount of mounts.keys()) {
519
501
  if (!mount.startsWith(path)) {
520
502
  continue;
@@ -549,7 +531,7 @@ readdirSync satisfies typeof fs.readdirSync;
549
531
  */
550
532
  export function linkSync(existing: fs.PathLike, newpath: fs.PathLike): void {
551
533
  newpath = normalizePath(newpath);
552
- return doOp('linkSync', false, existing.toString(), newpath.toString(), cred);
534
+ return wrap('linkSync', false, existing.toString(), newpath.toString(), cred);
553
535
  }
554
536
  linkSync satisfies typeof fs.linkSync;
555
537
 
package/src/file.ts CHANGED
@@ -701,8 +701,8 @@ export class PreloadFile<FS extends FileSystem> extends File {
701
701
  * For the filesystems which do not sync to anything..
702
702
  */
703
703
  export class NoSyncFile<T extends FileSystem> extends PreloadFile<T> {
704
- constructor(_fs: T, _path: string, _flag: string, _stat: Stats, contents?: Uint8Array) {
705
- super(_fs, _path, _flag, _stat, contents);
704
+ constructor(fs: T, path: string, flag: string, stats: Stats, contents?: Uint8Array) {
705
+ super(fs, path, flag, stats, contents);
706
706
  }
707
707
  /**
708
708
  * Asynchronous sync. Doesn't do anything, simply calls the cb.
package/src/filesystem.ts CHANGED
@@ -197,7 +197,7 @@ export abstract class FileSystem {
197
197
  /**
198
198
  * @internal
199
199
  */
200
- declare abstract class SyncFileSystem extends FileSystem {
200
+ declare abstract class SyncFS extends FileSystem {
201
201
  metadata(): FileSystemMetadata;
202
202
  ready(): Promise<void>;
203
203
  exists(path: string, cred: Cred): Promise<boolean>;
@@ -217,8 +217,8 @@ declare abstract class SyncFileSystem extends FileSystem {
217
217
  * Implements the asynchronous API in terms of the synchronous API.
218
218
  */
219
219
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
220
- export function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => SyncFileSystem) & T {
221
- abstract class _SyncFileSystem extends FS implements SyncFileSystem {
220
+ export function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => SyncFS) & T {
221
+ abstract class _SyncFS extends FS implements SyncFS {
222
222
  public async exists(path: string, cred: Cred): Promise<boolean> {
223
223
  return this.existsSync(path, cred);
224
224
  }
@@ -263,13 +263,13 @@ export function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS:
263
263
  return this.syncSync(path, data, stats);
264
264
  }
265
265
  }
266
- return _SyncFileSystem;
266
+ return _SyncFS;
267
267
  }
268
268
 
269
269
  /**
270
270
  * @internal
271
271
  */
272
- declare abstract class AsyncFileSystem extends FileSystem {
272
+ declare abstract class AsyncFS extends FileSystem {
273
273
  /**
274
274
  * @hidden
275
275
  */
@@ -312,8 +312,8 @@ type AsyncOperation = {
312
312
  *
313
313
  */
314
314
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
315
- export function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => AsyncFileSystem) & T {
316
- abstract class _AsyncFileSystem extends FS implements AsyncFileSystem {
315
+ export function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => AsyncFS) & T {
316
+ abstract class _AsyncFS extends FS implements AsyncFS {
317
317
  /**
318
318
  * Queue of pending asynchronous operations.
319
319
  */
@@ -359,18 +359,19 @@ export function Async<T extends abstract new (...args: any[]) => FileSystem>(FS:
359
359
  }
360
360
 
361
361
  public createFileSync(path: string, flag: string, mode: number, cred: Cred): PreloadFile<this> {
362
- const file = this._sync.createFileSync(path, flag, mode, cred);
362
+ this._sync.createFileSync(path, flag, mode, cred);
363
363
  this.queue('createFile', path, flag, mode, cred);
364
+ return this.openFileSync(path, flag, cred);
365
+ }
366
+
367
+ public openFileSync(path: string, flag: string, cred: Cred): PreloadFile<this> {
368
+ const file = this._sync.openFileSync(path, flag, cred);
364
369
  const stats = file.statSync();
365
370
  const buffer = new Uint8Array(stats.size);
366
371
  file.readSync(buffer);
367
372
  return new PreloadFile(this, path, flag, stats, buffer);
368
373
  }
369
374
 
370
- public openFileSync(path: string, flag: string, cred: Cred): File {
371
- return this._sync.openFileSync(path, flag, cred);
372
- }
373
-
374
375
  public unlinkSync(path: string, cred: Cred): void {
375
376
  this._sync.unlinkSync(path, cred);
376
377
  this.queue('unlink', path, cred);
@@ -455,13 +456,13 @@ export function Async<T extends abstract new (...args: any[]) => FileSystem>(FS:
455
456
  }
456
457
  }
457
458
 
458
- return _AsyncFileSystem;
459
+ return _AsyncFS;
459
460
  }
460
461
 
461
462
  /**
462
463
  * @internal
463
464
  */
464
- declare abstract class ReadonlyFileSystem extends FileSystem {
465
+ declare abstract class ReadonlyFS extends FileSystem {
465
466
  metadata(): FileSystemMetadata;
466
467
  rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
467
468
  renameSync(oldPath: string, newPath: string, cred: Cred): void;
@@ -483,8 +484,8 @@ declare abstract class ReadonlyFileSystem extends FileSystem {
483
484
  * Implements the non-readonly methods to throw `EROFS`
484
485
  */
485
486
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
486
- export function Readonly<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => ReadonlyFileSystem) & T {
487
- abstract class _ReadonlyFileSystem extends FS implements ReadonlyFileSystem {
487
+ export function Readonly<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => ReadonlyFS) & T {
488
+ abstract class _ReadonlyFS extends FS implements ReadonlyFS {
488
489
  public metadata(): FileSystemMetadata {
489
490
  return { ...super.metadata(), readonly: true };
490
491
  }
@@ -546,5 +547,5 @@ export function Readonly<T extends abstract new (...args: any[]) => FileSystem>(
546
547
  }
547
548
  /* eslint-enable @typescript-eslint/no-unused-vars */
548
549
  }
549
- return _ReadonlyFileSystem;
550
+ return _ReadonlyFS;
550
551
  }
package/src/index.ts CHANGED
@@ -2,7 +2,7 @@ export * from './error.js';
2
2
  export * from './backends/port/fs.js';
3
3
  export * from './backends/fetch.js';
4
4
  export * from './backends/memory.js';
5
- export * from './backends/Index.js';
5
+ export * from './backends/index/fs.js';
6
6
  export * from './backends/locked.js';
7
7
  export * from './backends/overlay.js';
8
8
  export * from './backends/store/fs.js';
package/src/mutex.ts CHANGED
@@ -5,24 +5,24 @@ import { ErrnoError, Errno } from './error.js';
5
5
  * @internal
6
6
  */
7
7
  export class Mutex {
8
- private _locks: Map<string, (() => void)[]> = new Map();
8
+ protected locks: Map<string, (() => void)[]> = new Map();
9
9
 
10
10
  public lock(path: string): Promise<void> {
11
11
  return new Promise(resolve => {
12
- if (this._locks.has(path)) {
13
- this._locks.get(path)!.push(resolve);
12
+ if (this.locks.has(path)) {
13
+ this.locks.get(path)!.push(resolve);
14
14
  } else {
15
- this._locks.set(path, [resolve]);
15
+ this.locks.set(path, [resolve]);
16
16
  }
17
17
  });
18
18
  }
19
19
 
20
20
  public unlock(path: string): void {
21
- if (!this._locks.has(path)) {
21
+ if (!this.locks.has(path)) {
22
22
  throw new ErrnoError(Errno.EPERM, 'Can not unlock an already unlocked path', path);
23
23
  }
24
24
 
25
- const next = this._locks.get(path)?.shift();
25
+ const next = this.locks.get(path)?.shift();
26
26
  /*
27
27
  don't unlock - we want to queue up next for the
28
28
  end of the current task execution, but we don't
@@ -32,23 +32,23 @@ export class Mutex {
32
32
  lock won't cause starvation.
33
33
  */
34
34
  if (next) {
35
- setTimeout(next, 0);
35
+ setTimeout(next);
36
36
  return;
37
37
  }
38
38
 
39
- this._locks.delete(path);
39
+ this.locks.delete(path);
40
40
  }
41
41
 
42
42
  public tryLock(path: string): boolean {
43
- if (this._locks.has(path)) {
43
+ if (this.locks.has(path)) {
44
44
  return false;
45
45
  }
46
46
 
47
- this._locks.set(path, []);
47
+ this.locks.set(path, []);
48
48
  return true;
49
49
  }
50
50
 
51
51
  public isLocked(path: string): boolean {
52
- return this._locks.has(path);
52
+ return this.locks.has(path);
53
53
  }
54
54
  }
package/src/stats.ts CHANGED
@@ -14,45 +14,45 @@ export enum FileType {
14
14
  /**
15
15
  *
16
16
  */
17
- export interface StatsLike {
17
+ export interface StatsLike<T extends number | bigint = number | bigint> {
18
18
  /**
19
19
  * Size of the item in bytes.
20
20
  * For directories/symlinks, this is normally the size of the struct that represents the item.
21
21
  */
22
- size: number | bigint;
22
+ size: T;
23
23
  /**
24
24
  * Unix-style file mode (e.g. 0o644) that includes the item type
25
25
  * Type of the item can be FILE, DIRECTORY, SYMLINK, or SOCKET
26
26
  */
27
- mode: number | bigint;
27
+ mode: T;
28
28
  /**
29
29
  * time of last access, in milliseconds since epoch
30
30
  */
31
- atimeMs: number | bigint;
31
+ atimeMs: T;
32
32
  /**
33
33
  * time of last modification, in milliseconds since epoch
34
34
  */
35
- mtimeMs: number | bigint;
35
+ mtimeMs: T;
36
36
  /**
37
37
  * time of last time file status was changed, in milliseconds since epoch
38
38
  */
39
- ctimeMs: number | bigint;
39
+ ctimeMs: T;
40
40
  /**
41
41
  * time of file creation, in milliseconds since epoch
42
42
  */
43
- birthtimeMs: number | bigint;
43
+ birthtimeMs: T;
44
44
  /**
45
45
  * the id of the user that owns the file
46
46
  */
47
- uid: number | bigint;
47
+ uid: T;
48
48
  /**
49
49
  * the id of the group that owns the file
50
50
  */
51
- gid: number | bigint;
51
+ gid: T;
52
52
  /**
53
53
  * the ino
54
54
  */
55
- ino: number | bigint;
55
+ ino: T;
56
56
  }
57
57
 
58
58
  /**