@zenfs/core 2.7.5 → 2.7.6
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.js +0 -2
- package/dist/backends/cow.d.ts +2 -2
- package/dist/backends/cow.js +6 -14
- package/dist/backends/passthrough.d.ts +0 -54
- package/dist/backends/passthrough.js +0 -54
- package/dist/backends/port.d.ts +2 -6
- package/dist/backends/port.js +3 -11
- package/dist/backends/store/fs.d.ts +0 -9
- package/dist/backends/store/fs.js +1 -21
- package/dist/backends/store/store.d.ts +1 -1
- package/dist/backends/store/store.js +1 -5
- package/dist/internal/contexts.d.ts +1 -2
- package/dist/internal/credentials.d.ts +0 -3
- package/dist/internal/file_index.js +0 -1
- package/dist/internal/index_fs.d.ts +2 -2
- package/dist/internal/index_fs.js +2 -2
- package/dist/internal/inode.d.ts +21 -43
- package/dist/internal/rpc.d.ts +16 -7
- package/dist/internal/rpc.js +2 -11
- package/dist/mixins/mutexed.d.ts +6 -41
- package/dist/mixins/mutexed.js +36 -109
- package/dist/mixins/sync.js +0 -2
- package/dist/node/async.js +2 -12
- package/dist/node/index.d.ts +1 -1
- package/dist/node/promises.d.ts +1 -6
- package/dist/node/promises.js +1 -1
- package/dist/node/stats.d.ts +25 -99
- package/dist/node/stats.js +18 -55
- package/dist/node/streams.d.ts +1 -37
- package/dist/node/sync.d.ts +1 -6
- package/dist/node/sync.js +2 -2
- package/dist/polyfills.js +9 -0
- package/dist/utils.d.ts +0 -4
- package/dist/vfs/acl.d.ts +1 -3
- package/dist/vfs/acl.js +1 -3
- package/dist/vfs/async.js +0 -5
- package/dist/vfs/dir.d.ts +3 -0
- package/dist/vfs/dir.js +4 -1
- package/dist/vfs/file.d.ts +1 -8
- package/dist/vfs/file.js +1 -3
- package/dist/vfs/sync.js +0 -1
- package/dist/vfs/vcache.js +0 -1
- package/package.json +1 -2
- package/tests/common/context.test.ts +1 -1
- package/tests/common/mutex.test.ts +0 -61
package/dist/backends/backend.js
CHANGED
|
@@ -55,9 +55,7 @@ export function checkOptions(backend, options) {
|
|
|
55
55
|
: typeof value === type || value?.constructor?.name === type;
|
|
56
56
|
if (Array.isArray(opt.type) ? opt.type.some(v => isType(v)) : isType(opt.type))
|
|
57
57
|
continue;
|
|
58
|
-
// The type of the value as a string
|
|
59
58
|
const type = typeof value == 'object' && 'constructor' in value ? value.constructor.name : typeof value;
|
|
60
|
-
// The expected type (as a string)
|
|
61
59
|
const name = (type) => (typeof type == 'function' ? (type.name != 'type' ? type.name : type.toString()) : type);
|
|
62
60
|
const expected = Array.isArray(opt.type) ? `one of ${opt.type.map(name).join(', ')}` : name(opt.type);
|
|
63
61
|
throw err(withErrno('EINVAL', `Incorrect type for "${optName}": ${type} (expected ${expected})`));
|
package/dist/backends/cow.d.ts
CHANGED
|
@@ -162,14 +162,14 @@ declare const _CopyOnWrite: {
|
|
|
162
162
|
};
|
|
163
163
|
type _CopyOnWrite = typeof _CopyOnWrite;
|
|
164
164
|
/**
|
|
165
|
-
*
|
|
165
|
+
* Makes a read-only filesystem writable by storing writes on a second, writable file system.
|
|
166
166
|
* Deletes are persisted via metadata stored on the writable file system.
|
|
167
167
|
* @category Backends and Configuration
|
|
168
168
|
*/
|
|
169
169
|
export interface CopyOnWrite extends _CopyOnWrite {
|
|
170
170
|
}
|
|
171
171
|
/**
|
|
172
|
-
*
|
|
172
|
+
* Makes a read-only filesystem writable by storing writes on a second, writable file system.
|
|
173
173
|
* Deletes are persisted via metadata stored on the writable file system.
|
|
174
174
|
* @category Backends and Configuration
|
|
175
175
|
* @internal
|
package/dist/backends/cow.js
CHANGED
|
@@ -141,7 +141,7 @@ export class CopyOnWriteFS extends FileSystem {
|
|
|
141
141
|
}
|
|
142
142
|
/* Note the layer's inode is not mutated, since it may be a persistent object.
|
|
143
143
|
`Inode` fields are accessors, so a copy must be explicit rather than a spread. */
|
|
144
|
-
return
|
|
144
|
+
return Object.assign(pick(inode, _inode_fields), { attributes: inode.attributes, ino });
|
|
145
145
|
}
|
|
146
146
|
/**
|
|
147
147
|
* @todo Consider trying to track information on the writable as well
|
|
@@ -252,25 +252,19 @@ export class CopyOnWriteFS extends FileSystem {
|
|
|
252
252
|
async unlink(path) {
|
|
253
253
|
if (!(await this.exists(path)))
|
|
254
254
|
throw withErrno('ENOENT');
|
|
255
|
-
if (await this.writable.exists(path))
|
|
255
|
+
if (await this.writable.exists(path))
|
|
256
256
|
await this.writable.unlink(path);
|
|
257
|
-
|
|
258
|
-
// if it still exists add to the delete log
|
|
259
|
-
if (await this.exists(path)) {
|
|
257
|
+
if (await this.exists(path))
|
|
260
258
|
this.journal.add('delete', path);
|
|
261
|
-
}
|
|
262
259
|
this.inos.delete(path);
|
|
263
260
|
}
|
|
264
261
|
unlinkSync(path) {
|
|
265
262
|
if (!this.existsSync(path))
|
|
266
263
|
throw withErrno('ENOENT');
|
|
267
|
-
if (this.writable.existsSync(path))
|
|
264
|
+
if (this.writable.existsSync(path))
|
|
268
265
|
this.writable.unlinkSync(path);
|
|
269
|
-
|
|
270
|
-
// if it still exists add to the delete log
|
|
271
|
-
if (this.existsSync(path)) {
|
|
266
|
+
if (this.existsSync(path))
|
|
272
267
|
this.journal.add('delete', path);
|
|
273
|
-
}
|
|
274
268
|
this.inos.delete(path);
|
|
275
269
|
}
|
|
276
270
|
async rmdir(path) {
|
|
@@ -283,7 +277,6 @@ export class CopyOnWriteFS extends FileSystem {
|
|
|
283
277
|
this.inos.delete(path);
|
|
284
278
|
return;
|
|
285
279
|
}
|
|
286
|
-
// Check if directory is empty.
|
|
287
280
|
if ((await this.readdir(path)).length)
|
|
288
281
|
throw withErrno('ENOTEMPTY');
|
|
289
282
|
this.journal.add('delete', path);
|
|
@@ -299,7 +292,6 @@ export class CopyOnWriteFS extends FileSystem {
|
|
|
299
292
|
this.inos.delete(path);
|
|
300
293
|
return;
|
|
301
294
|
}
|
|
302
|
-
// Check if directory is empty.
|
|
303
295
|
if (this.readdirSync(path).length)
|
|
304
296
|
throw withErrno('ENOTEMPTY');
|
|
305
297
|
this.journal.add('delete', path);
|
|
@@ -488,7 +480,7 @@ const _CopyOnWrite = {
|
|
|
488
480
|
},
|
|
489
481
|
};
|
|
490
482
|
/**
|
|
491
|
-
*
|
|
483
|
+
* Makes a read-only filesystem writable by storing writes on a second, writable file system.
|
|
492
484
|
* Deletes are persisted via metadata stored on the writable file system.
|
|
493
485
|
* @category Backends and Configuration
|
|
494
486
|
* @internal
|
|
@@ -16,21 +16,9 @@ export declare class PassthroughFS extends FileSystem {
|
|
|
16
16
|
constructor(nodeFS: NodeFS, prefix: string);
|
|
17
17
|
usage(): UsageInfo;
|
|
18
18
|
path(path: string): string;
|
|
19
|
-
/**
|
|
20
|
-
* Rename a file or directory.
|
|
21
|
-
*/
|
|
22
19
|
rename(oldPath: string, newPath: string): Promise<void>;
|
|
23
|
-
/**
|
|
24
|
-
* Rename a file or directory synchronously.
|
|
25
|
-
*/
|
|
26
20
|
renameSync(oldPath: string, newPath: string): void;
|
|
27
|
-
/**
|
|
28
|
-
* Get file statistics.
|
|
29
|
-
*/
|
|
30
21
|
stat(path: string): Promise<InodeLike>;
|
|
31
|
-
/**
|
|
32
|
-
* Get file statistics synchronously.
|
|
33
|
-
*/
|
|
34
22
|
statSync(path: string): InodeLike;
|
|
35
23
|
/**
|
|
36
24
|
* @privateRemarks
|
|
@@ -42,61 +30,19 @@ export declare class PassthroughFS extends FileSystem {
|
|
|
42
30
|
* Timestamps should be updated by the underlying file system.
|
|
43
31
|
*/
|
|
44
32
|
touchSync(path: string, metadata: InodeLike): void;
|
|
45
|
-
/**
|
|
46
|
-
* Unlink (delete) a file.
|
|
47
|
-
*/
|
|
48
33
|
unlink(path: string): Promise<void>;
|
|
49
|
-
/**
|
|
50
|
-
* Unlink (delete) a file synchronously.
|
|
51
|
-
*/
|
|
52
34
|
unlinkSync(path: string): void;
|
|
53
|
-
/**
|
|
54
|
-
* Create a directory.
|
|
55
|
-
*/
|
|
56
35
|
mkdir(path: string, options: CreationOptions): Promise<InodeLike>;
|
|
57
|
-
/**
|
|
58
|
-
* Create a directory synchronously.
|
|
59
|
-
*/
|
|
60
36
|
mkdirSync(path: string, options: CreationOptions): InodeLike;
|
|
61
|
-
/**
|
|
62
|
-
* Read the contents of a directory.
|
|
63
|
-
*/
|
|
64
37
|
readdir(path: string): Promise<string[]>;
|
|
65
|
-
/**
|
|
66
|
-
* Read the contents of a directory synchronously.
|
|
67
|
-
*/
|
|
68
38
|
readdirSync(path: string): string[];
|
|
69
|
-
/**
|
|
70
|
-
* Create a file.
|
|
71
|
-
*/
|
|
72
39
|
createFile(path: string, options: CreationOptions): Promise<InodeLike>;
|
|
73
|
-
/**
|
|
74
|
-
* Create a file synchronously.
|
|
75
|
-
*/
|
|
76
40
|
createFileSync(path: string, options: CreationOptions): InodeLike;
|
|
77
|
-
/**
|
|
78
|
-
* Remove a directory.
|
|
79
|
-
*/
|
|
80
41
|
rmdir(path: string): Promise<void>;
|
|
81
|
-
/**
|
|
82
|
-
* Remove a directory synchronously.
|
|
83
|
-
*/
|
|
84
42
|
rmdirSync(path: string): void;
|
|
85
|
-
/**
|
|
86
|
-
* Synchronize data to the file system.
|
|
87
|
-
*/
|
|
88
43
|
sync(): Promise<void>;
|
|
89
|
-
/**
|
|
90
|
-
* Synchronize data to the file system synchronously.
|
|
91
|
-
*/
|
|
92
44
|
syncSync(): void;
|
|
93
|
-
/**
|
|
94
|
-
* Create a hard link.
|
|
95
|
-
*/
|
|
96
45
|
link(target: string, link: string): Promise<void>;
|
|
97
|
-
/**
|
|
98
|
-
* Create a hard link synchronously.
|
|
99
|
-
*/
|
|
100
46
|
linkSync(target: string, link: string): void;
|
|
101
47
|
read(path: string, buffer: Uint8Array, offset: number, end: number): Promise<void>;
|
|
102
48
|
readSync(path: string, buffer: Uint8Array, offset: number, end: number): void;
|
|
@@ -72,27 +72,15 @@ export class PassthroughFS extends FileSystem {
|
|
|
72
72
|
path(path) {
|
|
73
73
|
return this.prefix + path;
|
|
74
74
|
}
|
|
75
|
-
/**
|
|
76
|
-
* Rename a file or directory.
|
|
77
|
-
*/
|
|
78
75
|
async rename(oldPath, newPath) {
|
|
79
76
|
await this.nodeFS.promises.rename(this.path(oldPath), this.path(newPath));
|
|
80
77
|
}
|
|
81
|
-
/**
|
|
82
|
-
* Rename a file or directory synchronously.
|
|
83
|
-
*/
|
|
84
78
|
renameSync(oldPath, newPath) {
|
|
85
79
|
this.nodeFS.renameSync(this.path(oldPath), this.path(newPath));
|
|
86
80
|
}
|
|
87
|
-
/**
|
|
88
|
-
* Get file statistics.
|
|
89
|
-
*/
|
|
90
81
|
async stat(path) {
|
|
91
82
|
return await this.nodeFS.promises.stat(this.path(path));
|
|
92
83
|
}
|
|
93
|
-
/**
|
|
94
|
-
* Get file statistics synchronously.
|
|
95
|
-
*/
|
|
96
84
|
statSync(path) {
|
|
97
85
|
return this.nodeFS.statSync(this.path(path));
|
|
98
86
|
}
|
|
@@ -135,47 +123,26 @@ export class PassthroughFS extends FileSystem {
|
|
|
135
123
|
err('Failed to chown passthrough file: ' + error.message);
|
|
136
124
|
}
|
|
137
125
|
}
|
|
138
|
-
/**
|
|
139
|
-
* Unlink (delete) a file.
|
|
140
|
-
*/
|
|
141
126
|
async unlink(path) {
|
|
142
127
|
await this.nodeFS.promises.unlink(this.path(path));
|
|
143
128
|
}
|
|
144
|
-
/**
|
|
145
|
-
* Unlink (delete) a file synchronously.
|
|
146
|
-
*/
|
|
147
129
|
unlinkSync(path) {
|
|
148
130
|
this.nodeFS.unlinkSync(this.path(path));
|
|
149
131
|
}
|
|
150
|
-
/**
|
|
151
|
-
* Create a directory.
|
|
152
|
-
*/
|
|
153
132
|
async mkdir(path, options) {
|
|
154
133
|
await this.nodeFS.promises.mkdir(this.path(path), options);
|
|
155
134
|
return await this.nodeFS.promises.stat(this.path(path));
|
|
156
135
|
}
|
|
157
|
-
/**
|
|
158
|
-
* Create a directory synchronously.
|
|
159
|
-
*/
|
|
160
136
|
mkdirSync(path, options) {
|
|
161
137
|
this.nodeFS.mkdirSync(this.path(path), options);
|
|
162
138
|
return this.nodeFS.statSync(this.path(path));
|
|
163
139
|
}
|
|
164
|
-
/**
|
|
165
|
-
* Read the contents of a directory.
|
|
166
|
-
*/
|
|
167
140
|
async readdir(path) {
|
|
168
141
|
return await this.nodeFS.promises.readdir(this.path(path));
|
|
169
142
|
}
|
|
170
|
-
/**
|
|
171
|
-
* Read the contents of a directory synchronously.
|
|
172
|
-
*/
|
|
173
143
|
readdirSync(path) {
|
|
174
144
|
return this.nodeFS.readdirSync(this.path(path));
|
|
175
145
|
}
|
|
176
|
-
/**
|
|
177
|
-
* Create a file.
|
|
178
|
-
*/
|
|
179
146
|
async createFile(path, options) {
|
|
180
147
|
if (isDirectory(options)) {
|
|
181
148
|
await this.nodeFS.promises.mkdir(this.path(path), { mode: options.mode });
|
|
@@ -198,9 +165,6 @@ export class PassthroughFS extends FileSystem {
|
|
|
198
165
|
}
|
|
199
166
|
return await this.nodeFS.promises.stat(this.path(path));
|
|
200
167
|
}
|
|
201
|
-
/**
|
|
202
|
-
* Create a file synchronously.
|
|
203
|
-
*/
|
|
204
168
|
createFileSync(path, options) {
|
|
205
169
|
if (isDirectory(options)) {
|
|
206
170
|
this.nodeFS.mkdirSync(this.path(path), { mode: options.mode });
|
|
@@ -211,39 +175,21 @@ export class PassthroughFS extends FileSystem {
|
|
|
211
175
|
}
|
|
212
176
|
return this.nodeFS.statSync(this.path(path));
|
|
213
177
|
}
|
|
214
|
-
/**
|
|
215
|
-
* Remove a directory.
|
|
216
|
-
*/
|
|
217
178
|
async rmdir(path) {
|
|
218
179
|
await this.nodeFS.promises.rmdir(this.path(path));
|
|
219
180
|
}
|
|
220
|
-
/**
|
|
221
|
-
* Remove a directory synchronously.
|
|
222
|
-
*/
|
|
223
181
|
rmdirSync(path) {
|
|
224
182
|
this.nodeFS.rmdirSync(this.path(path));
|
|
225
183
|
}
|
|
226
|
-
/**
|
|
227
|
-
* Synchronize data to the file system.
|
|
228
|
-
*/
|
|
229
184
|
async sync() {
|
|
230
185
|
warn('Sync on passthrough is unnecessary');
|
|
231
186
|
}
|
|
232
|
-
/**
|
|
233
|
-
* Synchronize data to the file system synchronously.
|
|
234
|
-
*/
|
|
235
187
|
syncSync() {
|
|
236
188
|
warn('Sync on passthrough is unnecessary');
|
|
237
189
|
}
|
|
238
|
-
/**
|
|
239
|
-
* Create a hard link.
|
|
240
|
-
*/
|
|
241
190
|
async link(target, link) {
|
|
242
191
|
await this.nodeFS.promises.link(this.path(target), this.path(link));
|
|
243
192
|
}
|
|
244
|
-
/**
|
|
245
|
-
* Create a hard link synchronously.
|
|
246
|
-
*/
|
|
247
193
|
linkSync(target, link) {
|
|
248
194
|
this.nodeFS.linkSync(this.path(target), this.path(link));
|
|
249
195
|
}
|
package/dist/backends/port.d.ts
CHANGED
|
@@ -33,13 +33,9 @@ export declare class PortFS<T extends RPC.Channel = RPC.Channel> extends PortFS_
|
|
|
33
33
|
readonly channel: T;
|
|
34
34
|
readonly timeout: number;
|
|
35
35
|
readonly port: RPC.Port<T>;
|
|
36
|
-
/**
|
|
37
|
-
* @hidden
|
|
38
|
-
*/
|
|
36
|
+
/** @hidden */
|
|
39
37
|
_sync: import("./index.js").StoreFS<import("./memory.js").InMemoryStore>;
|
|
40
|
-
/**
|
|
41
|
-
* Constructs a new PortFS instance that connects with the FS running on `options.port`.
|
|
42
|
-
*/
|
|
38
|
+
/** Constructs a new PortFS instance that connects with the FS running on `options.port`. */
|
|
43
39
|
constructor(channel: T, timeout?: number);
|
|
44
40
|
protected rpc<const T extends RPC.Method>(method: T, ...args: Parameters<RPC.Methods[T]>): Promise<Awaited<ReturnType<RPC.Methods[T]>>>;
|
|
45
41
|
ready(): Promise<void>;
|
package/dist/backends/port.js
CHANGED
|
@@ -19,13 +19,9 @@ export class PortFS extends Async(FileSystem) {
|
|
|
19
19
|
channel;
|
|
20
20
|
timeout;
|
|
21
21
|
port;
|
|
22
|
-
/**
|
|
23
|
-
* @hidden
|
|
24
|
-
*/
|
|
22
|
+
/** @hidden */
|
|
25
23
|
_sync = InMemory.create({ label: 'tmpfs:port' });
|
|
26
|
-
/**
|
|
27
|
-
* Constructs a new PortFS instance that connects with the FS running on `options.port`.
|
|
28
|
-
*/
|
|
24
|
+
/** Constructs a new PortFS instance that connects with the FS running on `options.port`. */
|
|
29
25
|
constructor(channel, timeout = 250) {
|
|
30
26
|
super(0x706f7274, 'portfs');
|
|
31
27
|
this.channel = channel;
|
|
@@ -34,11 +30,7 @@ export class PortFS extends Async(FileSystem) {
|
|
|
34
30
|
RPC.attach(this.port, RPC.handleResponse);
|
|
35
31
|
}
|
|
36
32
|
rpc(method, ...args) {
|
|
37
|
-
return RPC.request({ method, args }, {
|
|
38
|
-
port: this.port,
|
|
39
|
-
timeout: this.timeout,
|
|
40
|
-
fs: this,
|
|
41
|
-
});
|
|
33
|
+
return RPC.request({ method, args }, { port: this.port, timeout: this.timeout, fs: this });
|
|
42
34
|
}
|
|
43
35
|
async ready() {
|
|
44
36
|
await this.rpc('ready');
|
|
@@ -42,9 +42,6 @@ export declare class StoreFS<T extends Store = Store> extends FileSystem {
|
|
|
42
42
|
ready(): Promise<void>;
|
|
43
43
|
readySync(): void;
|
|
44
44
|
constructor(store: T);
|
|
45
|
-
/**
|
|
46
|
-
* @experimental
|
|
47
|
-
*/
|
|
48
45
|
usage(): UsageInfo;
|
|
49
46
|
/**
|
|
50
47
|
* Load an index into the StoreFS.
|
|
@@ -77,13 +74,7 @@ export declare class StoreFS<T extends Store = Store> extends FileSystem {
|
|
|
77
74
|
mkdirSync(path: string, options: CreationOptions): Inode;
|
|
78
75
|
readdir(path: string): Promise<string[]>;
|
|
79
76
|
readdirSync(path: string): string[];
|
|
80
|
-
/**
|
|
81
|
-
* Updated the inode and data node at `path`
|
|
82
|
-
*/
|
|
83
77
|
sync(): Promise<void>;
|
|
84
|
-
/**
|
|
85
|
-
* Updated the inode and data node at `path`
|
|
86
|
-
*/
|
|
87
78
|
syncSync(): void;
|
|
88
79
|
link(target: string, link: string): Promise<void>;
|
|
89
80
|
linkSync(target: string, link: string): void;
|
|
@@ -162,9 +162,6 @@ export class StoreFS extends FileSystem {
|
|
|
162
162
|
this.label = store.label;
|
|
163
163
|
debug(this.name + ': supports features: ' + this.store.flags?.join(', '));
|
|
164
164
|
}
|
|
165
|
-
/**
|
|
166
|
-
* @experimental
|
|
167
|
-
*/
|
|
168
165
|
usage() {
|
|
169
166
|
return (this.store.usage?.() || {
|
|
170
167
|
totalSpace: 0,
|
|
@@ -525,13 +522,7 @@ export class StoreFS extends FileSystem {
|
|
|
525
522
|
__disposeResources(env_12);
|
|
526
523
|
}
|
|
527
524
|
}
|
|
528
|
-
/**
|
|
529
|
-
* Updated the inode and data node at `path`
|
|
530
|
-
*/
|
|
531
525
|
async sync() { }
|
|
532
|
-
/**
|
|
533
|
-
* Updated the inode and data node at `path`
|
|
534
|
-
*/
|
|
535
526
|
syncSync() { }
|
|
536
527
|
async link(target, link) {
|
|
537
528
|
const env_13 = { stack: [], error: void 0, hasError: false };
|
|
@@ -758,16 +749,13 @@ export class StoreFS extends FileSystem {
|
|
|
758
749
|
crit('Store contains an invalid root inode. Refusing to populate tables');
|
|
759
750
|
return;
|
|
760
751
|
}
|
|
761
|
-
// Keep track of directories we have already traversed to avoid loops
|
|
762
752
|
const visitedDirectories = new Set();
|
|
763
753
|
let i = 0;
|
|
764
|
-
// Start BFS from root
|
|
765
754
|
const queue = [['/', rootIno]];
|
|
766
755
|
while (queue.length > 0) {
|
|
767
756
|
i++;
|
|
768
757
|
const [path, ino] = queue.shift();
|
|
769
758
|
this._add(ino, path);
|
|
770
|
-
// Get the inode data from the store
|
|
771
759
|
const inodeData = await tx.get(ino);
|
|
772
760
|
if (!inodeData) {
|
|
773
761
|
warn('Store is missing data for inode: ' + ino);
|
|
@@ -777,14 +765,10 @@ export class StoreFS extends FileSystem {
|
|
|
777
765
|
warn(`Invalid inode size for ino ${ino}: ${inodeData.length}`);
|
|
778
766
|
continue;
|
|
779
767
|
}
|
|
780
|
-
// Parse the raw data into our Inode object
|
|
781
768
|
const inode = new Inode(inodeData);
|
|
782
|
-
|
|
783
|
-
if (!isDirectory(inode) || visitedDirectories.has(ino)) {
|
|
769
|
+
if (!isDirectory(inode) || visitedDirectories.has(ino))
|
|
784
770
|
continue;
|
|
785
|
-
}
|
|
786
771
|
visitedDirectories.add(ino);
|
|
787
|
-
// Grab the directory listing from the store
|
|
788
772
|
const dirData = await tx.get(inode.data);
|
|
789
773
|
if (!dirData) {
|
|
790
774
|
warn('Store is missing directory data: ' + inode.data);
|
|
@@ -963,11 +947,9 @@ export class StoreFS extends FileSystem {
|
|
|
963
947
|
const { dir: parentPath, base: fname } = parse(path);
|
|
964
948
|
const parent = await this.findInode(tx, parentPath);
|
|
965
949
|
const listing = decodeDirListing((await tx.get(parent.data)) ?? _throw(withErrno('ENOENT')));
|
|
966
|
-
// Check if file already exists.
|
|
967
950
|
if (listing[fname])
|
|
968
951
|
throw withErrno('EEXIST');
|
|
969
952
|
const id = this.allocNew(path);
|
|
970
|
-
// Commit data.
|
|
971
953
|
const inode = new Inode({
|
|
972
954
|
...options,
|
|
973
955
|
ino: id,
|
|
@@ -977,7 +959,6 @@ export class StoreFS extends FileSystem {
|
|
|
977
959
|
});
|
|
978
960
|
await tx.set(inode.ino, inode);
|
|
979
961
|
await tx.set(inode.data, data);
|
|
980
|
-
// Update and commit parent directory listing.
|
|
981
962
|
listing[fname] = inode.ino;
|
|
982
963
|
await tx.set(parent.data, encodeDirListing(listing));
|
|
983
964
|
await tx.commit();
|
|
@@ -1025,7 +1006,6 @@ export class StoreFS extends FileSystem {
|
|
|
1025
1006
|
size: data.byteLength,
|
|
1026
1007
|
nlink: 1,
|
|
1027
1008
|
});
|
|
1028
|
-
// Update and commit parent directory listing.
|
|
1029
1009
|
tx.setSync(inode.ino, inode);
|
|
1030
1010
|
tx.setSync(inode.data, data);
|
|
1031
1011
|
listing[fname] = inode.ino;
|
|
@@ -162,7 +162,7 @@ export declare class WrappedTransaction<T extends Store = Store> {
|
|
|
162
162
|
data?: Uint8Array;
|
|
163
163
|
offset: number;
|
|
164
164
|
}[]>;
|
|
165
|
-
/**
|
|
165
|
+
/**
|
|
166
166
|
* List of keys modified in this transaction, if any.
|
|
167
167
|
*/
|
|
168
168
|
protected modifiedKeys: Set<number>;
|
|
@@ -109,7 +109,7 @@ export class WrappedTransaction {
|
|
|
109
109
|
* Allows us to roll back commits.
|
|
110
110
|
*/
|
|
111
111
|
originalData = new Map();
|
|
112
|
-
/**
|
|
112
|
+
/**
|
|
113
113
|
* List of keys modified in this transaction, if any.
|
|
114
114
|
*/
|
|
115
115
|
modifiedKeys = new Set();
|
|
@@ -154,11 +154,9 @@ export class WrappedTransaction {
|
|
|
154
154
|
async abort() {
|
|
155
155
|
if (this.done)
|
|
156
156
|
return;
|
|
157
|
-
// Rollback old values.
|
|
158
157
|
for (const [id, entries] of this.originalData) {
|
|
159
158
|
if (!this.modifiedKeys.has(id))
|
|
160
159
|
continue;
|
|
161
|
-
// Key didn't exist.
|
|
162
160
|
if (entries.some(ent => !ent.data)) {
|
|
163
161
|
await this.raw.remove(id);
|
|
164
162
|
this.fs._remove(id);
|
|
@@ -173,11 +171,9 @@ export class WrappedTransaction {
|
|
|
173
171
|
abortSync() {
|
|
174
172
|
if (this.done)
|
|
175
173
|
return;
|
|
176
|
-
// Rollback old values.
|
|
177
174
|
for (const [id, entries] of this.originalData) {
|
|
178
175
|
if (!this.modifiedKeys.has(id))
|
|
179
176
|
continue;
|
|
180
|
-
// Key didn't exist.
|
|
181
177
|
if (entries.some(ent => !ent.data)) {
|
|
182
178
|
this.raw.removeSync(id);
|
|
183
179
|
this.fs._remove(id);
|
|
@@ -20,8 +20,7 @@ export interface FSContext {
|
|
|
20
20
|
/** The unique ID of the context */
|
|
21
21
|
readonly id: number;
|
|
22
22
|
/**
|
|
23
|
-
* The absolute root path of the context
|
|
24
|
-
*
|
|
23
|
+
* The absolute root path of the context.
|
|
25
24
|
* Note the parent's root is not considered
|
|
26
25
|
*/
|
|
27
26
|
root: string;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
2
|
-
/* Note: this file is named file_index.ts because Typescript has special behavior regarding index.ts which can't be disabled. */
|
|
3
2
|
import { withErrno } from 'kerium';
|
|
4
3
|
import { sizeof } from 'memium';
|
|
5
4
|
import { isJSON, randomInt } from 'utilium';
|
|
@@ -40,8 +40,8 @@ export declare abstract class IndexFS extends FileSystem {
|
|
|
40
40
|
protected _mkdirSync?(path: string, options: CreationOptions): void;
|
|
41
41
|
mkdir(path: string, options: CreationOptions): Promise<Inode>;
|
|
42
42
|
mkdirSync(path: string, options: CreationOptions): Inode;
|
|
43
|
-
link(
|
|
44
|
-
linkSync(
|
|
43
|
+
link(): Promise<void>;
|
|
44
|
+
linkSync(): void;
|
|
45
45
|
readdir(path: string): Promise<string[]>;
|
|
46
46
|
readdirSync(path: string): string[];
|
|
47
47
|
sync(): Promise<void>;
|
|
@@ -200,10 +200,10 @@ export class IndexFS extends FileSystem {
|
|
|
200
200
|
this._mkdirSync?.(path, options);
|
|
201
201
|
return inode;
|
|
202
202
|
}
|
|
203
|
-
link(
|
|
203
|
+
link() {
|
|
204
204
|
throw withErrno('ENOSYS');
|
|
205
205
|
}
|
|
206
|
-
linkSync(
|
|
206
|
+
linkSync() {
|
|
207
207
|
throw withErrno('ENOSYS');
|
|
208
208
|
}
|
|
209
209
|
async readdir(path) {
|
package/dist/internal/inode.d.ts
CHANGED
|
@@ -32,61 +32,39 @@ export interface InodeFields {
|
|
|
32
32
|
data?: number;
|
|
33
33
|
flags?: number;
|
|
34
34
|
version?: number;
|
|
35
|
+
/** Extended attributes */
|
|
36
|
+
attributes?: Attributes;
|
|
35
37
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
* @internal
|
|
39
|
-
*/
|
|
40
|
-
export interface InodeLike<T extends number | bigint = number> extends InodeFields {
|
|
41
|
-
/**
|
|
42
|
-
* Size of the item in bytes.
|
|
43
|
-
* For directories/symlinks, this is normally the size of the struct that represents the item.
|
|
44
|
-
*/
|
|
38
|
+
export interface StatsLike<T extends number | bigint = number | bigint> {
|
|
39
|
+
/** Size of the item in bytes. For directories/symlinks, this may be the size of the struct that represents the item. */
|
|
45
40
|
size: T;
|
|
46
|
-
/**
|
|
47
|
-
* Unix-style file mode (e.g. 0o644) that includes the item type
|
|
48
|
-
*/
|
|
41
|
+
/** Unix-style file mode (e.g. 0o644) that includes the item type */
|
|
49
42
|
mode: T;
|
|
50
|
-
/**
|
|
51
|
-
* Time of last access, since epoch
|
|
52
|
-
*/
|
|
43
|
+
/** Time of last access, since epoch */
|
|
53
44
|
atimeMs: T;
|
|
54
|
-
/**
|
|
55
|
-
* Time of last modification, since epoch
|
|
56
|
-
*/
|
|
45
|
+
/** Time of last modification, since epoch */
|
|
57
46
|
mtimeMs: T;
|
|
58
|
-
/**
|
|
59
|
-
* Time of last time file status was changed, since epoch
|
|
60
|
-
*/
|
|
47
|
+
/** Time of last time file status was changed, since epoch */
|
|
61
48
|
ctimeMs: T;
|
|
62
|
-
/**
|
|
63
|
-
* Time of file creation, since epoch
|
|
64
|
-
*/
|
|
49
|
+
/** Time of file creation, since epoch */
|
|
65
50
|
birthtimeMs: T;
|
|
66
|
-
/**
|
|
67
|
-
* The id of the user that owns the file
|
|
68
|
-
*/
|
|
51
|
+
/** The id of the user that owns the file */
|
|
69
52
|
uid: T;
|
|
70
|
-
/**
|
|
71
|
-
* The id of the group that owns the file
|
|
72
|
-
*/
|
|
53
|
+
/** The id of the group that owns the file */
|
|
73
54
|
gid: T;
|
|
74
|
-
/**
|
|
75
|
-
* Inode number
|
|
76
|
-
*/
|
|
55
|
+
/** Inode number */
|
|
77
56
|
ino: T;
|
|
78
|
-
/**
|
|
79
|
-
* Number of hard links
|
|
80
|
-
*/
|
|
57
|
+
/** Number of hard links */
|
|
81
58
|
nlink: T;
|
|
82
|
-
/**
|
|
83
|
-
* Device ID for special files
|
|
84
|
-
*/
|
|
59
|
+
/** Device ID for special files */
|
|
85
60
|
rdev: T;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* @category Internals
|
|
64
|
+
* @internal
|
|
65
|
+
* @todo [breaking] switch fully to using bigints
|
|
66
|
+
*/
|
|
67
|
+
export interface InodeLike<T extends number | bigint = number> extends InodeFields, StatsLike<T> {
|
|
90
68
|
}
|
|
91
69
|
/**
|
|
92
70
|
* @internal @hidden
|
package/dist/internal/rpc.d.ts
CHANGED
|
@@ -100,15 +100,24 @@ export interface Message {
|
|
|
100
100
|
method: Method;
|
|
101
101
|
stack: string;
|
|
102
102
|
}
|
|
103
|
-
export interface
|
|
103
|
+
export interface RequestInit<TMethod extends Method = Method> {
|
|
104
104
|
method: TMethod;
|
|
105
105
|
args: Parameters<Methods[TMethod]>;
|
|
106
106
|
}
|
|
107
|
-
export
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
export type Request<TMethod extends Method = Method> = {
|
|
108
|
+
[K in Method]: Message & RequestInit<K>;
|
|
109
|
+
}[TMethod];
|
|
110
|
+
export type Response<TMethod extends Method = Method> = {
|
|
111
|
+
[K in Method]: Message & {
|
|
112
|
+
error?: WithOptional<ExceptionJSON, 'code' | 'errno'>;
|
|
113
|
+
method: K;
|
|
114
|
+
/**
|
|
115
|
+
* This is undefined if an error occurs, and we check it at runtime.
|
|
116
|
+
* We don't do the type stuff because Typescript gets confused
|
|
117
|
+
*/
|
|
118
|
+
value: ReturnType<Methods[K]>;
|
|
119
|
+
};
|
|
120
|
+
}[TMethod];
|
|
112
121
|
/**
|
|
113
122
|
* Encode a RPC message as a string using JSON.
|
|
114
123
|
* This is only done when structured cloning is not available.
|
|
@@ -130,7 +139,7 @@ export interface Executor extends PromiseWithResolvers<any> {
|
|
|
130
139
|
fs: PortFS;
|
|
131
140
|
timeout: ReturnType<typeof setTimeout>;
|
|
132
141
|
}
|
|
133
|
-
export declare function request<const
|
|
142
|
+
export declare function request<const Init extends RequestInit, TValue>(request: Init, { port, timeout: ms, fs }: Partial<Options> & {
|
|
134
143
|
fs: PortFS;
|
|
135
144
|
}): Promise<TValue>;
|
|
136
145
|
export declare function handleResponse<const TMethod extends Method>(response: Response<TMethod>): void;
|