@zenfs/core 0.12.1 → 0.12.2

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.
@@ -1,10 +1,13 @@
1
1
  // Utilities and shared data
2
2
 
3
- import { ErrnoError, Errno } from '../error.js';
3
+ import type { BigIntStatsFs, StatsFs } from 'node:fs';
4
4
  import { InMemory } from '../backends/memory.js';
5
5
  import { Cred, rootCred } from '../cred.js';
6
+ import { Errno, ErrnoError } from '../error.js';
6
7
  import type { File } from '../file.js';
7
8
  import { FileSystem } from '../filesystem.js';
9
+ import { size_max } from '../inode.js';
10
+ import { ZenFsType } from '../stats.js';
8
11
  import { normalizePath } from '../utils.js';
9
12
  import { resolve, type AbsolutePath } from './path.js';
10
13
 
@@ -117,3 +120,21 @@ export function mountObject(mounts: MountObject): void {
117
120
  mount(point, fs);
118
121
  }
119
122
  }
123
+
124
+ /**
125
+ * @hidden
126
+ */
127
+ export function _statfs<const T extends boolean>(fs: FileSystem, bigint?: T): T extends true ? BigIntStatsFs : StatsFs {
128
+ const md = fs.metadata();
129
+ const bs = md.blockSize || 4096;
130
+
131
+ return {
132
+ type: (bigint ? BigInt : Number)(md.type || ZenFsType),
133
+ bsize: (bigint ? BigInt : Number)(bs),
134
+ ffree: (bigint ? BigInt : Number)(md.freeNodes || size_max),
135
+ files: (bigint ? BigInt : Number)(md.totalNodes || size_max),
136
+ bavail: (bigint ? BigInt : Number)(md.freeSpace / bs),
137
+ bfree: (bigint ? BigInt : Number)(md.freeSpace / bs),
138
+ blocks: (bigint ? BigInt : Number)(md.totalSpace / bs),
139
+ } as T extends true ? BigIntStatsFs : StatsFs;
140
+ }
@@ -1,31 +1,14 @@
1
1
  import { Buffer } from 'buffer';
2
2
  import type * as fs from 'node:fs';
3
- import { ErrnoError, Errno } from '../error.js';
3
+ import { Errno, ErrnoError } from '../error.js';
4
4
  import { ActionType, File, isAppendable, isReadable, isWriteable, parseFlag, pathExistsAction, pathNotExistsAction } from '../file.js';
5
- import { FileContents, FileSystem } from '../filesystem.js';
6
- import { BigIntStats, FileType, type BigIntStatsFs, type Stats, type StatsFs } from '../stats.js';
5
+ import { FileContents } from '../filesystem.js';
6
+ import { BigIntStats, FileType, type Stats } from '../stats.js';
7
7
  import { normalizeMode, normalizeOptions, normalizePath, normalizeTime } from '../utils.js';
8
8
  import { COPYFILE_EXCL, F_OK, S_IFBLK, S_IFCHR, S_IFDIR, S_IFIFO, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK } from './constants.js';
9
9
  import { Dir, Dirent } from './dir.js';
10
10
  import { dirname, join, parse } from './path.js';
11
- import { cred, fd2file, fdMap, fixError, file2fd, mounts, resolveMount } from './shared.js';
12
-
13
- type FileSystemMethod = {
14
- [K in keyof FileSystem]: FileSystem[K] extends (...args: any[]) => unknown
15
- ? (name: K, resolveSymlinks: boolean, ...args: Parameters<FileSystem[K]>) => ReturnType<FileSystem[K]>
16
- : never;
17
- }[keyof FileSystem]; // https://stackoverflow.com/a/76335220/17637456
18
-
19
- function wrap<M extends FileSystemMethod, RT extends ReturnType<M>>(...[name, resolveSymlinks, path, ...args]: Parameters<M>): RT {
20
- path = normalizePath(path!);
21
- const { fs, path: resolvedPath } = resolveMount(resolveSymlinks && existsSync(path) ? realpathSync(path) : path);
22
- try {
23
- // @ts-expect-error 2556 (since ...args is not correctly picked up as being a tuple)
24
- return fs[name](resolvedPath, ...args) as RT;
25
- } catch (e) {
26
- throw fixError(e as Error, { [resolvedPath]: path });
27
- }
28
- }
11
+ import { _statfs, cred, fd2file, fdMap, file2fd, fixError, mounts, resolveMount } from './shared.js';
29
12
 
