@zenfs/core 1.0.9 → 1.0.11
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 +4 -8
- package/dist/backends/backend.js +7 -11
- package/dist/backends/fetch.d.ts +2 -4
- package/dist/backends/fetch.js +1 -3
- package/dist/backends/memory.d.ts +1 -1
- package/dist/backends/overlay.d.ts +9 -5
- package/dist/backends/overlay.js +128 -55
- package/dist/backends/port/fs.d.ts +12 -17
- package/dist/backends/port/fs.js +5 -8
- package/dist/backends/port/rpc.d.ts +1 -1
- package/dist/backends/store/fs.d.ts +8 -10
- package/dist/backends/store/fs.js +30 -49
- package/dist/backends/store/simple.d.ts +1 -1
- package/dist/backends/store/simple.js +1 -1
- package/dist/backends/store/store.d.ts +7 -13
- package/dist/config.d.ts +5 -5
- package/dist/config.js +26 -26
- package/dist/emulation/async.d.ts +21 -176
- package/dist/emulation/async.js +17 -111
- package/dist/emulation/dir.d.ts +0 -1
- package/dist/emulation/path.d.ts +0 -4
- package/dist/emulation/path.js +4 -8
- package/dist/emulation/promises.d.ts +31 -121
- package/dist/emulation/promises.js +30 -97
- package/dist/emulation/shared.d.ts +7 -3
- package/dist/emulation/shared.js +8 -5
- package/dist/emulation/streams.d.ts +0 -3
- package/dist/emulation/sync.d.ts +25 -178
- package/dist/emulation/sync.js +36 -129
- package/dist/emulation/watchers.d.ts +0 -4
- package/dist/error.d.ts +11 -11
- package/dist/error.js +8 -10
- package/dist/file.d.ts +50 -171
- package/dist/file.js +33 -115
- package/dist/filesystem.d.ts +10 -62
- package/dist/filesystem.js +5 -6
- package/dist/mixins/async.d.ts +4 -6
- package/dist/mixins/async.js +3 -1
- package/dist/mixins/mutexed.d.ts +4 -4
- package/dist/mixins/mutexed.js +7 -5
- package/dist/mixins/readonly.js +14 -15
- package/dist/mixins/shared.d.ts +5 -5
- package/dist/mixins/sync.d.ts +2 -2
- package/dist/stats.d.ts +21 -37
- package/dist/stats.js +9 -21
- package/dist/utils.d.ts +1 -3
- package/package.json +4 -4
- package/src/backends/backend.ts +7 -11
- package/src/backends/fetch.ts +2 -4
- package/src/backends/memory.ts +1 -1
- package/src/backends/overlay.ts +49 -40
- package/src/backends/port/fs.ts +11 -14
- package/src/backends/port/rpc.ts +1 -0
- package/src/backends/store/fs.ts +30 -46
- package/src/backends/store/simple.ts +1 -1
- package/src/backends/store/store.ts +7 -13
- package/src/config.ts +26 -26
- package/src/emulation/async.ts +28 -178
- package/src/emulation/path.ts +4 -11
- package/src/emulation/promises.ts +34 -116
- package/src/emulation/shared.ts +8 -6
- package/src/emulation/sync.ts +41 -185
- package/src/error.ts +7 -11
- package/src/file.ts +47 -180
- package/src/filesystem.ts +14 -65
- package/src/mixins/async.ts +4 -6
- package/src/mixins/mutexed.ts +4 -4
- package/src/mixins/readonly.ts +15 -15
- package/src/mixins/shared.ts +5 -5
- package/src/mixins/sync.ts +3 -3
- package/src/stats.ts +21 -38
|
@@ -72,15 +72,13 @@ export type OptionsOf<T extends Backend> = T extends Backend<FileSystem, infer T
|
|
|
72
72
|
* @internal
|
|
73
73
|
*/
|
|
74
74
|
export type FilesystemOf<T extends Backend> = T extends Backend<infer FS> ? FS : never;
|
|
75
|
-
/**
|
|
76
|
-
* @internal
|
|
77
|
-
*/
|
|
75
|
+
/** @internal */
|
|
78
76
|
export declare function isBackend(arg: unknown): arg is Backend;
|
|
79
77
|
/**
|
|
80
|
-
* Checks that
|
|
78
|
+
* Checks that `options` object is valid for the file system options.
|
|
81
79
|
* @internal
|
|
82
80
|
*/
|
|
83
|
-
export declare function checkOptions<T extends Backend>(backend: T,
|
|
81
|
+
export declare function checkOptions<T extends Backend>(backend: T, options: Record<string, unknown>): Promise<void>;
|
|
84
82
|
/**
|
|
85
83
|
* Specifies a file system backend type and its options.
|
|
86
84
|
*
|
|
@@ -91,8 +89,6 @@ export declare function checkOptions<T extends Backend>(backend: T, opts: Record
|
|
|
91
89
|
export type BackendConfiguration<T extends Backend> = OptionsOf<T> & Partial<SharedConfig> & {
|
|
92
90
|
backend: T;
|
|
93
91
|
};
|
|
94
|
-
/**
|
|
95
|
-
* @internal
|
|
96
|
-
*/
|
|
92
|
+
/** @internal */
|
|
97
93
|
export declare function isBackendConfig<T extends Backend>(arg: unknown): arg is BackendConfiguration<T>;
|
|
98
94
|
export {};
|
package/dist/backends/backend.js
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
1
|
import { ErrnoError, Errno } from '../error.js';
|
|
2
2
|
import { levenshtein } from '../utils.js';
|
|
3
|
-
/**
|
|
4
|
-
* @internal
|
|
5
|
-
*/
|
|
3
|
+
/** @internal */
|
|
6
4
|
export function isBackend(arg) {
|
|
7
5
|
return arg != null && typeof arg == 'object' && 'isAvailable' in arg && typeof arg.isAvailable == 'function' && 'create' in arg && typeof arg.create == 'function';
|
|
8
6
|
}
|
|
9
7
|
/**
|
|
10
|
-
* Checks that
|
|
8
|
+
* Checks that `options` object is valid for the file system options.
|
|
11
9
|
* @internal
|
|
12
10
|
*/
|
|
13
|
-
export async function checkOptions(backend,
|
|
14
|
-
if (typeof
|
|
11
|
+
export async function checkOptions(backend, options) {
|
|
12
|
+
if (typeof options != 'object' || options === null) {
|
|
15
13
|
throw new ErrnoError(Errno.EINVAL, 'Invalid options');
|
|
16
14
|
}
|
|
17
15
|
// Check for required options.
|
|
18
16
|
for (const [optName, opt] of Object.entries(backend.options)) {
|
|
19
|
-
const providedValue =
|
|
17
|
+
const providedValue = options?.[optName];
|
|
20
18
|
if (providedValue === undefined || providedValue === null) {
|
|
21
19
|
if (!opt.required) {
|
|
22
20
|
continue;
|
|
@@ -24,7 +22,7 @@ export async function checkOptions(backend, opts) {
|
|
|
24
22
|
/* Required option not provided.
|
|
25
23
|
if any incorrect options provided, which ones are close to the provided one?
|
|
26
24
|
(edit distance 5 === close)*/
|
|
27
|
-
const incorrectOptions = Object.keys(
|
|
25
|
+
const incorrectOptions = Object.keys(options)
|
|
28
26
|
.filter(o => !(o in backend.options))
|
|
29
27
|
.map((a) => {
|
|
30
28
|
return { str: a, distance: levenshtein(optName, a) };
|
|
@@ -44,9 +42,7 @@ export async function checkOptions(backend, opts) {
|
|
|
44
42
|
// Otherwise: All good!
|
|
45
43
|
}
|
|
46
44
|
}
|
|
47
|
-
/**
|
|
48
|
-
* @internal
|
|
49
|
-
*/
|
|
45
|
+
/** @internal */
|
|
50
46
|
export function isBackendConfig(arg) {
|
|
51
47
|
return arg != null && typeof arg == 'object' && 'backend' in arg && isBackend(arg.backend);
|
|
52
48
|
}
|
package/dist/backends/fetch.d.ts
CHANGED
|
@@ -41,9 +41,7 @@ export declare class FetchFS extends IndexFS {
|
|
|
41
41
|
constructor({ index, baseUrl }: FetchOptions);
|
|
42
42
|
metadata(): FileSystemMetadata;
|
|
43
43
|
/**
|
|
44
|
-
* Preload the
|
|
45
|
-
* @param path
|
|
46
|
-
* @param buffer
|
|
44
|
+
* Preload the `path` into the index.
|
|
47
45
|
*/
|
|
48
46
|
preload(path: string, buffer: Uint8Array): void;
|
|
49
47
|
/**
|
|
@@ -70,7 +68,7 @@ declare const _Fetch: {
|
|
|
70
68
|
readonly create: (options: FetchOptions) => FetchFS;
|
|
71
69
|
};
|
|
72
70
|
type _Fetch = typeof _Fetch;
|
|
73
|
-
interface Fetch extends _Fetch {
|
|
71
|
+
export interface Fetch extends _Fetch {
|
|
74
72
|
}
|
|
75
73
|
export declare const Fetch: Fetch;
|
|
76
74
|
export {};
|
package/dist/backends/fetch.js
CHANGED
|
@@ -69,18 +69,22 @@ export declare class UnmutexedOverlayFS extends FileSystem {
|
|
|
69
69
|
private checkInitialized;
|
|
70
70
|
private checkPath;
|
|
71
71
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
72
|
+
* Create the needed parent directories on the writable storage should they not exist.
|
|
73
|
+
* Use modes from the read-only storage.
|
|
74
74
|
*/
|
|
75
75
|
private createParentDirectoriesSync;
|
|
76
|
+
/**
|
|
77
|
+
* Create the needed parent directories on the writable storage should they not exist.
|
|
78
|
+
* Use modes from the read-only storage.
|
|
79
|
+
*/
|
|
76
80
|
private createParentDirectories;
|
|
77
81
|
/**
|
|
78
82
|
* Helper function:
|
|
79
83
|
* - Ensures p is on writable before proceeding. Throws an error if it doesn't exist.
|
|
80
84
|
* - Calls f to perform operation on writable.
|
|
81
85
|
*/
|
|
82
|
-
private
|
|
83
|
-
private
|
|
86
|
+
private copyForWriteSync;
|
|
87
|
+
private copyForWrite;
|
|
84
88
|
/**
|
|
85
89
|
* Copy from readable to writable storage.
|
|
86
90
|
* PRECONDITION: File does not exist on writable storage.
|
|
@@ -117,7 +121,7 @@ declare const _Overlay: {
|
|
|
117
121
|
readonly create: (options: OverlayOptions) => OverlayFS;
|
|
118
122
|
};
|
|
119
123
|
type _Overlay = typeof _Overlay;
|
|
120
|
-
interface Overlay extends _Overlay {
|
|
124
|
+
export interface Overlay extends _Overlay {
|
|
121
125
|
}
|
|
122
126
|
export declare const Overlay: Overlay;
|
|
123
127
|
export {};
|
package/dist/backends/overlay.js
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
+
var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
|
|
2
|
+
if (value !== null && value !== void 0) {
|
|
3
|
+
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
4
|
+
var dispose, inner;
|
|
5
|
+
if (async) {
|
|
6
|
+
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
7
|
+
dispose = value[Symbol.asyncDispose];
|
|
8
|
+
}
|
|
9
|
+
if (dispose === void 0) {
|
|
10
|
+
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
11
|
+
dispose = value[Symbol.dispose];
|
|
12
|
+
if (async) inner = dispose;
|
|
13
|
+
}
|
|
14
|
+
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
15
|
+
if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
|
|
16
|
+
env.stack.push({ value: value, dispose: dispose, async: async });
|
|
17
|
+
}
|
|
18
|
+
else if (async) {
|
|
19
|
+
env.stack.push({ async: true });
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
};
|
|
23
|
+
var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
|
|
24
|
+
return function (env) {
|
|
25
|
+
function fail(e) {
|
|
26
|
+
env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
27
|
+
env.hasError = true;
|
|
28
|
+
}
|
|
29
|
+
function next() {
|
|
30
|
+
while (env.stack.length) {
|
|
31
|
+
var rec = env.stack.pop();
|
|
32
|
+
try {
|
|
33
|
+
var result = rec.dispose && rec.dispose.call(rec.value);
|
|
34
|
+
if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
fail(e);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (env.hasError) throw env.error;
|
|
41
|
+
}
|
|
42
|
+
return next();
|
|
43
|
+
};
|
|
44
|
+
})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
45
|
+
var e = new Error(message);
|
|
46
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
47
|
+
});
|
|
1
48
|
import { dirname } from '../emulation/path.js';
|
|
2
49
|
import { Errno, ErrnoError } from '../error.js';
|
|
3
50
|
import { PreloadFile, parseFlag } from '../file.js';
|
|
@@ -5,9 +52,7 @@ import { FileSystem } from '../filesystem.js';
|
|
|
5
52
|
import { Mutexed } from '../mixins/mutexed.js';
|
|
6
53
|
import { Stats } from '../stats.js';
|
|
7
54
|
import { decode, encode } from '../utils.js';
|
|
8
|
-
/**
|
|
9
|
-
* @internal
|
|
10
|
-
*/
|
|
55
|
+
/** @internal */
|
|
11
56
|
const deletionLogPath = '/.deleted';
|
|
12
57
|
/**
|
|
13
58
|
* OverlayFS makes a read-only filesystem writable by storing writes on a second, writable file system.
|
|
@@ -47,14 +92,14 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
47
92
|
};
|
|
48
93
|
}
|
|
49
94
|
async sync(path, data, stats) {
|
|
50
|
-
await this.
|
|
95
|
+
await this.copyForWrite(path);
|
|
51
96
|
if (!(await this.writable.exists(path))) {
|
|
52
97
|
await this.writable.createFile(path, 'w', 0o644);
|
|
53
98
|
}
|
|
54
99
|
await this.writable.sync(path, data, stats);
|
|
55
100
|
}
|
|
56
101
|
syncSync(path, data, stats) {
|
|
57
|
-
this.
|
|
102
|
+
this.copyForWriteSync(path);
|
|
58
103
|
this.writable.syncSync(path, data, stats);
|
|
59
104
|
}
|
|
60
105
|
/**
|
|
@@ -92,6 +137,7 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
92
137
|
this.checkInitialized();
|
|
93
138
|
this.checkPath(oldPath);
|
|
94
139
|
this.checkPath(newPath);
|
|
140
|
+
await this.copyForWrite(oldPath);
|
|
95
141
|
try {
|
|
96
142
|
await this.writable.rename(oldPath, newPath);
|
|
97
143
|
}
|
|
@@ -105,6 +151,7 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
105
151
|
this.checkInitialized();
|
|
106
152
|
this.checkPath(oldPath);
|
|
107
153
|
this.checkPath(newPath);
|
|
154
|
+
this.copyForWriteSync(oldPath);
|
|
108
155
|
try {
|
|
109
156
|
this.writable.renameSync(oldPath, newPath);
|
|
110
157
|
}
|
|
@@ -124,7 +171,7 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
124
171
|
throw ErrnoError.With('ENOENT', path, 'stat');
|
|
125
172
|
}
|
|
126
173
|
const oldStat = new Stats(await this.readable.stat(path));
|
|
127
|
-
// Make the oldStat's mode writable.
|
|
174
|
+
// Make the oldStat's mode writable.
|
|
128
175
|
oldStat.mode |= 0o222;
|
|
129
176
|
return oldStat;
|
|
130
177
|
}
|
|
@@ -139,7 +186,7 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
139
186
|
throw ErrnoError.With('ENOENT', path, 'stat');
|
|
140
187
|
}
|
|
141
188
|
const oldStat = new Stats(this.readable.statSync(path));
|
|
142
|
-
// Make the oldStat's mode writable.
|
|
189
|
+
// Make the oldStat's mode writable.
|
|
143
190
|
oldStat.mode |= 0o222;
|
|
144
191
|
return oldStat;
|
|
145
192
|
}
|
|
@@ -150,7 +197,7 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
150
197
|
}
|
|
151
198
|
// Create an OverlayFile.
|
|
152
199
|
const file = await this.readable.openFile(path, parseFlag('r'));
|
|
153
|
-
const stats =
|
|
200
|
+
const stats = await file.stat();
|
|
154
201
|
const { buffer } = await file.read(new Uint8Array(stats.size));
|
|
155
202
|
return new PreloadFile(this, path, flag, stats, buffer);
|
|
156
203
|
}
|
|
@@ -160,7 +207,7 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
160
207
|
}
|
|
161
208
|
// Create an OverlayFile.
|
|
162
209
|
const file = this.readable.openFileSync(path, parseFlag('r'));
|
|
163
|
-
const stats =
|
|
210
|
+
const stats = file.statSync();
|
|
164
211
|
const data = new Uint8Array(stats.size);
|
|
165
212
|
file.readSync(data);
|
|
166
213
|
return new PreloadFile(this, path, flag, stats, data);
|
|
@@ -177,10 +224,12 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
177
224
|
}
|
|
178
225
|
async link(srcpath, dstpath) {
|
|
179
226
|
this.checkInitialized();
|
|
227
|
+
await this.copyForWrite(srcpath);
|
|
180
228
|
await this.writable.link(srcpath, dstpath);
|
|
181
229
|
}
|
|
182
230
|
linkSync(srcpath, dstpath) {
|
|
183
231
|
this.checkInitialized();
|
|
232
|
+
this.copyForWriteSync(srcpath);
|
|
184
233
|
this.writable.linkSync(srcpath, dstpath);
|
|
185
234
|
}
|
|
186
235
|
async unlink(path) {
|
|
@@ -219,15 +268,14 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
219
268
|
if (await this.writable.exists(path)) {
|
|
220
269
|
await this.writable.rmdir(path);
|
|
221
270
|
}
|
|
222
|
-
if (await this.exists(path)) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
await this.deletePath(path);
|
|
229
|
-
}
|
|
271
|
+
if (!(await this.exists(path))) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
// Check if directory is empty.
|
|
275
|
+
if ((await this.readdir(path)).length) {
|
|
276
|
+
throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
|
|
230
277
|
}
|
|
278
|
+
await this.deletePath(path);
|
|
231
279
|
}
|
|
232
280
|
rmdirSync(path) {
|
|
233
281
|
this.checkInitialized();
|
|
@@ -237,15 +285,14 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
237
285
|
if (this.writable.existsSync(path)) {
|
|
238
286
|
this.writable.rmdirSync(path);
|
|
239
287
|
}
|
|
240
|
-
if (this.existsSync(path)) {
|
|
241
|
-
|
|
242
|
-
if (this.readdirSync(path).length > 0) {
|
|
243
|
-
throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
void this.deletePath(path);
|
|
247
|
-
}
|
|
288
|
+
if (!this.existsSync(path)) {
|
|
289
|
+
return;
|
|
248
290
|
}
|
|
291
|
+
// Check if directory is empty.
|
|
292
|
+
if (this.readdirSync(path).length) {
|
|
293
|
+
throw ErrnoError.With('ENOTEMPTY', path, 'rmdir');
|
|
294
|
+
}
|
|
295
|
+
void this.deletePath(path);
|
|
249
296
|
}
|
|
250
297
|
async mkdir(path, mode) {
|
|
251
298
|
this.checkInitialized();
|
|
@@ -372,8 +419,8 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
372
419
|
}
|
|
373
420
|
}
|
|
374
421
|
/**
|
|
375
|
-
*
|
|
376
|
-
*
|
|
422
|
+
* Create the needed parent directories on the writable storage should they not exist.
|
|
423
|
+
* Use modes from the read-only storage.
|
|
377
424
|
*/
|
|
378
425
|
createParentDirectoriesSync(path) {
|
|
379
426
|
let parent = dirname(path);
|
|
@@ -386,6 +433,10 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
386
433
|
this.writable.mkdirSync(path, this.statSync(path).mode);
|
|
387
434
|
}
|
|
388
435
|
}
|
|
436
|
+
/**
|
|
437
|
+
* Create the needed parent directories on the writable storage should they not exist.
|
|
438
|
+
* Use modes from the read-only storage.
|
|
439
|
+
*/
|
|
389
440
|
async createParentDirectories(path) {
|
|
390
441
|
let parent = dirname(path);
|
|
391
442
|
const toCreate = [];
|
|
@@ -403,19 +454,23 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
403
454
|
* - Ensures p is on writable before proceeding. Throws an error if it doesn't exist.
|
|
404
455
|
* - Calls f to perform operation on writable.
|
|
405
456
|
*/
|
|
406
|
-
|
|
457
|
+
copyForWriteSync(path) {
|
|
407
458
|
if (!this.existsSync(path)) {
|
|
408
|
-
throw ErrnoError.With('ENOENT', path, '
|
|
459
|
+
throw ErrnoError.With('ENOENT', path, 'copyForWrite');
|
|
460
|
+
}
|
|
461
|
+
if (!this.writable.existsSync(dirname(path))) {
|
|
462
|
+
this.createParentDirectoriesSync(path);
|
|
409
463
|
}
|
|
410
464
|
if (!this.writable.existsSync(path)) {
|
|
411
|
-
// File is on readable storage. Copy to writable storage before
|
|
412
|
-
// changing its mode.
|
|
413
465
|
this.copyToWritableSync(path);
|
|
414
466
|
}
|
|
415
467
|
}
|
|
416
|
-
async
|
|
468
|
+
async copyForWrite(path) {
|
|
417
469
|
if (!(await this.exists(path))) {
|
|
418
|
-
throw ErrnoError.With('ENOENT', path, '
|
|
470
|
+
throw ErrnoError.With('ENOENT', path, 'copyForWrite');
|
|
471
|
+
}
|
|
472
|
+
if (!(await this.writable.exists(dirname(path)))) {
|
|
473
|
+
await this.createParentDirectories(path);
|
|
419
474
|
}
|
|
420
475
|
if (!(await this.writable.exists(path))) {
|
|
421
476
|
return this.copyToWritable(path);
|
|
@@ -426,32 +481,50 @@ export class UnmutexedOverlayFS extends FileSystem {
|
|
|
426
481
|
* PRECONDITION: File does not exist on writable storage.
|
|
427
482
|
*/
|
|
428
483
|
copyToWritableSync(path) {
|
|
429
|
-
const
|
|
430
|
-
|
|
431
|
-
this.
|
|
432
|
-
|
|
484
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
485
|
+
try {
|
|
486
|
+
const stats = this.statSync(path);
|
|
487
|
+
if (stats.isDirectory()) {
|
|
488
|
+
this.writable.mkdirSync(path, stats.mode);
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
const data = new Uint8Array(stats.size);
|
|
492
|
+
const readable = __addDisposableResource(env_1, this.readable.openFileSync(path, 'r'), false);
|
|
493
|
+
readable.readSync(data);
|
|
494
|
+
const writable = __addDisposableResource(env_1, this.writable.createFileSync(path, 'w', stats.mode | 0o222), false);
|
|
495
|
+
writable.writeSync(data);
|
|
496
|
+
}
|
|
497
|
+
catch (e_1) {
|
|
498
|
+
env_1.error = e_1;
|
|
499
|
+
env_1.hasError = true;
|
|
500
|
+
}
|
|
501
|
+
finally {
|
|
502
|
+
__disposeResources(env_1);
|
|
433
503
|
}
|
|
434
|
-
const data = new Uint8Array(stats.size);
|
|
435
|
-
const readable = this.readable.openFileSync(path, parseFlag('r'));
|
|
436
|
-
readable.readSync(data);
|
|
437
|
-
readable.closeSync();
|
|
438
|
-
const writable = this.writable.openFileSync(path, parseFlag('w'));
|
|
439
|
-
writable.writeSync(data);
|
|
440
|
-
writable.closeSync();
|
|
441
504
|
}
|
|
442
505
|
async copyToWritable(path) {
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
await this.
|
|
446
|
-
|
|
506
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
507
|
+
try {
|
|
508
|
+
const stats = await this.stat(path);
|
|
509
|
+
if (stats.isDirectory()) {
|
|
510
|
+
await this.writable.mkdir(path, stats.mode);
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
const data = new Uint8Array(stats.size);
|
|
514
|
+
const readable = __addDisposableResource(env_2, await this.readable.openFile(path, 'r'), true);
|
|
515
|
+
await readable.read(data);
|
|
516
|
+
const writable = __addDisposableResource(env_2, await this.writable.createFile(path, 'w', stats.mode | 0o222), true);
|
|
517
|
+
await writable.write(data);
|
|
518
|
+
}
|
|
519
|
+
catch (e_2) {
|
|
520
|
+
env_2.error = e_2;
|
|
521
|
+
env_2.hasError = true;
|
|
522
|
+
}
|
|
523
|
+
finally {
|
|
524
|
+
const result_1 = __disposeResources(env_2);
|
|
525
|
+
if (result_1)
|
|
526
|
+
await result_1;
|
|
447
527
|
}
|
|
448
|
-
const data = new Uint8Array(stats.size);
|
|
449
|
-
const readable = await this.readable.openFile(path, parseFlag('r'));
|
|
450
|
-
await readable.read(data);
|
|
451
|
-
await readable.close();
|
|
452
|
-
const writable = await this.writable.openFile(path, parseFlag('w'));
|
|
453
|
-
await writable.write(data);
|
|
454
|
-
await writable.close();
|
|
455
528
|
}
|
|
456
529
|
}
|
|
457
530
|
/**
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
3
1
|
import type { FileReadResult } from 'node:fs/promises';
|
|
4
2
|
import type { ExtractProperties } from 'utilium';
|
|
5
3
|
import { type MountConfiguration } from '../../config.js';
|
|
@@ -10,7 +8,8 @@ import type { Backend, FilesystemOf } from '../backend.js';
|
|
|
10
8
|
import * as RPC from './rpc.js';
|
|
11
9
|
type FileMethods = Omit<ExtractProperties<File, (...args: any[]) => Promise<any>>, typeof Symbol.asyncDispose>;
|
|
12
10
|
type FileMethod = keyof FileMethods;
|
|
13
|
-
|
|
11
|
+
/** @internal */
|
|
12
|
+
export interface FileRequest<TMethod extends FileMethod = FileMethod> extends RPC.Request {
|
|
14
13
|
fd: number;
|
|
15
14
|
scope: 'file';
|
|
16
15
|
method: TMethod;
|
|
@@ -46,13 +45,14 @@ export declare class PortFile extends File {
|
|
|
46
45
|
}
|
|
47
46
|
type FSMethods = ExtractProperties<FileSystem, (...args: any[]) => Promise<any> | FileSystemMetadata>;
|
|
48
47
|
type FSMethod = keyof FSMethods;
|
|
49
|
-
|
|
48
|
+
/** @internal */
|
|
49
|
+
export interface FSRequest<TMethod extends FSMethod = FSMethod> extends RPC.Request {
|
|
50
50
|
scope: 'fs';
|
|
51
51
|
method: TMethod;
|
|
52
52
|
args: Parameters<FSMethods[TMethod]>;
|
|
53
53
|
}
|
|
54
54
|
declare const PortFS_base: import("../../index.js").Mixin<typeof FileSystem, {
|
|
55
|
-
_sync?: FileSystem
|
|
55
|
+
_sync?: FileSystem;
|
|
56
56
|
queueDone(): Promise<void>;
|
|
57
57
|
ready(): Promise<void>;
|
|
58
58
|
renameSync(oldPath: string, newPath: string): void;
|
|
@@ -67,10 +67,10 @@ declare const PortFS_base: import("../../index.js").Mixin<typeof FileSystem, {
|
|
|
67
67
|
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
|
|
68
68
|
}>;
|
|
69
69
|
/**
|
|
70
|
-
* PortFS lets you access
|
|
70
|
+
* PortFS lets you access an FS instance that is running in a port, or the other way around.
|
|
71
71
|
*
|
|
72
|
-
* Note that synchronous operations are not permitted on the PortFS,
|
|
73
|
-
* of the configuration option of the remote FS.
|
|
72
|
+
* Note that *direct* synchronous operations are not permitted on the PortFS,
|
|
73
|
+
* regardless of the configuration option of the remote FS.
|
|
74
74
|
*/
|
|
75
75
|
export declare class PortFS extends PortFS_base {
|
|
76
76
|
readonly options: RPC.Options;
|
|
@@ -80,8 +80,7 @@ export declare class PortFS extends PortFS_base {
|
|
|
80
80
|
*/
|
|
81
81
|
_sync: import("../store/fs.js").StoreFS<import("../memory.js").InMemoryStore>;
|
|
82
82
|
/**
|
|
83
|
-
* Constructs a new PortFS instance that connects with
|
|
84
|
-
* the specified port.
|
|
83
|
+
* Constructs a new PortFS instance that connects with the FS running on `options.port`.
|
|
85
84
|
*/
|
|
86
85
|
constructor(options: RPC.Options);
|
|
87
86
|
metadata(): FileSystemMetadata;
|
|
@@ -99,13 +98,9 @@ export declare class PortFS extends PortFS_base {
|
|
|
99
98
|
exists(path: string): Promise<boolean>;
|
|
100
99
|
link(srcpath: string, dstpath: string): Promise<void>;
|
|
101
100
|
}
|
|
102
|
-
/**
|
|
103
|
-
* @internal
|
|
104
|
-
*/
|
|
101
|
+
/** @internal */
|
|
105
102
|
export type FileOrFSRequest = FSRequest | FileRequest;
|
|
106
|
-
/**
|
|
107
|
-
* @internal
|
|
108
|
-
*/
|
|
103
|
+
/** @internal */
|
|
109
104
|
export declare function handleRequest(port: RPC.Port, fs: FileSystem, request: FileOrFSRequest): Promise<void>;
|
|
110
105
|
export declare function attachFS(port: RPC.Port, fs: FileSystem): void;
|
|
111
106
|
export declare function detachFS(port: RPC.Port, fs: FileSystem): void;
|
|
@@ -128,7 +123,7 @@ declare const _Port: {
|
|
|
128
123
|
create(options: RPC.Options): PortFS;
|
|
129
124
|
};
|
|
130
125
|
type _Port = typeof _Port;
|
|
131
|
-
interface Port extends _Port {
|
|
126
|
+
export interface Port extends _Port {
|
|
132
127
|
}
|
|
133
128
|
export declare const Port: Port;
|
|
134
129
|
export declare function resolveRemoteMount<T extends Backend>(port: RPC.Port, config: MountConfiguration<T>, _depth?: number): Promise<FilesystemOf<T>>;
|
package/dist/backends/port/fs.js
CHANGED
|
@@ -87,15 +87,14 @@ export class PortFile extends File {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
|
-
* PortFS lets you access
|
|
90
|
+
* PortFS lets you access an FS instance that is running in a port, or the other way around.
|
|
91
91
|
*
|
|
92
|
-
* Note that synchronous operations are not permitted on the PortFS,
|
|
93
|
-
* of the configuration option of the remote FS.
|
|
92
|
+
* Note that *direct* synchronous operations are not permitted on the PortFS,
|
|
93
|
+
* regardless of the configuration option of the remote FS.
|
|
94
94
|
*/
|
|
95
95
|
export class PortFS extends Async(FileSystem) {
|
|
96
96
|
/**
|
|
97
|
-
* Constructs a new PortFS instance that connects with
|
|
98
|
-
* the specified port.
|
|
97
|
+
* Constructs a new PortFS instance that connects with the FS running on `options.port`.
|
|
99
98
|
*/
|
|
100
99
|
constructor(options) {
|
|
101
100
|
super();
|
|
@@ -160,9 +159,7 @@ export class PortFS extends Async(FileSystem) {
|
|
|
160
159
|
}
|
|
161
160
|
let nextFd = 0;
|
|
162
161
|
const descriptors = new Map();
|
|
163
|
-
/**
|
|
164
|
-
* @internal
|
|
165
|
-
*/
|
|
162
|
+
/** @internal */
|
|
166
163
|
export async function handleRequest(port, fs, request) {
|
|
167
164
|
if (!RPC.isMessage(request)) {
|
|
168
165
|
return;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
1
|
import { type ErrnoErrorJSON } from '../../error.js';
|
|
3
2
|
import type { Backend, FilesystemOf } from '../backend.js';
|
|
4
3
|
import { type PortFS } from './fs.js';
|
|
5
4
|
type _MessageEvent<T = any> = T | {
|
|
6
5
|
data: T;
|
|
7
6
|
};
|
|
7
|
+
/** @internal */
|
|
8
8
|
export interface Port {
|
|
9
9
|
postMessage(value: unknown): void;
|
|
10
10
|
on?(event: 'message', listener: (value: unknown) => void): this;
|
|
@@ -47,12 +47,12 @@ export declare class StoreFS<T extends Store = Store> extends FileSystem {
|
|
|
47
47
|
readdir(path: string): Promise<string[]>;
|
|
48
48
|
readdirSync(path: string): string[];
|
|
49
49
|
/**
|
|
50
|
-
* Updated the inode and data node at
|
|
50
|
+
* Updated the inode and data node at `path`
|
|
51
51
|
* @todo Ensure mtime updates properly, and use that to determine if a data update is required.
|
|
52
52
|
*/
|
|
53
53
|
sync(path: string, data: Uint8Array, stats: Readonly<Stats>): Promise<void>;
|
|
54
54
|
/**
|
|
55
|
-
* Updated the inode and data node at
|
|
55
|
+
* Updated the inode and data node at `path`
|
|
56
56
|
* @todo Ensure mtime updates properly, and use that to determine if a data update is required.
|
|
57
57
|
*/
|
|
58
58
|
syncSync(path: string, data: Uint8Array, stats: Readonly<Stats>): void;
|
|
@@ -82,13 +82,13 @@ export declare class StoreFS<T extends Store = Store> extends FileSystem {
|
|
|
82
82
|
*/
|
|
83
83
|
protected _findINodeSync(tx: Transaction, parent: string, filename: string, visited?: Set<string>): Ino;
|
|
84
84
|
/**
|
|
85
|
-
* Finds the Inode of
|
|
85
|
+
* Finds the Inode of `path`.
|
|
86
86
|
* @param path The path to look up.
|
|
87
87
|
* @todo memoize/cache
|
|
88
88
|
*/
|
|
89
89
|
private findINode;
|
|
90
90
|
/**
|
|
91
|
-
* Finds the Inode of
|
|
91
|
+
* Finds the Inode of `path`.
|
|
92
92
|
* @param path The path to look up.
|
|
93
93
|
* @return The Inode of the path p.
|
|
94
94
|
* @todo memoize/cache
|
|
@@ -131,18 +131,16 @@ export declare class StoreFS<T extends Store = Store> extends FileSystem {
|
|
|
131
131
|
*/
|
|
132
132
|
protected addNewSync(tx: Transaction, data: Uint8Array, path: string): Ino;
|
|
133
133
|
/**
|
|
134
|
-
* Commits a new file (well, a FILE or a DIRECTORY) to the file system with
|
|
135
|
-
* the given mode.
|
|
134
|
+
* Commits a new file (well, a FILE or a DIRECTORY) to the file system with `mode`.
|
|
136
135
|
* Note: This will commit the transaction.
|
|
137
136
|
* @param path The path to the new file.
|
|
138
137
|
* @param type The type of the new file.
|
|
139
138
|
* @param mode The mode to create the new file with.
|
|
140
|
-
* @param cred The UID/GID to create the file with
|
|
141
139
|
* @param data The data to store at the file's data node.
|
|
142
140
|
*/
|
|
143
141
|
private commitNew;
|
|
144
142
|
/**
|
|
145
|
-
* Commits a new file (well, a FILE or a DIRECTORY) to the file system with
|
|
143
|
+
* Commits a new file (well, a FILE or a DIRECTORY) to the file system with `mode`.
|
|
146
144
|
* Note: This will commit the transaction.
|
|
147
145
|
* @param path The path to the new file.
|
|
148
146
|
* @param type The type of the new file.
|
|
@@ -152,14 +150,14 @@ export declare class StoreFS<T extends Store = Store> extends FileSystem {
|
|
|
152
150
|
*/
|
|
153
151
|
protected commitNewSync(path: string, type: FileType, mode: number, data?: Uint8Array): Inode;
|
|
154
152
|
/**
|
|
155
|
-
* Remove all traces of
|
|
153
|
+
* Remove all traces of `path` from the file system.
|
|
156
154
|
* @param path The path to remove from the file system.
|
|
157
155
|
* @param isDir Does the path belong to a directory, or a file?
|
|
158
156
|
* @todo Update mtime.
|
|
159
157
|
*/
|
|
160
158
|
private remove;
|
|
161
159
|
/**
|
|
162
|
-
* Remove all traces of
|
|
160
|
+
* Remove all traces of `path` from the file system.
|
|
163
161
|
* @param path The path to remove from the file system.
|
|
164
162
|
* @param isDir Does the path belong to a directory, or a file?
|
|
165
163
|
* @todo Update mtime.
|