@zenfs/core 0.11.0 → 0.11.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.
- package/dist/backends/backend.d.ts +1 -2
- package/dist/backends/backend.js +0 -6
- package/dist/backends/fetch.d.ts +1 -1
- package/dist/backends/fetch.js +13 -11
- package/dist/backends/locked.d.ts +1 -1
- package/dist/backends/locked.js +34 -34
- package/dist/backends/memory.d.ts +1 -1
- package/dist/backends/port/fs.d.ts +1 -1
- package/dist/backends/port/fs.js +2 -1
- package/dist/backends/port/rpc.js +3 -1
- package/dist/backends/store/fs.d.ts +5 -5
- package/dist/backends/store/fs.js +1 -1
- package/dist/browser.min.js +3 -3
- package/dist/browser.min.js.map +3 -3
- package/dist/config.js +1 -1
- package/dist/emulation/promises.js +1 -2
- package/dist/emulation/sync.js +24 -40
- package/dist/filesystem.d.ts +6 -6
- package/dist/filesystem.js +11 -10
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/mutex.d.ts +1 -1
- package/dist/mutex.js +11 -11
- package/package.json +1 -1
- package/scripts/make-index.js +15 -12
- package/src/backends/backend.ts +3 -8
- package/src/backends/fetch.ts +13 -12
- package/src/backends/locked.ts +34 -34
- package/src/backends/memory.ts +1 -1
- package/src/backends/port/fs.ts +2 -1
- package/src/backends/port/rpc.ts +2 -1
- package/src/backends/store/fs.ts +5 -5
- package/src/config.ts +1 -1
- package/src/emulation/promises.ts +1 -2
- package/src/emulation/sync.ts +23 -41
- package/src/filesystem.ts +18 -17
- package/src/index.ts +2 -0
- package/src/mutex.ts +11 -11
|
@@ -33,7 +33,7 @@ export interface Backend<FS extends FileSystem = FileSystem, TOptions extends ob
|
|
|
33
33
|
/**
|
|
34
34
|
* Create a new instance of the backend
|
|
35
35
|
*/
|
|
36
|
-
create(options: TOptions): FS
|
|
36
|
+
create(options: TOptions): FS | Promise<FS>;
|
|
37
37
|
/**
|
|
38
38
|
* A name to identify the backend.
|
|
39
39
|
*/
|
|
@@ -64,7 +64,6 @@ export declare function isBackend(arg: unknown): arg is Backend;
|
|
|
64
64
|
* @internal
|
|
65
65
|
*/
|
|
66
66
|
export declare function checkOptions<T extends Backend>(backend: T, opts: Partial<OptionsOf<T>> & Record<string, unknown>): Promise<void>;
|
|
67
|
-
export declare function createBackend<B extends Backend>(backend: B, options?: Partial<OptionsOf<B>>): Promise<ReturnType<B['create']>>;
|
|
68
67
|
/**
|
|
69
68
|
* Specifies a file system backend type and its options.
|
|
70
69
|
*
|
package/dist/backends/backend.js
CHANGED
|
@@ -44,12 +44,6 @@ export async function checkOptions(backend, opts) {
|
|
|
44
44
|
// Otherwise: All good!
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
-
export async function createBackend(backend, options = {}) {
|
|
48
|
-
await checkOptions(backend, options);
|
|
49
|
-
const fs = backend.create(options);
|
|
50
|
-
await fs.ready();
|
|
51
|
-
return fs;
|
|
52
|
-
}
|
|
53
47
|
/**
|
|
54
48
|
* @internal
|
|
55
49
|
*/
|
package/dist/backends/fetch.d.ts
CHANGED
|
@@ -71,7 +71,7 @@ export declare const Fetch: {
|
|
|
71
71
|
readonly index: {
|
|
72
72
|
readonly type: readonly ["string", "object"];
|
|
73
73
|
readonly required: false;
|
|
74
|
-
readonly description: "URL to a file index as a JSON file or the file index object itself, generated with the
|
|
74
|
+
readonly description: "URL to a file index as a JSON file or the file index object itself, generated with the make-index script. Defaults to `index.json`.";
|
|
75
75
|
};
|
|
76
76
|
readonly baseUrl: {
|
|
77
77
|
readonly type: "string";
|
package/dist/backends/fetch.js
CHANGED
|
@@ -2,23 +2,23 @@ import { ErrnoError, Errno } from '../error.js';
|
|
|
2
2
|
import { NoSyncFile } from '../file.js';
|
|
3
3
|
import { Stats } from '../stats.js';
|
|
4
4
|
import { FileIndex, AsyncIndexFS } from './Index.js';
|
|
5
|
-
/**
|
|
6
|
-
* @hidden
|
|
7
|
-
*/
|
|
8
|
-
function convertError(e) {
|
|
9
|
-
throw new ErrnoError(Errno.EIO, e.message);
|
|
10
|
-
}
|
|
11
5
|
async function fetchFile(path, type) {
|
|
12
|
-
const response = await fetch(path).catch(
|
|
6
|
+
const response = await fetch(path).catch(e => {
|
|
7
|
+
throw new ErrnoError(Errno.EIO, e.message);
|
|
8
|
+
});
|
|
13
9
|
if (!response.ok) {
|
|
14
10
|
throw new ErrnoError(Errno.EIO, 'fetch failed: response returned code ' + response.status);
|
|
15
11
|
}
|
|
16
12
|
switch (type) {
|
|
17
13
|
case 'buffer':
|
|
18
|
-
const arrayBuffer = await response.arrayBuffer().catch(
|
|
14
|
+
const arrayBuffer = await response.arrayBuffer().catch(e => {
|
|
15
|
+
throw new ErrnoError(Errno.EIO, e.message);
|
|
16
|
+
});
|
|
19
17
|
return new Uint8Array(arrayBuffer);
|
|
20
18
|
case 'json':
|
|
21
|
-
return response.json().catch(
|
|
19
|
+
return response.json().catch(e => {
|
|
20
|
+
throw new ErrnoError(Errno.EIO, e.message);
|
|
21
|
+
});
|
|
22
22
|
default:
|
|
23
23
|
throw new ErrnoError(Errno.EINVAL, 'Invalid download type: ' + type);
|
|
24
24
|
}
|
|
@@ -28,7 +28,9 @@ async function fetchFile(path, type) {
|
|
|
28
28
|
* @hidden
|
|
29
29
|
*/
|
|
30
30
|
async function fetchSize(path) {
|
|
31
|
-
const response = await fetch(path, { method: 'HEAD' }).catch(
|
|
31
|
+
const response = await fetch(path, { method: 'HEAD' }).catch(e => {
|
|
32
|
+
throw new ErrnoError(Errno.EIO, e.message);
|
|
33
|
+
});
|
|
32
34
|
if (!response.ok) {
|
|
33
35
|
throw new ErrnoError(Errno.EIO, 'fetch failed: HEAD response returned code ' + response.status);
|
|
34
36
|
}
|
|
@@ -153,7 +155,7 @@ export const Fetch = {
|
|
|
153
155
|
index: {
|
|
154
156
|
type: ['string', 'object'],
|
|
155
157
|
required: false,
|
|
156
|
-
description: 'URL to a file index as a JSON file or the file index object itself, generated with the
|
|
158
|
+
description: 'URL to a file index as a JSON file or the file index object itself, generated with the make-index script. Defaults to `index.json`.',
|
|
157
159
|
},
|
|
158
160
|
baseUrl: {
|
|
159
161
|
type: 'string',
|
|
@@ -14,7 +14,7 @@ import type { Stats } from '../stats.js';
|
|
|
14
14
|
*/
|
|
15
15
|
export declare class LockedFS<FS extends FileSystem> implements FileSystem {
|
|
16
16
|
readonly fs: FS;
|
|
17
|
-
private
|
|
17
|
+
private mutex;
|
|
18
18
|
constructor(fs: FS);
|
|
19
19
|
ready(): Promise<void>;
|
|
20
20
|
metadata(): FileSystemMetadata;
|
package/dist/backends/locked.js
CHANGED
|
@@ -13,7 +13,7 @@ import { Mutex } from '../mutex.js';
|
|
|
13
13
|
export class LockedFS {
|
|
14
14
|
constructor(fs) {
|
|
15
15
|
this.fs = fs;
|
|
16
|
-
this.
|
|
16
|
+
this.mutex = new Mutex();
|
|
17
17
|
}
|
|
18
18
|
async ready() {
|
|
19
19
|
await this.fs.ready();
|
|
@@ -25,127 +25,127 @@ export class LockedFS {
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
async rename(oldPath, newPath, cred) {
|
|
28
|
-
await this.
|
|
28
|
+
await this.mutex.lock(oldPath);
|
|
29
29
|
await this.fs.rename(oldPath, newPath, cred);
|
|
30
|
-
this.
|
|
30
|
+
this.mutex.unlock(oldPath);
|
|
31
31
|
}
|
|
32
32
|
renameSync(oldPath, newPath, cred) {
|
|
33
|
-
if (this.
|
|
33
|
+
if (this.mutex.isLocked(oldPath)) {
|
|
34
34
|
throw ErrnoError.With('EBUSY', oldPath, 'rename');
|
|
35
35
|
}
|
|
36
36
|
return this.fs.renameSync(oldPath, newPath, cred);
|
|
37
37
|
}
|
|
38
38
|
async stat(path, cred) {
|
|
39
|
-
await this.
|
|
39
|
+
await this.mutex.lock(path);
|
|
40
40
|
const stats = await this.fs.stat(path, cred);
|
|
41
|
-
this.
|
|
41
|
+
this.mutex.unlock(path);
|
|
42
42
|
return stats;
|
|
43
43
|
}
|
|
44
44
|
statSync(path, cred) {
|
|
45
|
-
if (this.
|
|
45
|
+
if (this.mutex.isLocked(path)) {
|
|
46
46
|
throw ErrnoError.With('EBUSY', path, 'stat');
|
|
47
47
|
}
|
|
48
48
|
return this.fs.statSync(path, cred);
|
|
49
49
|
}
|
|
50
50
|
async openFile(path, flag, cred) {
|
|
51
|
-
await this.
|
|
51
|
+
await this.mutex.lock(path);
|
|
52
52
|
const fd = await this.fs.openFile(path, flag, cred);
|
|
53
|
-
this.
|
|
53
|
+
this.mutex.unlock(path);
|
|
54
54
|
return fd;
|
|
55
55
|
}
|
|
56
56
|
openFileSync(path, flag, cred) {
|
|
57
|
-
if (this.
|
|
57
|
+
if (this.mutex.isLocked(path)) {
|
|
58
58
|
throw ErrnoError.With('EBUSY', path, 'openFile');
|
|
59
59
|
}
|
|
60
60
|
return this.fs.openFileSync(path, flag, cred);
|
|
61
61
|
}
|
|
62
62
|
async createFile(path, flag, mode, cred) {
|
|
63
|
-
await this.
|
|
63
|
+
await this.mutex.lock(path);
|
|
64
64
|
const fd = await this.fs.createFile(path, flag, mode, cred);
|
|
65
|
-
this.
|
|
65
|
+
this.mutex.unlock(path);
|
|
66
66
|
return fd;
|
|
67
67
|
}
|
|
68
68
|
createFileSync(path, flag, mode, cred) {
|
|
69
|
-
if (this.
|
|
69
|
+
if (this.mutex.isLocked(path)) {
|
|
70
70
|
throw ErrnoError.With('EBUSY', path, 'createFile');
|
|
71
71
|
}
|
|
72
72
|
return this.fs.createFileSync(path, flag, mode, cred);
|
|
73
73
|
}
|
|
74
74
|
async unlink(path, cred) {
|
|
75
|
-
await this.
|
|
75
|
+
await this.mutex.lock(path);
|
|
76
76
|
await this.fs.unlink(path, cred);
|
|
77
|
-
this.
|
|
77
|
+
this.mutex.unlock(path);
|
|
78
78
|
}
|
|
79
79
|
unlinkSync(path, cred) {
|
|
80
|
-
if (this.
|
|
80
|
+
if (this.mutex.isLocked(path)) {
|
|
81
81
|
throw ErrnoError.With('EBUSY', path, 'unlink');
|
|
82
82
|
}
|
|
83
83
|
return this.fs.unlinkSync(path, cred);
|
|
84
84
|
}
|
|
85
85
|
async rmdir(path, cred) {
|
|
86
|
-
await this.
|
|
86
|
+
await this.mutex.lock(path);
|
|
87
87
|
await this.fs.rmdir(path, cred);
|
|
88
|
-
this.
|
|
88
|
+
this.mutex.unlock(path);
|
|
89
89
|
}
|
|
90
90
|
rmdirSync(path, cred) {
|
|
91
|
-
if (this.
|
|
91
|
+
if (this.mutex.isLocked(path)) {
|
|
92
92
|
throw ErrnoError.With('EBUSY', path, 'rmdir');
|
|
93
93
|
}
|
|
94
94
|
return this.fs.rmdirSync(path, cred);
|
|
95
95
|
}
|
|
96
96
|
async mkdir(path, mode, cred) {
|
|
97
|
-
await this.
|
|
97
|
+
await this.mutex.lock(path);
|
|
98
98
|
await this.fs.mkdir(path, mode, cred);
|
|
99
|
-
this.
|
|
99
|
+
this.mutex.unlock(path);
|
|
100
100
|
}
|
|
101
101
|
mkdirSync(path, mode, cred) {
|
|
102
|
-
if (this.
|
|
102
|
+
if (this.mutex.isLocked(path)) {
|
|
103
103
|
throw ErrnoError.With('EBUSY', path, 'mkdir');
|
|
104
104
|
}
|
|
105
105
|
return this.fs.mkdirSync(path, mode, cred);
|
|
106
106
|
}
|
|
107
107
|
async readdir(path, cred) {
|
|
108
|
-
await this.
|
|
108
|
+
await this.mutex.lock(path);
|
|
109
109
|
const files = await this.fs.readdir(path, cred);
|
|
110
|
-
this.
|
|
110
|
+
this.mutex.unlock(path);
|
|
111
111
|
return files;
|
|
112
112
|
}
|
|
113
113
|
readdirSync(path, cred) {
|
|
114
|
-
if (this.
|
|
114
|
+
if (this.mutex.isLocked(path)) {
|
|
115
115
|
throw ErrnoError.With('EBUSY', path, 'readdir');
|
|
116
116
|
}
|
|
117
117
|
return this.fs.readdirSync(path, cred);
|
|
118
118
|
}
|
|
119
119
|
async exists(path, cred) {
|
|
120
|
-
await this.
|
|
120
|
+
await this.mutex.lock(path);
|
|
121
121
|
const exists = await this.fs.exists(path, cred);
|
|
122
|
-
this.
|
|
122
|
+
this.mutex.unlock(path);
|
|
123
123
|
return exists;
|
|
124
124
|
}
|
|
125
125
|
existsSync(path, cred) {
|
|
126
|
-
if (this.
|
|
126
|
+
if (this.mutex.isLocked(path)) {
|
|
127
127
|
throw ErrnoError.With('EBUSY', path, 'exists');
|
|
128
128
|
}
|
|
129
129
|
return this.fs.existsSync(path, cred);
|
|
130
130
|
}
|
|
131
131
|
async link(srcpath, dstpath, cred) {
|
|
132
|
-
await this.
|
|
132
|
+
await this.mutex.lock(srcpath);
|
|
133
133
|
await this.fs.link(srcpath, dstpath, cred);
|
|
134
|
-
this.
|
|
134
|
+
this.mutex.unlock(srcpath);
|
|
135
135
|
}
|
|
136
136
|
linkSync(srcpath, dstpath, cred) {
|
|
137
|
-
if (this.
|
|
137
|
+
if (this.mutex.isLocked(srcpath)) {
|
|
138
138
|
throw ErrnoError.With('EBUSY', srcpath, 'link');
|
|
139
139
|
}
|
|
140
140
|
return this.fs.linkSync(srcpath, dstpath, cred);
|
|
141
141
|
}
|
|
142
142
|
async sync(path, data, stats) {
|
|
143
|
-
await this.
|
|
143
|
+
await this.mutex.lock(path);
|
|
144
144
|
await this.fs.sync(path, data, stats);
|
|
145
|
-
this.
|
|
145
|
+
this.mutex.unlock(path);
|
|
146
146
|
}
|
|
147
147
|
syncSync(path, data, stats) {
|
|
148
|
-
if (this.
|
|
148
|
+
if (this.mutex.isLocked(path)) {
|
|
149
149
|
throw ErrnoError.With('EBUSY', path, 'sync');
|
|
150
150
|
}
|
|
151
151
|
return this.fs.syncSync(path, data, stats);
|
|
@@ -79,7 +79,7 @@ export declare class PortFS extends PortFS_base {
|
|
|
79
79
|
/**
|
|
80
80
|
* @hidden
|
|
81
81
|
*/
|
|
82
|
-
_sync: import("../store/fs.js").StoreFS
|
|
82
|
+
_sync: import("../store/fs.js").StoreFS<import("../memory.js").InMemoryStore>;
|
|
83
83
|
/**
|
|
84
84
|
* Constructs a new PortFS instance that connects with ZenFS running on
|
|
85
85
|
* the specified port.
|
package/dist/backends/port/fs.js
CHANGED
|
@@ -39,7 +39,8 @@ export class PortFile extends File {
|
|
|
39
39
|
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.write');
|
|
40
40
|
}
|
|
41
41
|
async read(buffer, offset, length, position) {
|
|
42
|
-
|
|
42
|
+
const result = await this.rpc('read', buffer, offset, length, position);
|
|
43
|
+
return result;
|
|
43
44
|
}
|
|
44
45
|
readSync() {
|
|
45
46
|
throw ErrnoError.With('ENOSYS', this.path, 'PortFile.read');
|
|
@@ -17,10 +17,12 @@ export function request(request, { port, timeout = 1000, fs } = {}) {
|
|
|
17
17
|
const id = Math.random().toString(16).slice(10);
|
|
18
18
|
executors.set(id, { resolve, reject, fs });
|
|
19
19
|
port.postMessage({ ...request, _zenfs: true, id, stack });
|
|
20
|
-
setTimeout(() => {
|
|
20
|
+
const _ = setTimeout(() => {
|
|
21
21
|
const error = new ErrnoError(Errno.EIO, 'RPC Failed');
|
|
22
22
|
error.stack += stack;
|
|
23
23
|
reject(error);
|
|
24
|
+
if (typeof _ == 'object')
|
|
25
|
+
_.unref();
|
|
24
26
|
}, timeout);
|
|
25
27
|
});
|
|
26
28
|
}
|
|
@@ -5,20 +5,20 @@ import { type Ino, Inode } from '../../inode.js';
|
|
|
5
5
|
import { type Stats, FileType } from '../../stats.js';
|
|
6
6
|
import type { Store, Transaction } from './store.js';
|
|
7
7
|
/**
|
|
8
|
-
* A
|
|
8
|
+
* A file system which uses a key-value store.
|
|
9
9
|
*
|
|
10
10
|
* We use a unique ID for each node in the file system. The root node has a fixed ID.
|
|
11
11
|
* @todo Introduce Node ID caching.
|
|
12
12
|
* @todo Check modes.
|
|
13
13
|
* @internal
|
|
14
14
|
*/
|
|
15
|
-
export declare class StoreFS extends FileSystem {
|
|
15
|
+
export declare class StoreFS<T extends Store = Store> extends FileSystem {
|
|
16
16
|
private $store;
|
|
17
|
-
protected get store():
|
|
18
|
-
protected _store?:
|
|
17
|
+
protected get store(): T;
|
|
18
|
+
protected _store?: T;
|
|
19
19
|
private _initialized;
|
|
20
20
|
ready(): Promise<void>;
|
|
21
|
-
constructor($store:
|
|
21
|
+
constructor($store: T | Promise<T>);
|
|
22
22
|
metadata(): FileSystemMetadata;
|
|
23
23
|
/**
|
|
24
24
|
* Delete all contents stored in the file system.
|
|
@@ -8,7 +8,7 @@ import { FileType } from '../../stats.js';
|
|
|
8
8
|
import { encodeDirListing, encode, decodeDirListing } from '../../utils.js';
|
|
9
9
|
const maxInodeAllocTries = 5;
|
|
10
10
|
/**
|
|
11
|
-
* A
|
|
11
|
+
* A file system which uses a key-value store.
|
|
12
12
|
*
|
|
13
13
|
* We use a unique ID for each node in the file system. The root node has a fixed ID.
|
|
14
14
|
* @todo Introduce Node ID caching.
|