30
13
  /**
31
14
  * Synchronous rename.
@@ -78,8 +61,14 @@ existsSync satisfies typeof fs.existsSync;
78
61
  export function statSync(path: fs.PathLike, options?: { bigint?: boolean }): Stats;
79
62
  export function statSync(path: fs.PathLike, options: { bigint: true }): BigIntStats;
80
63
  export function statSync(path: fs.PathLike, options?: fs.StatOptions): Stats | BigIntStats {
81
- const stats: Stats = wrap('statSync', true, path.toString(), cred);
82
- return options?.bigint ? new BigIntStats(stats) : stats;
64
+ path = normalizePath(path);
65
+ const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
66
+ try {
67
+ const stats = fs.statSync(resolved, cred);
68
+ return options?.bigint ? new BigIntStats(stats) : stats;
69
+ } catch (e) {
70
+ throw fixError(e as Error, { [resolved]: path });
71
+ }
83
72
  }
84
73
  statSync satisfies typeof fs.statSync;
85
74
 
@@ -92,8 +81,14 @@ statSync satisfies typeof fs.statSync;
92
81
  export function lstatSync(path: fs.PathLike, options?: { bigint?: boolean }): Stats;
93
82
  export function lstatSync(path: fs.PathLike, options: { bigint: true }): BigIntStats;
94
83
  export function lstatSync(path: fs.PathLike, options?: fs.StatOptions): Stats | BigIntStats {
95
- const stats: Stats = wrap('statSync', false, path.toString(), cred);
96
- return options?.bigint ? new BigIntStats(stats) : stats;
84
+ path = normalizePath(path);
85
+ const { fs, path: resolved } = resolveMount(path);
86
+ try {
87
+ const stats = fs.statSync(resolved, cred);
88
+ return options?.bigint ? new BigIntStats(stats) : stats;
89
+ } catch (e) {
90
+ throw fixError(e as Error, { [resolved]: path });
91
+ }
97
92
  }
98
93
  lstatSync satisfies typeof fs.lstatSync;
99
94
 
@@ -117,45 +112,42 @@ truncateSync satisfies typeof fs.truncateSync;
117
112
  * @param path
118
113
  */
119
114
  export function unlinkSync(path: fs.PathLike): void {
120
- return wrap('unlinkSync', false, path.toString(), cred);
115
+ path = normalizePath(path);
116
+ const { fs, path: resolved } = resolveMount(path);
117
+ try {
118
+ return fs.unlinkSync(resolved, cred);
119
+ } catch (e) {
120
+ throw fixError(e as Error, { [resolved]: path });
121
+ }
121
122
  }
122
123
  unlinkSync satisfies typeof fs.unlinkSync;
123
124
 
