@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/FileIndex.d.ts +117 -34
- package/dist/FileIndex.js +166 -84
- package/dist/backends/AsyncMirror.d.ts +28 -2
- package/dist/backends/AsyncMirror.js +3 -11
- package/dist/backends/AsyncStore.d.ts +16 -2
- package/dist/backends/AsyncStore.js +3 -2
- package/dist/backends/Locked.d.ts +1 -1
- package/dist/backends/Locked.js +1 -1
- package/dist/backends/Overlay.d.ts +1 -1
- package/dist/backends/Overlay.js +1 -1
- package/dist/backends/SyncStore.d.ts +29 -2
- package/dist/backends/SyncStore.js +3 -2
- package/dist/browser.min.js +5 -5
- package/dist/browser.min.js.map +3 -3
- package/dist/file.d.ts +2 -2
- package/dist/file.js +2 -2
- package/dist/filesystem.d.ts +27 -15
- package/dist/filesystem.js +133 -118
- package/package.json +1 -1
- package/readme.md +48 -70
- package/dist/backends/FolderAdapter.d.ts +0 -52
- package/dist/backends/FolderAdapter.js +0 -173
- package/dist/backends/OverlayFS.d.ts +0 -112
- package/dist/backends/OverlayFS.js +0 -542
- package/dist/emulation/fs.d.ts +0 -6
- package/dist/emulation/fs.js +0 -4
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
|
|
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 {
|
|
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.
|
package/dist/filesystem.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
157
|
+
* @internal
|
|
159
158
|
*/
|
|
160
|
-
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
|
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 {};
|
package/dist/filesystem.js
CHANGED
|
@@ -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
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
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
|
|
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
|
-
|
|
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
|
-
>
|
|
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
|
|
44
|
+
A single `InMemory` backend is created by default, mounted on `/`.
|
|
42
45
|
|
|
43
|
-
|
|
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
|
-
|
|
48
|
+
You can use multiple backends by passing an object to `configure` which maps paths to file systems.
|
|
48
49
|
|
|
49
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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');
|
|
123
|
+
fs.writeFileSync('/persistant.txt', 'My persistant data');
|
|
113
124
|
```
|
|
114
125
|
|
|
115
|
-
|
|
126
|
+
#### Mounting and unmounting, creating backends
|
|
116
127
|
|
|
117
|
-
|
|
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
|
-
|
|
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':
|
|
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
|
-
}
|