@zenfs/core 0.2.3 → 0.3.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.
package/dist/file.d.ts CHANGED
@@ -1,5 +1,5 @@
1
+ import type { FileSystem } from './filesystem.js';
1
2
  import { Stats, type FileType } from './stats.js';
2
- import { FileSystem, type SyncFileSystem } from './filesystem.js';
3
3
  declare global {
4
4
  interface ArrayBuffer {
5
5
  readonly resizable: boolean;
@@ -419,7 +419,7 @@ export declare abstract class PreloadFile<T extends FileSystem> extends File {
419
419
  /**
420
420
  * For synchronous file systems
421
421
  */
422
- export declare class SyncFile<FS extends SyncFileSystem> extends PreloadFile<FS> {
422
+ export declare class SyncFile<FS extends FileSystem> extends PreloadFile<FS> {
423
423
  constructor(_fs: FS, _path: string, _flag: FileFlag, _stat: Stats, contents?: Uint8Array);
424
424
  sync(): Promise<void>;
425
425
  syncSync(): void;
package/dist/file.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ApiError, ErrorCode } from './ApiError.js';
2
- import { Stats } from './stats.js';
3
- import { O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_SYNC, S_IFMT } from './emulation/constants.js';
2
+ import { O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_SYNC, O_TRUNC, O_WRONLY, S_IFMT } from './emulation/constants.js';
4
3
  import { size_max } from './inode.js';
4
+ import { Stats } from './stats.js';
5
5
  export var ActionType;
6
6
  (function (ActionType) {
7
7
  // Indicates that the code should not do anything.
@@ -46,7 +46,6 @@ export interface FileSystemMetadata {
46
46
  * - All arguments are present. Any optional arguments at the Node API level have been passed in with their default values.
47
47
  */
48
48
  export declare abstract class FileSystem {
49
- static get Name(): string;
50
49
  get metadata(): FileSystemMetadata;
51
50
  constructor(options?: object);
52
51
  abstract ready(): Promise<this>;
@@ -155,11 +154,12 @@ export declare abstract class FileSystem {
155
154
  abstract syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
156
155
  }
157
156
  /**
158
- * Implements the asynchronous API in terms of the synchronous API.
157
+ * @internal
159
158
  */
160
- export declare abstract class SyncFileSystem extends FileSystem {
159
+ declare abstract class SyncFileSystem extends FileSystem {
161
160
  get metadata(): FileSystemMetadata;
162
161
  ready(): Promise<this>;
162
+ exists(path: string, cred: Cred): Promise<boolean>;
163
163
  rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
164
164
  stat(path: string, cred: Cred): Promise<Stats>;
165
165
  createFile(path: string, flag: FileFlag, mode: number, cred: Cred): Promise<File>;
@@ -171,20 +171,18 @@ export declare abstract class SyncFileSystem extends FileSystem {
171
171
  link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
172
172
  sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
173
173
  }
174
- export declare abstract class ReadonlySyncFileSystem extends SyncFileSystem {
175
- renameSync(oldPath: string, newPath: string, cred: Cred): void;
176
- createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): File;
177
- unlinkSync(path: string, cred: Cred): void;
178
- rmdirSync(path: string, cred: Cred): void;
179
- mkdirSync(path: string, mode: number, cred: Cred): void;
180
- linkSync(srcpath: string, dstpath: string, cred: Cred): void;
181
- syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
182
- }
183
- export declare abstract class AsyncFileSystem extends FileSystem {
174
+ /**
175
+ * Implements the asynchronous API in terms of the synchronous API.
176
+ */
177
+ export declare function Sync<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => SyncFileSystem) & T;
178
+ /**
179
+ * @internal
180
+ */
181
+ declare abstract class AsyncFileSystem {
182
+ get metadata(): FileSystemMetadata;
184
183
  renameSync(oldPath: string, newPath: string, cred: Cred): void;
185
184
  statSync(path: string, cred: Cred): Stats;
186
185
  createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): File;
187
- openSync(path: string, flags: FileFlag, mode: number, cred: Cred): File;
188
186
  openFileSync(path: string, flag: FileFlag, cred: Cred): File;
189
187
  unlinkSync(path: string, cred: Cred): void;
190
188
  rmdirSync(path: string, cred: Cred): void;
@@ -193,12 +191,26 @@ export declare abstract class AsyncFileSystem extends FileSystem {
193
191
  linkSync(srcpath: string, dstpath: string, cred: Cred): void;
194
192
  syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
195
193
  }
196
- export declare abstract class ReadonlyAsyncFileSystem extends AsyncFileSystem {
194
+ export declare function Async<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => AsyncFileSystem) & T;
195
+ /**
196
+ * @internal
197
+ */
198
+ declare abstract class ReadonlyFileSystem {
199
+ get metadata(): FileSystemMetadata;
197
200
  rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
201
+ renameSync(oldPath: string, newPath: string, cred: Cred): void;
198
202
  createFile(path: string, flag: FileFlag, mode: number, cred: Cred): Promise<File>;
203
+ createFileSync(path: string, flag: FileFlag, mode: number, cred: Cred): File;
199
204
  unlink(path: string, cred: Cred): Promise<void>;
205
+ unlinkSync(path: string, cred: Cred): void;
200
206
  rmdir(path: string, cred: Cred): Promise<void>;
207
+ rmdirSync(path: string, cred: Cred): void;
201
208
  mkdir(path: string, mode: number, cred: Cred): Promise<void>;
209
+ mkdirSync(path: string, mode: number, cred: Cred): void;
202
210
  link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
211
+ linkSync(srcpath: string, dstpath: string, cred: Cred): void;
203
212
  sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
213
+ syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
204
214
  }
215
+ export declare function Readonly<T extends abstract new (...args: any[]) => FileSystem>(FS: T): (abstract new (...args: any[]) => ReadonlyFileSystem) & T;
216
+ export {};
@@ -1,5 +1,3 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
- // disable no-unused-vars since BaseFileSystem uses them a lot
3
1
  import { ApiError, ErrorCode } from './ApiError.js';
4
2
  /**
5
3
  * Structure for a filesystem. All ZenFS FileSystems must implement this.
@@ -12,9 +10,6 @@ import { ApiError, ErrorCode } from './ApiError.js';
12
10
  * - All arguments are present. Any optional arguments at the Node API level have been passed in with their default values.
13
11
  */
14
12
  export class FileSystem {
15
- static get Name() {
16
- return this.name;
17
- }
18
13
  get metadata() {
19
14
  return {
20
15
  name: this.constructor.name,
@@ -25,6 +20,7 @@ export class FileSystem {
25
20
  freeSpace: 0,
26
21
  };
27
22
  }
23
+ /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
28
24
  constructor(options) {
29
25
  // unused
30
26
  }
@@ -56,122 +52,141 @@ export class FileSystem {
56
52
  /**
57
53
  * Implements the asynchronous API in terms of the synchronous API.
58
54
  */
59
- export class SyncFileSystem extends FileSystem {
60
- get metadata() {
61
- return { ...super.metadata, synchronous: true };
62
- }
63
- async ready() {
64
- return this;
65
- }
66
- async rename(oldPath, newPath, cred) {
67
- return this.renameSync(oldPath, newPath, cred);
68
- }
69
- async stat(path, cred) {
70
- return this.statSync(path, cred);
71
- }
72
- async createFile(path, flag, mode, cred) {
73
- return this.createFileSync(path, flag, mode, cred);
74
- }
75
- async openFile(path, flag, cred) {
76
- return this.openFileSync(path, flag, cred);
77
- }
78
- async unlink(path, cred) {
79
- return this.unlinkSync(path, cred);
80
- }
81
- async rmdir(path, cred) {
82
- return this.rmdirSync(path, cred);
83
- }
84
- async mkdir(path, mode, cred) {
85
- return this.mkdirSync(path, mode, cred);
86
- }
87
- async readdir(path, cred) {
88
- return this.readdirSync(path, cred);
89
- }
90
- async link(srcpath, dstpath, cred) {
91
- return this.linkSync(srcpath, dstpath, cred);
92
- }
93
- async sync(path, data, stats) {
94
- return this.syncSync(path, data, stats);
95
- }
96
- }
97
- export class ReadonlySyncFileSystem extends SyncFileSystem {
98
- renameSync(oldPath, newPath, cred) {
99
- throw new ApiError(ErrorCode.EROFS);
100
- }
101
- createFileSync(path, flag, mode, cred) {
102
- throw new ApiError(ErrorCode.EROFS);
103
- }
104
- unlinkSync(path, cred) {
105
- throw new ApiError(ErrorCode.EROFS);
106
- }
107
- rmdirSync(path, cred) {
108
- throw new ApiError(ErrorCode.EROFS);
109
- }
110
- mkdirSync(path, mode, cred) {
111
- throw new ApiError(ErrorCode.EROFS);
112
- }
113
- linkSync(srcpath, dstpath, cred) {
114
- throw new ApiError(ErrorCode.EROFS);
115
- }
116
- syncSync(path, data, stats) {
117
- throw new ApiError(ErrorCode.EROFS);
55
+ export function Sync(FS) {
56
+ /**
57
+ * Implements the asynchronous API in terms of the synchronous API.
58
+ */
59
+ class _SyncFileSystem extends FS {
60
+ get metadata() {
61
+ return { ...super.metadata, synchronous: true };
62
+ }
63
+ async ready() {
64
+ return this;
65
+ }
66
+ async exists(path, cred) {
67
+ return this.existsSync(path, cred);
68
+ }
69
+ async rename(oldPath, newPath, cred) {
70
+ return this.renameSync(oldPath, newPath, cred);
71
+ }
72
+ async stat(path, cred) {
73
+ return this.statSync(path, cred);
74
+ }
75
+ async createFile(path, flag, mode, cred) {
76
+ return this.createFileSync(path, flag, mode, cred);
77
+ }
78
+ async openFile(path, flag, cred) {
79
+ return this.openFileSync(path, flag, cred);
80
+ }
81
+ async unlink(path, cred) {
82
+ return this.unlinkSync(path, cred);
83
+ }
84
+ async rmdir(path, cred) {
85
+ return this.rmdirSync(path, cred);
86
+ }
87
+ async mkdir(path, mode, cred) {
88
+ return this.mkdirSync(path, mode, cred);
89
+ }
90
+ async readdir(path, cred) {
91
+ return this.readdirSync(path, cred);
92
+ }
93
+ async link(srcpath, dstpath, cred) {
94
+ return this.linkSync(srcpath, dstpath, cred);
95
+ }
96
+ async sync(path, data, stats) {
97
+ return this.syncSync(path, data, stats);
98
+ }
118
99
  }
100
+ return _SyncFileSystem;
119
101
  }
120
- export class AsyncFileSystem extends FileSystem {
121
- renameSync(oldPath, newPath, cred) {
122
- throw new ApiError(ErrorCode.ENOTSUP);
123
- }
124
- statSync(path, cred) {
125
- throw new ApiError(ErrorCode.ENOTSUP);
126
- }
127
- createFileSync(path, flag, mode, cred) {
128
- throw new ApiError(ErrorCode.ENOTSUP);
129
- }
130
- openSync(path, flags, mode, cred) {
131
- throw new ApiError(ErrorCode.ENOTSUP);
132
- }
133
- openFileSync(path, flag, cred) {
134
- throw new ApiError(ErrorCode.ENOTSUP);
135
- }
136
- unlinkSync(path, cred) {
137
- throw new ApiError(ErrorCode.ENOTSUP);
138
- }
139
- rmdirSync(path, cred) {
140
- throw new ApiError(ErrorCode.ENOTSUP);
141
- }
142
- mkdirSync(path, mode, cred) {
143
- throw new ApiError(ErrorCode.ENOTSUP);
144
- }
145
- readdirSync(path, cred) {
146
- throw new ApiError(ErrorCode.ENOTSUP);
147
- }
148
- linkSync(srcpath, dstpath, cred) {
149
- throw new ApiError(ErrorCode.ENOTSUP);
150
- }
151
- syncSync(path, data, stats) {
152
- throw new ApiError(ErrorCode.ENOTSUP);
102
+ export function Async(FS) {
103
+ class _AsyncFileSystem extends FS {
104
+ get metadata() {
105
+ return { ...super.metadata, synchronous: false };
106
+ }
107
+ /* eslint-disable @typescript-eslint/no-unused-vars */
108
+ renameSync(oldPath, newPath, cred) {
109
+ throw new ApiError(ErrorCode.ENOTSUP);
110
+ }
111
+ statSync(path, cred) {
112
+ throw new ApiError(ErrorCode.ENOTSUP);
113
+ }
114
+ createFileSync(path, flag, mode, cred) {
115
+ throw new ApiError(ErrorCode.ENOTSUP);
116
+ }
117
+ openFileSync(path, flag, cred) {
118
+ throw new ApiError(ErrorCode.ENOTSUP);
119
+ }
120
+ unlinkSync(path, cred) {
121
+ throw new ApiError(ErrorCode.ENOTSUP);
122
+ }
123
+ rmdirSync(path, cred) {
124
+ throw new ApiError(ErrorCode.ENOTSUP);
125
+ }
126
+ mkdirSync(path, mode, cred) {
127
+ throw new ApiError(ErrorCode.ENOTSUP);
128
+ }
129
+ readdirSync(path, cred) {
130
+ throw new ApiError(ErrorCode.ENOTSUP);
131
+ }
132
+ linkSync(srcpath, dstpath, cred) {
133
+ throw new ApiError(ErrorCode.ENOTSUP);
134
+ }
135
+ syncSync(path, data, stats) {
136
+ throw new ApiError(ErrorCode.ENOTSUP);
137
+ }
153
138
  }
139
+ /* eslint-enable @typescript-eslint/no-unused-vars */
140
+ return _AsyncFileSystem;
154
141
  }
155
- export class ReadonlyAsyncFileSystem extends AsyncFileSystem {
156
- async rename(oldPath, newPath, cred) {
157
- throw new ApiError(ErrorCode.EROFS);
158
- }
159
- async createFile(path, flag, mode, cred) {
160
- throw new ApiError(ErrorCode.EROFS);
161
- }
162
- async unlink(path, cred) {
163
- throw new ApiError(ErrorCode.EROFS);
164
- }
165
- async rmdir(path, cred) {
166
- throw new ApiError(ErrorCode.EROFS);
167
- }
168
- async mkdir(path, mode, cred) {
169
- throw new ApiError(ErrorCode.EROFS);
170
- }
171
- async link(srcpath, dstpath, cred) {
172
- throw new ApiError(ErrorCode.EROFS);
173
- }
174
- async sync(path, data, stats) {
175
- throw new ApiError(ErrorCode.EROFS);
142
+ export function Readonly(FS) {
143
+ class _ReadonlyFileSystem extends FS {
144
+ get metadata() {
145
+ return { ...super.metadata, readonly: true };
146
+ }
147
+ /* eslint-disable @typescript-eslint/no-unused-vars */
148
+ async rename(oldPath, newPath, cred) {
149
+ throw new ApiError(ErrorCode.EROFS);
150
+ }
151
+ renameSync(oldPath, newPath, cred) {
152
+ throw new ApiError(ErrorCode.EROFS);
153
+ }
154
+ async createFile(path, flag, mode, cred) {
155
+ throw new ApiError(ErrorCode.EROFS);
156
+ }
157
+ createFileSync(path, flag, mode, cred) {
158
+ throw new ApiError(ErrorCode.EROFS);
159
+ }
160
+ async unlink(path, cred) {
161
+ throw new ApiError(ErrorCode.EROFS);
162
+ }
163
+ unlinkSync(path, cred) {
164
+ throw new ApiError(ErrorCode.EROFS);
165
+ }
166
+ async rmdir(path, cred) {
167
+ throw new ApiError(ErrorCode.EROFS);
168
+ }
169
+ rmdirSync(path, cred) {
170
+ throw new ApiError(ErrorCode.EROFS);
171
+ }
172
+ async mkdir(path, mode, cred) {
173
+ throw new ApiError(ErrorCode.EROFS);
174
+ }
175
+ mkdirSync(path, mode, cred) {
176
+ throw new ApiError(ErrorCode.EROFS);
177
+ }
178
+ async link(srcpath, dstpath, cred) {
179
+ throw new ApiError(ErrorCode.EROFS);
180
+ }
181
+ linkSync(srcpath, dstpath, cred) {
182
+ throw new ApiError(ErrorCode.EROFS);
183
+ }
184
+ async sync(path, data, stats) {
185
+ throw new ApiError(ErrorCode.EROFS);
186
+ }
187
+ syncSync(path, data, stats) {
188
+ throw new ApiError(ErrorCode.EROFS);
189
+ }
176
190
  }
191
+ return _ReadonlyFileSystem;
177
192
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenfs/core",
3
- "version": "0.2.3",
3
+ "version": "0.3.1",
4
4
  "description": "A filesystem in your browser",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist",
package/readme.md CHANGED
@@ -4,14 +4,16 @@ ZenFS is an in-browser file system that emulates the [Node JS file system API](h
4
4
 
5
5
  ## Backends
6
6
 
7
- ZenFS is highly extensible, and includes many builtin filesystem backends:
7
+ ZenFS is highly extensible, and includes a few built-in backends:
8
8
 
9
9
  - `InMemory`: Stores files in-memory. It is a temporary file store that clears when the user navigates away.
10
10
  - `Overlay`: Mount a read-only file system as read-write by overlaying a writable file system on top of it. Like Docker's overlayfs, it will only write changed files to the writable file system.
11
11
  - `AsyncMirror`: Use an asynchronous backend synchronously. Invaluable for Emscripten; let your Emscripten applications write to larger file stores with no additional effort!
12
- - `AsyncMirror` loads the entire contents of the async file system into a synchronous backend during construction. It performs operations synchronous file system and then queues them to be mirrored onto the asynchronous backend.
13
12
 
14
- More backends can be defined by separate libraries, so long as they extend they implement `ZenFS.FileSystem`. Multiple backends can be active at once at different locations in the directory hierarchy.
13
+ > [!NOTE]
14
+ > When constructed, `AsyncMirror` loads the entire contents of the async file system into a synchronous backend. It performs operations on the synchronous file system and then queues them to be mirrored onto the asynchronous backend.
15
+
16
+ More backends can be defined by separate libraries, as long as they implement `FileSystem`.
15
17
 
16
18
  ZenFS supports a number of other backends (many are provided as seperate packages under `@zenfs`).
17
19
 
@@ -25,7 +27,8 @@ npm install @zenfs/core
25
27
 
26
28
  ## Usage
27
29
 
28
- > 🛈 The examples are written in ESM. If you are using CJS, you can `require` the package. If running in a browser you can add a script tag to your HTML pointing to the `browser.min.js` and use ZenFS via the global `ZenFS` object.
30
+ > [!NOTE]
31
+ > The examples are written in ESM. If you are using CJS, you can `require` the package. If running in a browser you can add a script tag to your HTML pointing to the `browser.min.js` and use ZenFS via the global `ZenFS` object.
29
32
 
30
33
  ```js
31
34
  import fs from '@zenfs/core';
@@ -36,27 +39,15 @@ const contents = fs.readFileSync('/test.txt', 'utf-8');
36
39
  console.log(contents);
37
40
  ```
38
41
 
39
- #### Using different backends
42
+ #### Using different and/or different backends
40
43
 
41
- A `InMemory` backend is created by default. If you would like to use a different one, you must configure ZenFS. It is recommended to do so using the `configure` function. Here is an example using the `Storage` backend from `@zenfs/dom`:
44
+ A single `InMemory` backend is created by default, mounted on `/`.
42
45
 
43
- ```js
44
- import { configure, fs } from '@zenfs/core';
45
- import { StorageStore } from '@zenfs/dom';
46
+ You can configure ZenFS to use a different backend and mount multiple backends. It is strongly recommended to do so using the `configure` function.
46
47
 
47
- await configure({ backend: StorageStore });
48
+ You can use multiple backends by passing an object to `configure` which maps paths to file systems.
48
49
 
49
- if (!fs.existsSync('/test.txt')) {
50
- fs.writeFileSync('/test.txt', 'This will persist across reloads!');
51
- }
52
-
53
- const contents = fs.readFileSync('/test.txt', 'utf-8');
54
- console.log(contents);
55
- ```
56
-
57
- #### Using multiple backends
58
-
59
- You can use multiple backends by passing an object to `configure` which maps paths to file systems. The following example mounts a zip file to `/zip`, in-memory storage to `/tmp`, and IndexedDB storage to `/home` (note that `/` has the default in-memory backend):
50
+ The following example mounts a zip file to `/zip`, in-memory storage to `/tmp`, and IndexedDB to `/home`. Note that `/` has the default in-memory backend.
60
51
 
61
52
  ```js
62
53
  import { configure } from '@zenfs/core';
@@ -66,16 +57,32 @@ import { Zip } from '@zenfs/zip';
66
57
  const zipData = await (await fetch('mydata.zip')).arrayBuffer();
67
58
 
68
59
  await configure({
69
- '/mnt/zip': {
70
- backend: Zip,
71
- zipData: zipData,
72
- },
60
+ '/mnt/zip': { backend: Zip, zipData },
73
61
  '/tmp': 'InMemory',
74
62
  '/home': IndexedDB,
75
63
  };
76
64
  ```
77
65
 
78
- #### FS Promises API
66
+ > [!TIP]
67
+ > When configuring a mount point, you can pass in 1. A string that maps to a built-in backend 2. A `Backend` object, if the backend has no required options 3. An object that has a `backend` property which is a `Backend` or a string that maps to a built-in backend and the options accepted by the backend
68
+
69
+ Here is an example that mounts the `Storage` backend from `@zenfs/dom` on `/`:
70
+
71
+ ```js
72
+ import { configure, fs } from '@zenfs/core';
73
+ import { Storage } from '@zenfs/dom';
74
+
75
+ await configure({ backend: Storage });
76
+
77
+ if (!fs.existsSync('/test.txt')) {
78
+ fs.writeFileSync('/test.txt', 'This will persist across reloads!');
79
+ }
80
+
81
+ const contents = fs.readFileSync('/test.txt', 'utf-8');
82
+ console.log(contents);
83
+ ```
84
+
85
+ #### FS Promises
79
86
 
80
87
  The FS promises API is exposed as `promises`.
81
88
 
@@ -91,11 +98,15 @@ if (!exists) {
91
98
  }
92
99
  ```
93
100
 
94
- ZenFS does _not_ provide a seperate public import for importing promises in its built form. If you are using ESM, you can import promises functions from `dist/emulation/promises`, though this may change at any time and is not recommended.
101
+ > [!NOTE]
102
+ > You can import the promises API using `promises`, or using `fs.promises` on the exported `fs`.
103
+
104
+ > [!IMPORTANT]
105
+ > ZenFS does _not_ provide a seperate public import for importing promises like `fs/promises`. If you are using ESM, you can import promises functions like `fs/promises` from the `dist/emulation/promises.ts` file, though this may change at any time and is **not recommended**.
95
106
 
96
107
  #### Using asynchronous backends synchronously
97
108
 
98
- You may have noticed that attempting to use a synchronous function on an asynchronous backend (e.g. IndexedDB) results in a "not supplied" error (`ENOTSUP`). If you wish to use an asynchronous backend synchronously you need to wrap it in an `AsyncMirror`:
109
+ You may have noticed that attempting to use a synchronous function on an asynchronous backend (e.g. `IndexedDB`) results in a "not supplied" error (`ENOTSUP`). If you would like to use an asynchronous backend synchronously you need to wrap it in an `AsyncMirror`:
99
110
 
100
111
  ```js
101
112
  import { configure, fs } from '@zenfs/core';
@@ -109,55 +120,23 @@ await configure({
109
120
  },
110
121
  });
111
122
 
112
- fs.writeFileSync('/persistant.txt', 'My persistant data'); // This fails if you configure with only IndexedDB
123
+ fs.writeFileSync('/persistant.txt', 'My persistant data');
113
124
  ```
114
125
 
115
- ### Advanced usage
126
+ #### Mounting and unmounting, creating backends
116
127
 
117
- #### Creating backends
128
+ If you would like to create backends without configure (e.g. to do something dynamic at runtime), you may do so by importing the backend and calling `createBackend` with it.
118
129
 
119
- If you would like to create backends without configure, you may do so by importing the backend and calling `createBackend` with it. You can import the backend directly or with `backends`:
120
-
121
- ```js
122
- import { configure, backends, InMemory } from '@zenfs/core';
123
-
124
- console.log(backends.InMemory === InMemory); // they are the same
125
-
126
- const internalInMemoryFS = await createBackend(InMemory);
127
- ```
128
-
129
- > ⚠ Instances of backends follow the **_internal_** ZenFS API. You should never use a backend's methods unless you are extending a backend.
130
-
131
- ```js
132
- import { configure, InMemory } from '@zenfs/core';
133
-
134
- const internalInMemoryFS = new InMemory();
135
- await internalInMemoryFS.ready();
136
- ```
137
-
138
- #### Mounting
139
-
140
- If you would like to mount and unmount backends, you can do so using the `mount` and `umount` functions:
141
-
142
- ```js
143
- import { fs, InMemory } from '@zenfs/core';
144
-
145
- const internalInMemoryFS = await createBackend(InMemory); // create an FS instance
146
-
147
- fs.mount('/tmp', internalInMemoryFS); // mount
148
-
149
- fs.umount('/tmp'); // unmount /tmp
150
- ```
151
-
152
- This could be used in the "multiple backends" example like so:
130
+ You can then mount and unmount the backend instance by using `mount` and `umount`.
153
131
 
154
132
  ```js
133
+ import { configure, createBackend } from '@zenfs/core';
155
134
  import { IndexedDB } from '@zenfs/dom';
156
135
  import { Zip } from '@zenfs/zip';
157
136
 
158
137
  await configure({
159
138
  '/tmp': 'InMemory',
160
- '/home': 'IndexedDB',
139
+ '/home': IndexedDB,
161
140
  };
162
141
 
163
142
  fs.mkdirSync('/mnt');
@@ -171,6 +150,9 @@ fs.mount('/mnt/zip', zipFs);
171
150
  fs.umount('/mnt/zip'); // finished using the zip
172
151
  ```
173
152
 
153
+ > [!WARNING]
154
+ > Instances of backends follow the **internal** ZenFS API. You should never use a backend's methods unless you are extending a backend.
155
+
174
156
  ## Using with bundlers
175
157
 
176
158
  ZenFS exports a drop-in for Node's `fs` module (up to the version of `@types/node` in package.json), so you can use it for your bundler of preference using the default export.
@@ -185,7 +167,3 @@ ZenFS exports a drop-in for Node's `fs` module (up to the version of `@types/nod
185
167
  ### Testing
186
168
 
187
169
  Run unit tests with `npm test`.
188
-
189
- ### License
190
-
191
- ZenFS is licensed under the MIT License.
@@ -1,52 +0,0 @@
1
- import { BaseFileSystem, type FileSystem } from '../filesystem.js';
2
- import { type BackendOptions } from './backend.js';
3
- export declare namespace FolderAdapter {
4
- /**
5
- * Configuration options for a FolderAdapter file system.
6
- */
7
- interface Options {
8
- folder: string;
9
- wrapped: FileSystem;
10
- }
11
- }
12
- /**
13
- * The FolderAdapter file system wraps a file system, and scopes all interactions to a subfolder of that file system.
14
- *
15
- * Example: Given a file system `foo` with folder `bar` and file `bar/baz`...
16
- *
17
- * ```javascript
18
- * ZenFS.configure({
19
- * fs: "FolderAdapter",
20
- * options: {
21
- * folder: "bar",
22
- * wrapped: foo
23
- * }
24
- * }, function(e) {
25
- * var fs = ZenFS.BFSRequire('fs');
26
- * fs.readdirSync('/'); // ['baz']
27
- * });
28
- * ```
29
- */
30
- export declare class FolderAdapter extends BaseFileSystem {
31
- static readonly Name = "FolderAdapter";
32
- static Create: any;
33
- static readonly Options: BackendOptions;
34
- static isAvailable(): boolean;
35
- _wrapped: FileSystem;
36
- _folder: string;
37
- constructor({ folder, wrapped }: FolderAdapter.Options);
38
- get metadata(): {
39
- supportsLinks: boolean;
40
- name: string;
41
- readonly: boolean;
42
- synchronous: boolean;
43
- supportsProperties: boolean;
44
- totalSpace: number;
45
- freeSpace: number;
46
- };
47
- /**
48
- * Initialize the file system. Ensures that the wrapped file system
49
- * has the given folder.
50
- */
51
- private _initialize;
52
- }