124
- function _openSync(_path: fs.PathLike, _flag: fs.OpenMode, _mode?: fs.Mode | null, resolveSymlinks: boolean = true): File {
125
- const path = normalizePath(_path),
126
- mode = normalizeMode(_mode, 0o644),
125
+ function _openSync(path: fs.PathLike, _flag: fs.OpenMode, _mode?: fs.Mode | null, resolveSymlinks: boolean = true): File {
126
+ path = normalizePath(path);
127
+ const mode = normalizeMode(_mode, 0o644),
127
128
  flag = parseFlag(_flag);
128
- // Check if the path exists, and is a file.
129
- let stats: Stats;
130
- try {
131
- stats = wrap('statSync', resolveSymlinks, path, cred);
132
- } catch (_) {
133
- const original = _ as ErrnoError;
134
- if (original.code != 'ENOENT') {
135
- throw original;
136
- }
137
- try {
138
- // File does not exist.
139
- switch (pathNotExistsAction(flag)) {
140
- case ActionType.CREATE:
141
- // Ensure parent exists.
142
- const parentStats: Stats = wrap('statSync', resolveSymlinks, dirname(path), cred);
143
- if (!parentStats.isDirectory()) {
144
- throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
145
- }
146
- return wrap('createFileSync', resolveSymlinks, path, flag, mode, cred);
147
- case ActionType.THROW:
148
- throw ErrnoError.With('ENOENT', path, '_open');
149
- default:
150
- throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');
151
- }
152
- } catch (_) {
153
- const ex = _ as ErrnoError;
154
- ex.stack += '\n<original>\n';
155
- ex.stack += (original as Error).stack;
156
- throw ex;
129
+
130
+ path = resolveSymlinks && existsSync(path) ? realpathSync(path) : path;
131
+ const { fs, path: resolved } = resolveMount(path);
132
+
133
+ if (!fs.existsSync(resolved, cred)) {
134
+ switch (pathNotExistsAction(flag)) {
135
+ case ActionType.CREATE:
136
+ // Ensure parent exists.
137
+ const parentStats: Stats = fs.statSync(dirname(resolved), cred);
138
+ if (!parentStats.isDirectory()) {
139
+ throw ErrnoError.With('ENOTDIR', dirname(path), '_open');
140
+ }
141
+ return fs.createFileSync(resolved, flag, mode, cred);
142
+ case ActionType.THROW:
143
+ throw ErrnoError.With('ENOENT', path, '_open');
144
+ default:
145
+ throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');
157
146
  }
158
147
  }
148
+
149
+ const stats: Stats = fs.statSync(resolved, cred);
150
+
159
151
  if (!stats.hasAccess(mode, cred)) {
160
152
  throw ErrnoError.With('EACCES', path, '_open');
161
153
  }
@@ -166,16 +158,16 @@ function _openSync(_path: fs.PathLike, _flag: fs.OpenMode, _mode?: fs.Mode | nul
166
158
  throw ErrnoError.With('EEXIST', path, '_open');
167
159
  case ActionType.TRUNCATE:
168
160
  // Delete file.
169
- wrap('unlinkSync', resolveSymlinks, path, cred);
161
+ fs.unlinkSync(resolved, cred);
170
162
  /*
171
163
  Create file. Use the same mode as the old file.
172
164
  Node itself modifies the ctime when this occurs, so this action
173
165
  will preserve that behavior if the underlying file system
174
166
  supports those properties.
175
167
  */
176
- return wrap('createFileSync', resolveSymlinks, path, flag, stats.mode, cred);
168
+ return fs.createFileSync(resolved, flag, stats.mode, cred);
177
169
  case ActionType.NOP:
178
- return wrap('openFileSync', resolveSymlinks, path, flag, cred);
170
+ return fs.openFileSync(resolved, flag, cred);
179
171
  default:
180
172
  throw new ErrnoError(Errno.EINVAL, 'Invalid FileFlag object.');
181
173
  }
@@ -474,7 +466,13 @@ futimesSync satisfies typeof fs.futimesSync;
474
466
  * @param path
475
467
  */
476
468
  export function rmdirSync(path: fs.PathLike): void {
477
- return wrap('rmdirSync', true, path.toString(), cred);
469
+ path = normalizePath(path);
470
+ const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
471
+ try {
472
+ fs.rmdirSync(resolved, cred);
473
+ } catch (e) {
474
+ throw fixError(e as Error, { [resolved]: path });
475
+ }
478
476
  }
479
477
  rmdirSync satisfies typeof fs.rmdirSync;
480
478
 
@@ -488,9 +486,15 @@ export function mkdirSync(path: fs.PathLike, options: fs.MakeDirectoryOptions &
488
486
  export function mkdirSync(path: fs.PathLike, options?: fs.Mode | (fs.MakeDirectoryOptions & { recursive?: false }) | null): void;
489
487
  export function mkdirSync(path: fs.PathLike, options?: fs.Mode | fs.MakeDirectoryOptions | null): string | undefined;
490
488
  export function mkdirSync(path: fs.PathLike, options?: fs.Mode | fs.MakeDirectoryOptions | null): string | undefined | void {
491
- const mode: fs.Mode | undefined = typeof options == 'number' || typeof options == 'string' ? options : options?.mode;
489
+ const mode: fs.Mode = normalizeMode(typeof options == 'number' || typeof options == 'string' ? options : options?.mode, 0o777);
492
490
  const recursive = typeof options == 'object' && options?.recursive;
493
- wrap('mkdirSync', true, path.toString(), normalizeMode(mode, 0o777), cred);
491
+ path = normalizePath(path);
492
+ const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
493
+ try {
494
+ return fs.mkdirSync(resolved, mode, cred);
495
+ } catch (e) {
496
+ throw fixError(e as Error, { [resolved]: path });
497
+ }
494
498
  }
495
499
  mkdirSync satisfies typeof fs.mkdirSync;
496
500
 
@@ -507,7 +511,13 @@ export function readdirSync(
507
511
  options?: { recursive?: boolean; encoding?: BufferEncoding | 'buffer' | null; withFileTypes?: boolean } | BufferEncoding | 'buffer' | null
508
512
  ): string[] | Dirent[] | Buffer[] {
509
513
  path = normalizePath(path);
510
- const entries: string[] = wrap('readdirSync', true, path, cred);
514
+ const { fs, path: resolved } = resolveMount(existsSync(path) ? realpathSync(path) : path);
515
+ let entries: string[];
516
+ try {
517
+ entries = fs.readdirSync(resolved, cred);
518
+ } catch (e) {
519
+ throw fixError(e as Error, { [resolved]: path });
520
+ }
511
521
  for (const mount of mounts.keys()) {
512
522
  if (!mount.startsWith(path)) {
513
523
  continue;
@@ -541,8 +551,14 @@ readdirSync satisfies typeof fs.readdirSync;
541
551
  * @param newpath
542
552
  */
543
553
  export function linkSync(existing: fs.PathLike, newpath: fs.PathLike): void {
554
+ existing = normalizePath(existing);
544
555
  newpath = normalizePath(newpath);
545
- return wrap('linkSync', false, existing.toString(), newpath.toString(), cred);
556
+ const { fs, path: resolved } = resolveMount(existing);
557
+ try {
558
+ return fs.linkSync(resolved, newpath, cred);
559
+ } catch (e) {
560
+ throw fixError(e as Error, { [resolved]: existing });
561
+ }
546
562
  }
547
563
  linkSync satisfies typeof fs.linkSync;
548
564
 
@@ -883,9 +899,11 @@ cpSync satisfies typeof fs.cpSync;
883
899
  * @param path A path to an existing file or directory on the file system to be queried.
884
900
  * @param callback
885
901
  */
886
- export function statfsSync(path: fs.PathLike, options?: fs.StatFsOptions & { bigint?: false }): StatsFs;
887
- export function statfsSync(path: fs.PathLike, options: fs.StatFsOptions & { bigint: true }): BigIntStatsFs;
888
- export function statfsSync(path: fs.PathLike, options?: fs.StatFsOptions): StatsFs | BigIntStatsFs;
889
- export function statfsSync(path: fs.PathLike, options?: fs.StatFsOptions): StatsFs | BigIntStatsFs {
890
- throw ErrnoError.With('ENOSYS', path.toString(), 'statfs');
902
+ export function statfsSync(path: fs.PathLike, options?: fs.StatFsOptions & { bigint?: false }): fs.StatsFs;
903
+ export function statfsSync(path: fs.PathLike, options: fs.StatFsOptions & { bigint: true }): fs.BigIntStatsFs;
904
+ export function statfsSync(path: fs.PathLike, options?: fs.StatFsOptions): fs.StatsFs | fs.BigIntStatsFs;
905
+ export function statfsSync(path: fs.PathLike, options?: fs.StatFsOptions): fs.StatsFs | fs.BigIntStatsFs {
906
+ path = normalizePath(path);
907
+ const { fs } = resolveMount(path);
908
+ return _statfs(fs, options?.bigint);
891
909
  }
package/src/file.ts CHANGED
@@ -359,7 +359,7 @@ export abstract class File {
359
359
  */
360
360
  export class PreloadFile<FS extends FileSystem> extends File {
361
361
  protected _position: number = 0;
362
- protected _dirty: boolean = false;
362
+ protected dirty: boolean = false;
363
363
  /**
364
364
  * Creates a file with the given path and, optionally, the given contents. Note
365
365
  * that, if contents is specified, it will be mutated by the file!
@@ -400,7 +400,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
400
400
  throw new Error(`Size mismatch: buffer length ${_buffer.byteLength}, stats size ${this.stats.size}`);
401
401
  }
402
402
 
403
- this._dirty = true;
403
+ this.dirty = true;
404
404
  }
405
405
 
406
406
  /**
@@ -435,19 +435,19 @@ export class PreloadFile<FS extends FileSystem> extends File {
435
435
  }
436
436
 
437
437
  public async sync(): Promise<void> {
438
- if (!this.isDirty()) {
438
+ if (!this.dirty) {
439
439
  return;
440
440
  }
441
441
  await this.fs.sync(this.path, this._buffer, this.stats);
442
- this._dirty = false;
442
+ this.dirty = false;
443
443
  }
444
444
 
445
445
  public syncSync(): void {
446
- if (!this.isDirty()) {
446
+ if (!this.dirty) {
447
447
  return;
448
448
  }
449
449
  this.fs.syncSync(this.path, this._buffer, this.stats);
450
- this._dirty = false;
450
+ this.dirty = false;
451
451
  }
452
452
 
453
453
  public async close(): Promise<void> {
@@ -474,40 +474,33 @@ export class PreloadFile<FS extends FileSystem> extends File {
474
474
 
475
475
  /**
476
476
  * Asynchronous truncate.
477
- * @param len
477
+ * @param length
478
478
  */
479
- public async truncate(len: number): Promise<void> {
480
- this.truncateSync(len);
481
- if (isSynchronous(this.flag)) {
482
- return this.sync();
483
- }
479
+ public async truncate(length: number): Promise<void> {
480
+ this.truncateSync(length);
481
+ return this.sync();
484
482
  }
485
483
 
486
484
  /**
487
485
  * Synchronous truncate.
488
- * @param len
486
+ * @param length
489
487
  */
490
- public truncateSync(len: number): void {
491
- this._dirty = true;
488
+ public truncateSync(length: number): void {
489
+ this.dirty = true;
492
490
  if (!isWriteable(this.flag)) {
493
491
  throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
494
492
  }
495
493
  this.stats.mtimeMs = Date.now();
496
- if (len > this._buffer.length) {
497
- const buf = new Uint8Array(len - this._buffer.length);
498
- // Write will set stats.size for us.
499
- this.writeSync(buf, 0, buf.length, this._buffer.length);
500
- if (isSynchronous(this.flag)) {
501
- this.syncSync();
502
- }
494
+ if (length > this._buffer.length) {
495
+ const data = new Uint8Array(length - this._buffer.length);
496
+ // Write will set stats.size and handle syncing.
497
+ this.writeSync(data, 0, data.length, this._buffer.length);
503
498
  return;
504
499
  }
505
- this.stats.size = len;
506
- // Truncate buffer to 'len'.
507
- this._buffer = this._buffer.subarray(0, len);
508
- if (isSynchronous(this.flag)) {
509
- this.syncSync();
510
- }
500
+ this.stats.size = length;
501
+ // Truncate.
502
+ this._buffer = this._buffer.slice(0, length);
503
+ this.syncSync();
511
504
  }
512
505
 
513
506
  /**
@@ -542,7 +535,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
542
535
  * @returns bytes written
543
536
  */
544
537
  public writeSync(buffer: Uint8Array, offset: number = 0, length: number = this.stats.size, position: number = 0): number {
545
- this._dirty = true;
538
+ this.dirty = true;
546
539
  position ??= this.position;
547
540
  if (!isWriteable(this.flag)) {
548
541
  throw new ErrnoError(Errno.EPERM, 'File not opened with a writeable mode.');
@@ -566,11 +559,8 @@ export class PreloadFile<FS extends FileSystem> extends File {
566
559
  this._buffer.set(slice, position);
567
560
  const bytesWritten = slice.byteLength;
568
561
  this.stats.mtimeMs = Date.now();
569
- if (isSynchronous(this.flag)) {
570
- this.syncSync();
571
- return bytesWritten;
572
- }
573
562
  this.position = position + bytesWritten;
563
+ this.syncSync();
574
564
  return bytesWritten;
575
565
  }
576
566
 
@@ -609,6 +599,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
609
599
  if (!isReadable(this.flag)) {
610
600
  throw new ErrnoError(Errno.EPERM, 'File not opened with a readable mode.');
611
601
  }
602
+ this.dirty = true;
612
603
  position ??= this.position;
613
604
  let end = position + length;
614
605
  if (end > this.stats.size) {
@@ -617,6 +608,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
617
608
  this.stats.atimeMs = Date.now();
618
609
  this._position = end;
619
610
  const bytesRead = end - position;
611
+ this.syncSync();
620
612
  if (bytesRead == 0) {
621
613
  // No copy/read. Return immediatly for better performance
622
614
  return bytesRead;
@@ -638,7 +630,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
638
630
  * @param mode
639
631
  */
640
632
  public chmodSync(mode: number): void {
641
- this._dirty = true;
633
+ this.dirty = true;
642
634
  this.stats.chmod(mode);
643
635
  this.syncSync();
644
636
  }
@@ -658,7 +650,7 @@ export class PreloadFile<FS extends FileSystem> extends File {
658
650
  * @param gid
659
651
  */
660
652
  public chownSync(uid: number, gid: number): void {
661
- this._dirty = true;
653
+ this.dirty = true;
662
654
  this.stats.chown(uid, gid);
663
655
  this.syncSync();
664
656
  }
@@ -668,31 +660,20 @@ export class PreloadFile<FS extends FileSystem> extends File {
668
660
  }
669
661
 
670
662
  public utimesSync(atime: Date, mtime: Date): void {
671
- this._dirty = true;
663
+ this.dirty = true;
672
664
  this.stats.atime = atime;
673
665
  this.stats.mtime = mtime;
674
666
  this.syncSync();
675
667
  }
676
668
 
677
- protected isDirty(): boolean {
678
- return this._dirty;
679
- }
680
-
681
- /**
682
- * Resets the dirty bit. Should only be called after a sync has completed successfully.
683
- */
684
- protected resetDirty() {
685
- this._dirty = false;
686
- }
687
-
688
669
  public _setType(type: FileType): Promise<void> {
689
- this._dirty = true;
670
+ this.dirty = true;
690
671
  this.stats.mode = (this.stats.mode & ~S_IFMT) | type;
691
672
  return this.sync();
692
673
  }
693
674
 
694
675
  public _setTypeSync(type: FileType): void {
695
- this._dirty = true;
676
+ this.dirty = true;
696
677
  this.stats.mode = (this.stats.mode & ~S_IFMT) | type;
697
678
  this.syncSync();
698
679
  }
package/src/filesystem.ts CHANGED
@@ -44,6 +44,27 @@ export interface FileSystemMetadata {
44
44
  * @default false
45
45
  */
46
46
  noAsyncCache: boolean;
47
+
48
+ /**
49
+ * The optimal block size to use with the file system
50
+ * @default 4096
51
+ */
52
+ blockSize?: number;
53
+
54
+ /**
55
+ * Total number of (file) nodes available
56
+ */
57
+ totalNodes?: number;
58
+
59
+ /**
60
+ * Number of free (file) nodes available
61
+ */
62
+ freeNodes?: number;
63
+
64
+ /**
65
+ * The type of the FS
66
+ */
67
+ type?: number;
47
68
  }
48
69
 
49
70
  /**
@@ -57,6 +78,12 @@ export interface FileSystemMetadata {
57
78
  * - All arguments are present. Any optional arguments at the Node API level have been passed in with their default values.
58
79
  */
59
80
  export abstract class FileSystem {
81
+ /**
82
+ * Numeric type, used for statfs
83
+ * @internal @protected
84
+ */
85
+ _type?: number;
86
+
60
87
  /**
61
88
  * Get metadata about the current file system
62
89
  */
@@ -68,11 +95,11 @@ export abstract class FileSystem {
68
95
  freeSpace: 0,
69
96
  noResizableBuffers: false,
70
97
  noAsyncCache: false,
98
+ type: this._type,
71
99
  };
72
100
  }
73
101
 
74
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
75
- public constructor(options?: object) {}
102
+ public constructor() {}
76
103
 
77
104
  public async ready(): Promise<void> {}
78
105