@zenfs/core 0.9.2 → 0.9.4
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/backends/Index.d.ts +3 -0
- package/dist/browser.min.js +3 -3
- package/dist/browser.min.js.map +3 -3
- package/dist/filesystem.d.ts +1 -1
- package/dist/filesystem.js +6 -6
- package/package.json +2 -9
- package/src/ApiError.ts +310 -0
- package/src/backends/AsyncStore.ts +635 -0
- package/src/backends/InMemory.ts +56 -0
- package/src/backends/Index.ts +500 -0
- package/src/backends/Locked.ts +181 -0
- package/src/backends/Overlay.ts +591 -0
- package/src/backends/SyncStore.ts +589 -0
- package/src/backends/backend.ts +152 -0
- package/src/config.ts +101 -0
- package/src/cred.ts +21 -0
- package/src/emulation/async.ts +910 -0
- package/src/emulation/constants.ts +176 -0
- package/src/emulation/dir.ts +139 -0
- package/src/emulation/index.ts +8 -0
- package/src/emulation/path.ts +468 -0
- package/src/emulation/promises.ts +1071 -0
- package/src/emulation/shared.ts +128 -0
- package/src/emulation/streams.ts +33 -0
- package/src/emulation/sync.ts +898 -0
- package/src/file.ts +721 -0
- package/src/filesystem.ts +544 -0
- package/src/index.ts +21 -0
- package/src/inode.ts +229 -0
- package/src/mutex.ts +52 -0
- package/src/stats.ts +385 -0
- package/src/utils.ts +287 -0
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
import type { ExtractProperties } from 'utilium';
|
|
2
|
+
import { ApiError, ErrorCode } from './ApiError.js';
|
|
3
|
+
import { rootCred, type Cred } from './cred.js';
|
|
4
|
+
import { join } from './emulation/path.js';
|
|
5
|
+
import { PreloadFile, parseFlag, type File } from './file.js';
|
|
6
|
+
import type { Stats } from './stats.js';
|
|
7
|
+
|
|
8
|
+
export type FileContents = Uint8Array | string;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Metadata about a FileSystem
|
|
12
|
+
*/
|
|
13
|
+
export interface FileSystemMetadata {
|
|
14
|
+
/**
|
|
15
|
+
* The name of the FS
|
|
16
|
+
*/
|
|
17
|
+
name: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Wheter the FS is readonly or not
|
|
21
|
+
*/
|
|
22
|
+
readonly: boolean;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The total space
|
|
26
|
+
*/
|
|
27
|
+
totalSpace: number;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The available space
|
|
31
|
+
*/
|
|
32
|
+
freeSpace: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Structure for a filesystem. All ZenFS backends must extend this.
|
|
37
|
+
*
|
|
38
|
+
* This class includes some default implementations
|
|
39
|
+
*
|
|
40
|
+
* Assume the following about arguments passed to each API method:
|
|
41
|
+
*
|
|
42
|
+
* - Every path is an absolute path. `.`, `..`, and other items are resolved into an absolute form.
|
|
43
|
+
* - All arguments are present. Any optional arguments at the Node API level have been passed in with their default values.
|
|
44
|
+
*/
|
|
45
|
+
export abstract class FileSystem {
|
|
46
|
+
/**
|
|
47
|
+
* Get metadata about the current file syste,
|
|
48
|
+
*/
|
|
49
|
+
public metadata(): FileSystemMetadata {
|
|
50
|
+
return {
|
|
51
|
+
name: this.constructor.name,
|
|
52
|
+
readonly: false,
|
|
53
|
+
totalSpace: 0,
|
|
54
|
+
freeSpace: 0,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public constructor(options?: object) {
|
|
59
|
+
// unused
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public async ready(): Promise<this> {
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Asynchronous rename. No arguments other than a possible exception
|
|
68
|
+
* are given to the completion callback.
|
|
69
|
+
*/
|
|
70
|
+
public abstract rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Synchronous rename.
|
|
73
|
+
*/
|
|
74
|
+
public abstract renameSync(oldPath: string, newPath: string, cred: Cred): void;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Asynchronous `stat`.
|
|
78
|
+
*/
|
|
79
|
+
public abstract stat(path: string, cred: Cred): Promise<Stats>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Synchronous `stat`.
|
|
83
|
+
*/
|
|
84
|
+
public abstract statSync(path: string, cred: Cred): Stats;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Opens the file at path p with the given flag. The file must exist.
|
|
88
|
+
* @param p The path to open.
|
|
89
|
+
* @param flag The flag to use when opening the file.
|
|
90
|
+
*/
|
|
91
|
+
public abstract openFile(path: string, flag: string, cred: Cred): Promise<File>;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Opens the file at path p with the given flag. The file must exist.
|
|
95
|
+
* @param p The path to open.
|
|
96
|
+
* @param flag The flag to use when opening the file.
|
|
97
|
+
* @return A File object corresponding to the opened file.
|
|
98
|
+
*/
|
|
99
|
+
public abstract openFileSync(path: string, flag: string, cred: Cred): File;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Create the file at path p with the given mode. Then, open it with the given
|
|
103
|
+
* flag.
|
|
104
|
+
*/
|
|
105
|
+
public abstract createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File>;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Create the file at path p with the given mode. Then, open it with the given
|
|
109
|
+
* flag.
|
|
110
|
+
*/
|
|
111
|
+
public abstract createFileSync(path: string, flag: string, mode: number, cred: Cred): File;
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Asynchronous `unlink`.
|
|
115
|
+
*/
|
|
116
|
+
public abstract unlink(path: string, cred: Cred): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Synchronous `unlink`.
|
|
119
|
+
*/
|
|
120
|
+
public abstract unlinkSync(path: string, cred: Cred): void;
|
|
121
|
+
// Directory operations
|
|
122
|
+
/**
|
|
123
|
+
* Asynchronous `rmdir`.
|
|
124
|
+
*/
|
|
125
|
+
public abstract rmdir(path: string, cred: Cred): Promise<void>;
|
|
126
|
+
/**
|
|
127
|
+
* Synchronous `rmdir`.
|
|
128
|
+
*/
|
|
129
|
+
public abstract rmdirSync(path: string, cred: Cred): void;
|
|
130
|
+
/**
|
|
131
|
+
* Asynchronous `mkdir`.
|
|
132
|
+
* @param mode Mode to make the directory using. Can be ignored if
|
|
133
|
+
* the filesystem doesn't support permissions.
|
|
134
|
+
*/
|
|
135
|
+
public abstract mkdir(path: string, mode: number, cred: Cred): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* Synchronous `mkdir`.
|
|
138
|
+
* @param mode Mode to make the directory using. Can be ignored if
|
|
139
|
+
* the filesystem doesn't support permissions.
|
|
140
|
+
*/
|
|
141
|
+
public abstract mkdirSync(path: string, mode: number, cred: Cred): void;
|
|
142
|
+
/**
|
|
143
|
+
* Asynchronous `readdir`. Reads the contents of a directory.
|
|
144
|
+
*
|
|
145
|
+
* The callback gets two arguments `(err, files)` where `files` is an array of
|
|
146
|
+
* the names of the files in the directory excluding `'.'` and `'..'`.
|
|
147
|
+
*/
|
|
148
|
+
public abstract readdir(path: string, cred: Cred): Promise<string[]>;
|
|
149
|
+
/**
|
|
150
|
+
* Synchronous `readdir`. Reads the contents of a directory.
|
|
151
|
+
*/
|
|
152
|
+
public abstract readdirSync(path: string, cred: Cred): string[];
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Test whether or not the given path exists by checking with the file system.
|
|
156
|
+
*/
|
|
157
|
+
public async exists(path: string, cred: Cred): Promise<boolean> {
|
|
158
|
+
try {
|
|
159
|
+
await this.stat(path, cred);
|
|
160
|
+
return true;
|
|
161
|
+
} catch (e) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Test whether or not the given path exists by checking with the file system.
|
|
168
|
+
*/
|
|
169
|
+
public existsSync(path: string, cred: Cred): boolean {
|
|
170
|
+
try {
|
|
171
|
+
this.statSync(path, cred);
|
|
172
|
+
return true;
|
|
173
|
+
} catch (e) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Asynchronous `link`.
|
|
180
|
+
*/
|
|
181
|
+
public abstract link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Synchronous `link`.
|
|
185
|
+
*/
|
|
186
|
+
public abstract linkSync(srcpath: string, dstpath: string, cred: Cred): void;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Synchronize the data and stats for path asynchronously
|
|
190
|
+
*/
|
|
191
|
+
public abstract sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Synchronize the data and stats for path synchronously
|
|
195
|
+
*/
|
|
196
|
+
public abstract syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @internal
|
|
201
|
+
*/
|
|
202
|
+
declare abstract class SyncFileSystem extends FileSystem {
|
|
203
|
+
metadata(): FileSystemMetadata;
|
|
204
|
+
ready(): Promise<this>;
|
|
205
|
+
exists(path: string, cred: Cred): Promise<boolean>;
|
|
206
|
+
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
|
|
207
|
+
stat(path: string, cred: Cred): Promise<Stats>;
|
|
208
|
+
createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File>;
|
|
209
|
+
openFile(path: string, flag: string, cred: Cred): Promise<File>;
|
|
210
|
+
unlink(path: string, cred: Cred): Promise<void>;
|
|
211
|
+
rmdir(path: string, cred: Cred): Promise<void>;
|
|
212
|
+
mkdir(path: string, mode: number, cred: Cred): Promise<void>;
|
|
213
|
+
readdir(path: string, cred: Cred): Promise<string[]>;
|
|
214
|
+
link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
|
|
215
|
+
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Implements the asynchronous API in terms of the synchronous API.
|
|
220
|
+
*/
|
|
221
|
+
export function Sync<T extends abstract new (...args) => FileSystem>(FS: T): (abstract new (...args) => SyncFileSystem) & T {
|
|
222
|
+
abstract class _SyncFileSystem extends FS implements SyncFileSystem {
|
|
223
|
+
public async exists(path: string, cred: Cred): Promise<boolean> {
|
|
224
|
+
return this.existsSync(path, cred);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
public async rename(oldPath: string, newPath: string, cred: Cred): Promise<void> {
|
|
228
|
+
return this.renameSync(oldPath, newPath, cred);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
public async stat(path: string, cred: Cred): Promise<Stats> {
|
|
232
|
+
return this.statSync(path, cred);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
public async createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File> {
|
|
236
|
+
return this.createFileSync(path, flag, mode, cred);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
public async openFile(path: string, flag: string, cred: Cred): Promise<File> {
|
|
240
|
+
return this.openFileSync(path, flag, cred);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
public async unlink(path: string, cred: Cred): Promise<void> {
|
|
244
|
+
return this.unlinkSync(path, cred);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
public async rmdir(path: string, cred: Cred): Promise<void> {
|
|
248
|
+
return this.rmdirSync(path, cred);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
public async mkdir(path: string, mode: number, cred: Cred): Promise<void> {
|
|
252
|
+
return this.mkdirSync(path, mode, cred);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
public async readdir(path: string, cred: Cred): Promise<string[]> {
|
|
256
|
+
return this.readdirSync(path, cred);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
public async link(srcpath: string, dstpath: string, cred: Cred): Promise<void> {
|
|
260
|
+
return this.linkSync(srcpath, dstpath, cred);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
public async sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void> {
|
|
264
|
+
return this.syncSync(path, data, stats);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return _SyncFileSystem;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* @internal
|
|
272
|
+
*/
|
|
273
|
+
declare abstract class AsyncFileSystem extends FileSystem {
|
|
274
|
+
/**
|
|
275
|
+
* @hidden
|
|
276
|
+
*/
|
|
277
|
+
abstract _sync: FileSystem;
|
|
278
|
+
metadata(): FileSystemMetadata;
|
|
279
|
+
ready(): Promise<this>;
|
|
280
|
+
renameSync(oldPath: string, newPath: string, cred: Cred): void;
|
|
281
|
+
statSync(path: string, cred: Cred): Stats;
|
|
282
|
+
createFileSync(path: string, flag: string, mode: number, cred: Cred): File;
|
|
283
|
+
openFileSync(path: string, flag: string, cred: Cred): File;
|
|
284
|
+
unlinkSync(path: string, cred: Cred): void;
|
|
285
|
+
rmdirSync(path: string, cred: Cred): void;
|
|
286
|
+
mkdirSync(path: string, mode: number, cred: Cred): void;
|
|
287
|
+
readdirSync(path: string, cred: Cred): string[];
|
|
288
|
+
linkSync(srcpath: string, dstpath: string, cred: Cred): void;
|
|
289
|
+
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
type AsyncMethods = ExtractProperties<FileSystem, (...args) => Promise<unknown>>;
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* @internal
|
|
296
|
+
*/
|
|
297
|
+
type AsyncOperation = {
|
|
298
|
+
[K in keyof AsyncMethods]: [K, ...Parameters<FileSystem[K]>];
|
|
299
|
+
}[keyof AsyncMethods];
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Async() implements synchronous methods on an asynchronous file system
|
|
303
|
+
*
|
|
304
|
+
* Implementing classes must define a protected _sync property for the synchronous file system used as a cache.
|
|
305
|
+
* by:
|
|
306
|
+
*
|
|
307
|
+
* - Performing operations over the in-memory copy, while asynchronously pipelining them
|
|
308
|
+
* to the backing store.
|
|
309
|
+
* - During application loading, the contents of the async file system can be reloaded into
|
|
310
|
+
* the synchronous store, if desired.
|
|
311
|
+
*
|
|
312
|
+
*/
|
|
313
|
+
export function Async<T extends abstract new (...args) => FileSystem>(FS: T): (abstract new (...args) => AsyncFileSystem) & T {
|
|
314
|
+
abstract class _AsyncFileSystem extends FS implements AsyncFileSystem {
|
|
315
|
+
/**
|
|
316
|
+
* Queue of pending asynchronous operations.
|
|
317
|
+
*/
|
|
318
|
+
private _queue: AsyncOperation[] = [];
|
|
319
|
+
private _queueRunning: boolean = false;
|
|
320
|
+
private _isInitialized: boolean = false;
|
|
321
|
+
|
|
322
|
+
abstract _sync: FileSystem;
|
|
323
|
+
|
|
324
|
+
public async ready(): Promise<this> {
|
|
325
|
+
await this._sync.ready();
|
|
326
|
+
await super.ready();
|
|
327
|
+
if (this._isInitialized) {
|
|
328
|
+
return this;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
try {
|
|
332
|
+
await this.crossCopy('/');
|
|
333
|
+
this._isInitialized = true;
|
|
334
|
+
} catch (e) {
|
|
335
|
+
this._isInitialized = false;
|
|
336
|
+
throw e;
|
|
337
|
+
}
|
|
338
|
+
return this;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
public renameSync(oldPath: string, newPath: string, cred: Cred): void {
|
|
342
|
+
this._sync.renameSync(oldPath, newPath, cred);
|
|
343
|
+
this.queue('rename', oldPath, newPath, cred);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
public statSync(p: string, cred: Cred): Stats {
|
|
347
|
+
return this._sync.statSync(p, cred);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
public createFileSync(path: string, flag: string, mode: number, cred: Cred): PreloadFile<this> {
|
|
351
|
+
const file = this._sync.createFileSync(path, flag, mode, cred);
|
|
352
|
+
this.queue('createFile', path, flag, mode, cred);
|
|
353
|
+
const stats = file.statSync();
|
|
354
|
+
const buffer = new Uint8Array(stats.size);
|
|
355
|
+
file.readSync(buffer);
|
|
356
|
+
return new PreloadFile(this, path, flag, stats, buffer);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
public openFileSync(path: string, flag: string, cred: Cred): File {
|
|
360
|
+
return this._sync.openFileSync(path, flag, cred);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
public unlinkSync(p: string, cred: Cred): void {
|
|
364
|
+
this._sync.unlinkSync(p, cred);
|
|
365
|
+
this.queue('unlink', p, cred);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
public rmdirSync(p: string, cred: Cred): void {
|
|
369
|
+
this._sync.rmdirSync(p, cred);
|
|
370
|
+
this.queue('rmdir', p, cred);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
public mkdirSync(p: string, mode: number, cred: Cred): void {
|
|
374
|
+
this._sync.mkdirSync(p, mode, cred);
|
|
375
|
+
this.queue('mkdir', p, mode, cred);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
public readdirSync(p: string, cred: Cred): string[] {
|
|
379
|
+
return this._sync.readdirSync(p, cred);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
public linkSync(srcpath: string, dstpath: string, cred: Cred): void {
|
|
383
|
+
this._sync.linkSync(srcpath, dstpath, cred);
|
|
384
|
+
this.queue('link', srcpath, dstpath, cred);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
public syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void {
|
|
388
|
+
this._sync.syncSync(path, data, stats);
|
|
389
|
+
this.queue('sync', path, data, stats);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
public existsSync(p: string, cred: Cred): boolean {
|
|
393
|
+
return this._sync.existsSync(p, cred);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* @internal
|
|
398
|
+
*/
|
|
399
|
+
protected async crossCopy(p: string): Promise<void> {
|
|
400
|
+
const stats = await this.stat(p, rootCred);
|
|
401
|
+
if (stats.isDirectory()) {
|
|
402
|
+
if (p !== '/') {
|
|
403
|
+
const stats = await this.stat(p, rootCred);
|
|
404
|
+
this._sync.mkdirSync(p, stats.mode, stats.cred());
|
|
405
|
+
}
|
|
406
|
+
const files = await this.readdir(p, rootCred);
|
|
407
|
+
for (const file of files) {
|
|
408
|
+
await this.crossCopy(join(p, file));
|
|
409
|
+
}
|
|
410
|
+
} else {
|
|
411
|
+
const asyncFile = await this.openFile(p, parseFlag('r'), rootCred);
|
|
412
|
+
const syncFile = this._sync.createFileSync(p, parseFlag('w'), stats.mode, stats.cred());
|
|
413
|
+
try {
|
|
414
|
+
const buffer = new Uint8Array(stats.size);
|
|
415
|
+
await asyncFile.read(buffer);
|
|
416
|
+
syncFile.writeSync(buffer);
|
|
417
|
+
} finally {
|
|
418
|
+
await asyncFile.close();
|
|
419
|
+
syncFile.closeSync();
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* @internal
|
|
426
|
+
*/
|
|
427
|
+
private async _next(): Promise<void> {
|
|
428
|
+
if (this._queue.length == 0) {
|
|
429
|
+
this._queueRunning = false;
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const [method, ...args] = this._queue.shift()!;
|
|
434
|
+
// @ts-expect-error 2556 (since ...args is not correctly picked up as being a tuple)
|
|
435
|
+
await this[method](...args);
|
|
436
|
+
await this._next();
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* @internal
|
|
441
|
+
*/
|
|
442
|
+
private queue(...op: AsyncOperation) {
|
|
443
|
+
this._queue.push(op);
|
|
444
|
+
if (this._queueRunning) {
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
this._queueRunning = true;
|
|
449
|
+
this._next();
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
return _AsyncFileSystem;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* @internal
|
|
458
|
+
*/
|
|
459
|
+
declare abstract class ReadonlyFileSystem extends FileSystem {
|
|
460
|
+
metadata(): FileSystemMetadata;
|
|
461
|
+
rename(oldPath: string, newPath: string, cred: Cred): Promise<void>;
|
|
462
|
+
renameSync(oldPath: string, newPath: string, cred: Cred): void;
|
|
463
|
+
createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File>;
|
|
464
|
+
createFileSync(path: string, flag: string, mode: number, cred: Cred): File;
|
|
465
|
+
unlink(path: string, cred: Cred): Promise<void>;
|
|
466
|
+
unlinkSync(path: string, cred: Cred): void;
|
|
467
|
+
rmdir(path: string, cred: Cred): Promise<void>;
|
|
468
|
+
rmdirSync(path: string, cred: Cred): void;
|
|
469
|
+
mkdir(path: string, mode: number, cred: Cred): Promise<void>;
|
|
470
|
+
mkdirSync(path: string, mode: number, cred: Cred): void;
|
|
471
|
+
link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
|
|
472
|
+
linkSync(srcpath: string, dstpath: string, cred: Cred): void;
|
|
473
|
+
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
|
|
474
|
+
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Implements the non-readonly methods to throw `EROFS`
|
|
479
|
+
*/
|
|
480
|
+
export function Readonly<T extends abstract new (...args) => FileSystem>(FS: T): (abstract new (...args) => ReadonlyFileSystem) & T {
|
|
481
|
+
abstract class _ReadonlyFileSystem extends FS implements ReadonlyFileSystem {
|
|
482
|
+
public metadata(): FileSystemMetadata {
|
|
483
|
+
return { ...super.metadata(), readonly: true };
|
|
484
|
+
}
|
|
485
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
486
|
+
public async rename(oldPath: string, newPath: string, cred: Cred): Promise<void> {
|
|
487
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
public renameSync(oldPath: string, newPath: string, cred: Cred): void {
|
|
491
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
public async createFile(path: string, flag: string, mode: number, cred: Cred): Promise<File> {
|
|
495
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
public createFileSync(path: string, flag: string, mode: number, cred: Cred): File {
|
|
499
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
public async unlink(path: string, cred: Cred): Promise<void> {
|
|
503
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
public unlinkSync(path: string, cred: Cred): void {
|
|
507
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
public async rmdir(path: string, cred: Cred): Promise<void> {
|
|
511
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
public rmdirSync(path: string, cred: Cred): void {
|
|
515
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
public async mkdir(path: string, mode: number, cred: Cred): Promise<void> {
|
|
519
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
public mkdirSync(path: string, mode: number, cred: Cred): void {
|
|
523
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
public async link(srcpath: string, dstpath: string, cred: Cred): Promise<void> {
|
|
527
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
public linkSync(srcpath: string, dstpath: string, cred: Cred): void {
|
|
531
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
public async sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void> {
|
|
535
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
public syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void {
|
|
539
|
+
throw new ApiError(ErrorCode.EROFS);
|
|
540
|
+
}
|
|
541
|
+
/* eslint-enable @typescript-eslint/no-unused-vars */
|
|
542
|
+
}
|
|
543
|
+
return _ReadonlyFileSystem;
|
|
544
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export * from './ApiError.js';
|
|
2
|
+
export * from './backends/AsyncStore.js';
|
|
3
|
+
export * from './backends/InMemory.js';
|
|
4
|
+
export * from './backends/Index.js';
|
|
5
|
+
export * from './backends/Locked.js';
|
|
6
|
+
export * from './backends/Overlay.js';
|
|
7
|
+
export * from './backends/SyncStore.js';
|
|
8
|
+
export * from './backends/backend.js';
|
|
9
|
+
export * from './config.js';
|
|
10
|
+
export * from './cred.js';
|
|
11
|
+
export * from './file.js';
|
|
12
|
+
export * from './filesystem.js';
|
|
13
|
+
export * from './inode.js';
|
|
14
|
+
export * from './mutex.js';
|
|
15
|
+
export * from './stats.js';
|
|
16
|
+
export * from './utils.js';
|
|
17
|
+
|
|
18
|
+
export * from './emulation/index.js';
|
|
19
|
+
import * as fs from './emulation/index.js';
|
|
20
|
+
export { fs };
|
|
21
|
+
export default fs;
|