@zenfs/core 1.11.4 → 2.0.0
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 +19 -15
- package/dist/backends/backend.js +31 -15
- package/dist/backends/cow.d.ts +20 -30
- package/dist/backends/cow.js +52 -142
- package/dist/backends/fetch.d.ts +1 -0
- package/dist/backends/fetch.js +3 -1
- package/dist/backends/index.d.ts +1 -1
- package/dist/backends/index.js +1 -1
- package/dist/backends/memory.d.ts +5 -7
- package/dist/backends/memory.js +2 -3
- package/dist/backends/passthrough.d.ts +19 -22
- package/dist/backends/passthrough.js +85 -160
- package/dist/backends/port.d.ts +207 -0
- package/dist/backends/port.js +297 -0
- package/dist/backends/single_buffer.d.ts +11 -5
- package/dist/backends/single_buffer.js +18 -12
- package/dist/backends/store/fs.d.ts +11 -27
- package/dist/backends/store/fs.js +67 -91
- package/dist/backends/store/store.d.ts +7 -12
- package/dist/config.d.ts +1 -10
- package/dist/config.js +7 -8
- package/dist/context.d.ts +8 -21
- package/dist/context.js +33 -10
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/internal/contexts.d.ts +63 -0
- package/dist/internal/contexts.js +15 -0
- package/dist/internal/credentials.d.ts +2 -11
- package/dist/internal/credentials.js +0 -19
- package/dist/internal/devices.d.ts +18 -80
- package/dist/internal/devices.js +76 -279
- package/dist/internal/file_index.js +3 -3
- package/dist/internal/filesystem.d.ts +31 -89
- package/dist/internal/filesystem.js +21 -20
- package/dist/internal/index.d.ts +0 -1
- package/dist/internal/index.js +0 -1
- package/dist/internal/index_fs.d.ts +12 -30
- package/dist/internal/index_fs.js +23 -55
- package/dist/internal/inode.d.ts +147 -9
- package/dist/internal/inode.js +333 -25
- package/dist/internal/log.d.ts +19 -13
- package/dist/internal/log.js +81 -80
- package/dist/mixins/async.js +26 -90
- package/dist/mixins/mutexed.d.ts +17 -16
- package/dist/mixins/mutexed.js +29 -31
- package/dist/mixins/readonly.d.ts +7 -6
- package/dist/mixins/readonly.js +6 -0
- package/dist/mixins/sync.js +8 -8
- package/dist/{vfs/path.d.ts → path.d.ts} +3 -4
- package/dist/{vfs/path.js → path.js} +6 -9
- package/dist/readline.d.ts +134 -0
- package/dist/readline.js +623 -0
- package/dist/utils.d.ts +4 -35
- package/dist/utils.js +8 -73
- package/dist/vfs/acl.d.ts +42 -0
- package/dist/vfs/acl.js +249 -0
- package/dist/vfs/async.d.ts +7 -21
- package/dist/vfs/async.js +19 -19
- package/dist/vfs/config.d.ts +6 -18
- package/dist/vfs/config.js +8 -18
- package/dist/vfs/dir.d.ts +3 -3
- package/dist/vfs/dir.js +9 -8
- package/dist/vfs/file.d.ts +106 -0
- package/dist/vfs/file.js +235 -0
- package/dist/vfs/flags.d.ts +19 -0
- package/dist/vfs/flags.js +62 -0
- package/dist/vfs/index.d.ts +4 -10
- package/dist/vfs/index.js +4 -13
- package/dist/vfs/ioctl.d.ts +87 -0
- package/dist/vfs/ioctl.js +304 -0
- package/dist/vfs/promises.d.ts +78 -16
- package/dist/vfs/promises.js +273 -122
- package/dist/vfs/shared.d.ts +7 -26
- package/dist/vfs/shared.js +25 -53
- package/dist/{stats.d.ts → vfs/stats.d.ts} +14 -28
- package/dist/{stats.js → vfs/stats.js} +11 -66
- package/dist/vfs/streams.d.ts +1 -0
- package/dist/vfs/streams.js +24 -19
- package/dist/vfs/sync.d.ts +4 -3
- package/dist/vfs/sync.js +143 -128
- package/dist/vfs/watchers.d.ts +2 -2
- package/dist/vfs/watchers.js +6 -6
- package/dist/vfs/xattr.d.ts +116 -0
- package/dist/vfs/xattr.js +218 -0
- package/package.json +3 -3
- package/readme.md +1 -1
- package/tests/backend/config.worker.js +4 -1
- package/tests/backend/fetch.test.ts +3 -0
- package/tests/backend/port.test.ts +21 -35
- package/tests/backend/remote.worker.js +4 -1
- package/tests/backend/single-buffer.test.ts +24 -0
- package/tests/common/context.test.ts +1 -1
- package/tests/common/handle.test.ts +17 -12
- package/tests/common/path.test.ts +1 -1
- package/tests/common/readline.test.ts +104 -0
- package/tests/common.ts +4 -19
- package/tests/fetch/fetch.ts +1 -1
- package/tests/fs/links.test.ts +1 -1
- package/tests/fs/permissions.test.ts +7 -6
- package/tests/fs/readFile.test.ts +3 -3
- package/tests/fs/stat.test.ts +6 -6
- package/tests/fs/streams.test.ts +2 -11
- package/tests/fs/times.test.ts +1 -1
- package/tests/fs/xattr.test.ts +85 -0
- package/tests/logs.js +22 -0
- package/tests/setup/context.ts +1 -1
- package/tests/setup/index.ts +3 -3
- package/tests/setup/port.ts +1 -1
- package/dist/backends/port/fs.d.ts +0 -84
- package/dist/backends/port/fs.js +0 -151
- package/dist/backends/port/rpc.d.ts +0 -77
- package/dist/backends/port/rpc.js +0 -100
- package/dist/backends/store/simple.d.ts +0 -20
- package/dist/backends/store/simple.js +0 -13
- package/dist/internal/file.d.ts +0 -359
- package/dist/internal/file.js +0 -751
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type * as fs from 'node:fs';
|
|
2
|
-
import {
|
|
3
|
-
import { FileSystem
|
|
4
|
-
import type
|
|
5
|
-
import { Stats } from '../stats.js';
|
|
2
|
+
import type { CreationOptions, UsageInfo } from '../internal/filesystem.js';
|
|
3
|
+
import { FileSystem } from '../internal/filesystem.js';
|
|
4
|
+
import { type InodeLike } from '../internal/inode.js';
|
|
6
5
|
export type NodeFS = typeof fs;
|
|
7
6
|
/**
|
|
8
7
|
* Passthrough backend options
|
|
@@ -10,7 +9,7 @@ export type NodeFS = typeof fs;
|
|
|
10
9
|
*/
|
|
11
10
|
export interface PassthroughOptions {
|
|
12
11
|
fs: NodeFS;
|
|
13
|
-
prefix
|
|
12
|
+
prefix: string;
|
|
14
13
|
}
|
|
15
14
|
export declare class PassthroughFS extends FileSystem {
|
|
16
15
|
readonly nodeFS: NodeFS;
|
|
@@ -30,19 +29,13 @@ export declare class PassthroughFS extends FileSystem {
|
|
|
30
29
|
/**
|
|
31
30
|
* Get file statistics.
|
|
32
31
|
*/
|
|
33
|
-
stat(path: string): Promise<
|
|
32
|
+
stat(path: string): Promise<InodeLike>;
|
|
34
33
|
/**
|
|
35
34
|
* Get file statistics synchronously.
|
|
36
35
|
*/
|
|
37
|
-
statSync(path: string):
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
*/
|
|
41
|
-
openFile(path: string, flag: string): Promise<File>;
|
|
42
|
-
/**
|
|
43
|
-
* Open a file synchronously.
|
|
44
|
-
*/
|
|
45
|
-
openFileSync(path: string, flag: string): File;
|
|
36
|
+
statSync(path: string): InodeLike;
|
|
37
|
+
touch(path: string, metadata: InodeLike): Promise<void>;
|
|
38
|
+
touchSync(path: string, metadata: InodeLike): void;
|
|
46
39
|
/**
|
|
47
40
|
* Unlink (delete) a file.
|
|
48
41
|
*/
|
|
@@ -54,11 +47,11 @@ export declare class PassthroughFS extends FileSystem {
|
|
|
54
47
|
/**
|
|
55
48
|
* Create a directory.
|
|
56
49
|
*/
|
|
57
|
-
mkdir(path: string,
|
|
50
|
+
mkdir(path: string, options: CreationOptions): Promise<InodeLike>;
|
|
58
51
|
/**
|
|
59
52
|
* Create a directory synchronously.
|
|
60
53
|
*/
|
|
61
|
-
mkdirSync(path: string,
|
|
54
|
+
mkdirSync(path: string, options: CreationOptions): InodeLike;
|
|
62
55
|
/**
|
|
63
56
|
* Read the contents of a directory.
|
|
64
57
|
*/
|
|
@@ -70,11 +63,11 @@ export declare class PassthroughFS extends FileSystem {
|
|
|
70
63
|
/**
|
|
71
64
|
* Create a file.
|
|
72
65
|
*/
|
|
73
|
-
createFile(path: string,
|
|
66
|
+
createFile(path: string, options: CreationOptions): Promise<InodeLike>;
|
|
74
67
|
/**
|
|
75
68
|
* Create a file synchronously.
|
|
76
69
|
*/
|
|
77
|
-
createFileSync(path: string,
|
|
70
|
+
createFileSync(path: string, options: CreationOptions): InodeLike;
|
|
78
71
|
/**
|
|
79
72
|
* Remove a directory.
|
|
80
73
|
*/
|
|
@@ -86,11 +79,11 @@ export declare class PassthroughFS extends FileSystem {
|
|
|
86
79
|
/**
|
|
87
80
|
* Synchronize data to the file system.
|
|
88
81
|
*/
|
|
89
|
-
sync(path: string
|
|
82
|
+
sync(path: string): Promise<void>;
|
|
90
83
|
/**
|
|
91
84
|
* Synchronize data to the file system synchronously.
|
|
92
85
|
*/
|
|
93
|
-
syncSync(path: string
|
|
86
|
+
syncSync(path: string): void;
|
|
94
87
|
/**
|
|
95
88
|
* Create a hard link.
|
|
96
89
|
*/
|
|
@@ -113,12 +106,16 @@ declare const _Passthrough: {
|
|
|
113
106
|
};
|
|
114
107
|
readonly prefix: {
|
|
115
108
|
readonly type: "string";
|
|
116
|
-
readonly required:
|
|
109
|
+
readonly required: true;
|
|
117
110
|
};
|
|
118
111
|
};
|
|
119
112
|
readonly create: ({ fs, prefix }: PassthroughOptions) => PassthroughFS;
|
|
120
113
|
};
|
|
121
114
|
type _Passthrough = typeof _Passthrough;
|
|
115
|
+
/**
|
|
116
|
+
* A file system that passes through to another FS
|
|
117
|
+
* @category Backends and Configuration
|
|
118
|
+
*/
|
|
122
119
|
export interface Passthrough extends _Passthrough {
|
|
123
120
|
}
|
|
124
121
|
/**
|
|
@@ -51,90 +51,10 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
51
51
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
52
|
});
|
|
53
53
|
import { ErrnoError } from '../internal/error.js';
|
|
54
|
-
import { File } from '../internal/file.js';
|
|
55
54
|
import { FileSystem } from '../internal/filesystem.js';
|
|
56
|
-
import {
|
|
57
|
-
import {
|
|
58
|
-
|
|
59
|
-
constructor(fs, path, fd) {
|
|
60
|
-
super(fs, path);
|
|
61
|
-
this.fd = fd;
|
|
62
|
-
this.node = fs.nodeFS;
|
|
63
|
-
this.nodePath = fs.path(path);
|
|
64
|
-
}
|
|
65
|
-
error(err) {
|
|
66
|
-
const error = err;
|
|
67
|
-
return ErrnoError.With(error.code, this.path, error.syscall);
|
|
68
|
-
}
|
|
69
|
-
get position() {
|
|
70
|
-
// Placeholder: Implement proper position tracking if needed.
|
|
71
|
-
return 0;
|
|
72
|
-
}
|
|
73
|
-
async stat() {
|
|
74
|
-
const { resolve, reject, promise } = Promise.withResolvers();
|
|
75
|
-
this.node.fstat(this.fd, (err, stats) => (err ? reject(this.error(err)) : resolve(new Stats(stats))));
|
|
76
|
-
return promise;
|
|
77
|
-
}
|
|
78
|
-
statSync() {
|
|
79
|
-
return new Stats(this.node.fstatSync(this.fd));
|
|
80
|
-
}
|
|
81
|
-
close() {
|
|
82
|
-
const { resolve, reject, promise } = Promise.withResolvers();
|
|
83
|
-
this.node.close(this.fd, err => (err ? reject(this.error(err)) : resolve()));
|
|
84
|
-
return promise;
|
|
85
|
-
}
|
|
86
|
-
closeSync() {
|
|
87
|
-
this.node.closeSync(this.fd);
|
|
88
|
-
}
|
|
89
|
-
async truncate(len) {
|
|
90
|
-
await this.node.promises.truncate(this.nodePath, len);
|
|
91
|
-
}
|
|
92
|
-
truncateSync(len) {
|
|
93
|
-
this.node.ftruncateSync(this.fd, len);
|
|
94
|
-
}
|
|
95
|
-
async sync() {
|
|
96
|
-
const { resolve, reject, promise } = Promise.withResolvers();
|
|
97
|
-
this.node.fsync(this.fd, err => (err ? reject(this.error(err)) : resolve()));
|
|
98
|
-
return promise;
|
|
99
|
-
}
|
|
100
|
-
syncSync() {
|
|
101
|
-
this.node.fsyncSync(this.fd);
|
|
102
|
-
}
|
|
103
|
-
async write(buffer, offset, length, position) {
|
|
104
|
-
const { resolve, reject, promise } = Promise.withResolvers();
|
|
105
|
-
this.node.write(this.fd, buffer, offset, length, position, (err, written) => (err ? reject(this.error(err)) : resolve(written)));
|
|
106
|
-
return promise;
|
|
107
|
-
}
|
|
108
|
-
writeSync(buffer, offset, length, position) {
|
|
109
|
-
return this.node.writeSync(this.fd, buffer, offset, length, position);
|
|
110
|
-
}
|
|
111
|
-
async read(buffer, offset = 0, length, position = null) {
|
|
112
|
-
const { resolve, reject, promise } = Promise.withResolvers();
|
|
113
|
-
this.node.read(this.fd, buffer, offset, length || (await this.stat()).size, position, (err, bytesRead, buffer) => err ? reject(this.error(err)) : resolve({ bytesRead, buffer }));
|
|
114
|
-
return promise;
|
|
115
|
-
}
|
|
116
|
-
readSync(buffer, offset = 0, length = this.statSync().size, position = null) {
|
|
117
|
-
return this.node.readSync(this.fd, buffer, offset, length, position);
|
|
118
|
-
}
|
|
119
|
-
async chmod(mode) {
|
|
120
|
-
await this.node.promises.chmod(this.nodePath, mode);
|
|
121
|
-
}
|
|
122
|
-
chmodSync(mode) {
|
|
123
|
-
this.node.fchmodSync(this.fd, mode);
|
|
124
|
-
}
|
|
125
|
-
async chown(uid, gid) {
|
|
126
|
-
await this.node.promises.chown(this.nodePath, uid, gid);
|
|
127
|
-
}
|
|
128
|
-
chownSync(uid, gid) {
|
|
129
|
-
this.node.fchownSync(this.fd, uid, gid);
|
|
130
|
-
}
|
|
131
|
-
async utimes(atime, mtime) {
|
|
132
|
-
await this.node.promises.utimes(this.nodePath, atime, mtime);
|
|
133
|
-
}
|
|
134
|
-
utimesSync(atime, mtime) {
|
|
135
|
-
this.node.futimesSync(this.fd, atime, mtime);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
55
|
+
import { isDirectory } from '../internal/inode.js';
|
|
56
|
+
import { resolve } from '../path.js';
|
|
57
|
+
import { warn } from '../internal/log.js';
|
|
138
58
|
export class PassthroughFS extends FileSystem {
|
|
139
59
|
constructor(nodeFS, prefix) {
|
|
140
60
|
super(0x6e6f6465, 'nodefs');
|
|
@@ -149,7 +69,7 @@ export class PassthroughFS extends FileSystem {
|
|
|
149
69
|
};
|
|
150
70
|
}
|
|
151
71
|
path(path) {
|
|
152
|
-
return
|
|
72
|
+
return this.prefix + path;
|
|
153
73
|
}
|
|
154
74
|
error(err, path) {
|
|
155
75
|
const error = err;
|
|
@@ -182,7 +102,7 @@ export class PassthroughFS extends FileSystem {
|
|
|
182
102
|
*/
|
|
183
103
|
async stat(path) {
|
|
184
104
|
try {
|
|
185
|
-
return
|
|
105
|
+
return await this.nodeFS.promises.stat(this.path(path));
|
|
186
106
|
}
|
|
187
107
|
catch (err) {
|
|
188
108
|
this.error(err, path);
|
|
@@ -193,31 +113,40 @@ export class PassthroughFS extends FileSystem {
|
|
|
193
113
|
*/
|
|
194
114
|
statSync(path) {
|
|
195
115
|
try {
|
|
196
|
-
return
|
|
116
|
+
return this.nodeFS.statSync(this.path(path));
|
|
197
117
|
}
|
|
198
118
|
catch (err) {
|
|
199
119
|
this.error(err, path);
|
|
200
120
|
}
|
|
201
121
|
}
|
|
202
|
-
|
|
203
|
-
* Open a file.
|
|
204
|
-
*/
|
|
205
|
-
async openFile(path, flag) {
|
|
122
|
+
async touch(path, metadata) {
|
|
206
123
|
try {
|
|
207
|
-
const {
|
|
208
|
-
|
|
124
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
125
|
+
try {
|
|
126
|
+
const handle = __addDisposableResource(env_1, await this.nodeFS.promises.open(this.path(path), 'w'), true);
|
|
127
|
+
await handle.chmod(metadata.mode);
|
|
128
|
+
await handle.chown(metadata.uid, metadata.gid);
|
|
129
|
+
await handle.utimes(metadata.atimeMs, metadata.mtimeMs);
|
|
130
|
+
}
|
|
131
|
+
catch (e_1) {
|
|
132
|
+
env_1.error = e_1;
|
|
133
|
+
env_1.hasError = true;
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
const result_1 = __disposeResources(env_1);
|
|
137
|
+
if (result_1)
|
|
138
|
+
await result_1;
|
|
139
|
+
}
|
|
209
140
|
}
|
|
210
141
|
catch (err) {
|
|
211
142
|
this.error(err, path);
|
|
212
143
|
}
|
|
213
144
|
}
|
|
214
|
-
|
|
215
|
-
* Open a file synchronously.
|
|
216
|
-
*/
|
|
217
|
-
openFileSync(path, flag) {
|
|
145
|
+
touchSync(path, metadata) {
|
|
218
146
|
try {
|
|
219
|
-
|
|
220
|
-
|
|
147
|
+
this.nodeFS.chmodSync(this.path(path), metadata.mode);
|
|
148
|
+
this.nodeFS.chownSync(this.path(path), metadata.uid, metadata.gid);
|
|
149
|
+
this.nodeFS.utimesSync(this.path(path), metadata.atimeMs, metadata.mtimeMs);
|
|
221
150
|
}
|
|
222
151
|
catch (err) {
|
|
223
152
|
this.error(err, path);
|
|
@@ -248,9 +177,10 @@ export class PassthroughFS extends FileSystem {
|
|
|
248
177
|
/**
|
|
249
178
|
* Create a directory.
|
|
250
179
|
*/
|
|
251
|
-
async mkdir(path,
|
|
180
|
+
async mkdir(path, options) {
|
|
252
181
|
try {
|
|
253
|
-
await this.nodeFS.promises.mkdir(this.path(path),
|
|
182
|
+
await this.nodeFS.promises.mkdir(this.path(path), options);
|
|
183
|
+
return await this.nodeFS.promises.stat(this.path(path));
|
|
254
184
|
}
|
|
255
185
|
catch (err) {
|
|
256
186
|
this.error(err, path);
|
|
@@ -259,9 +189,10 @@ export class PassthroughFS extends FileSystem {
|
|
|
259
189
|
/**
|
|
260
190
|
* Create a directory synchronously.
|
|
261
191
|
*/
|
|
262
|
-
mkdirSync(path,
|
|
192
|
+
mkdirSync(path, options) {
|
|
263
193
|
try {
|
|
264
|
-
this.nodeFS.mkdirSync(this.path(path),
|
|
194
|
+
this.nodeFS.mkdirSync(this.path(path), options);
|
|
195
|
+
return this.nodeFS.statSync(this.path(path));
|
|
265
196
|
}
|
|
266
197
|
catch (err) {
|
|
267
198
|
this.error(err, path);
|
|
@@ -292,10 +223,28 @@ export class PassthroughFS extends FileSystem {
|
|
|
292
223
|
/**
|
|
293
224
|
* Create a file.
|
|
294
225
|
*/
|
|
295
|
-
async createFile(path,
|
|
226
|
+
async createFile(path, options) {
|
|
296
227
|
try {
|
|
297
|
-
|
|
298
|
-
|
|
228
|
+
if (isDirectory(options)) {
|
|
229
|
+
await this.nodeFS.promises.mkdir(this.path(path), { mode: options.mode });
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
233
|
+
try {
|
|
234
|
+
const handle = __addDisposableResource(env_2, await this.nodeFS.promises.open(this.path(path), 'wx'), true);
|
|
235
|
+
await handle.close();
|
|
236
|
+
}
|
|
237
|
+
catch (e_2) {
|
|
238
|
+
env_2.error = e_2;
|
|
239
|
+
env_2.hasError = true;
|
|
240
|
+
}
|
|
241
|
+
finally {
|
|
242
|
+
const result_2 = __disposeResources(env_2);
|
|
243
|
+
if (result_2)
|
|
244
|
+
await result_2;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return await this.nodeFS.promises.stat(this.path(path));
|
|
299
248
|
}
|
|
300
249
|
catch (err) {
|
|
301
250
|
this.error(err, path);
|
|
@@ -304,10 +253,16 @@ export class PassthroughFS extends FileSystem {
|
|
|
304
253
|
/**
|
|
305
254
|
* Create a file synchronously.
|
|
306
255
|
*/
|
|
307
|
-
createFileSync(path,
|
|
256
|
+
createFileSync(path, options) {
|
|
308
257
|
try {
|
|
309
|
-
|
|
310
|
-
|
|
258
|
+
if (isDirectory(options)) {
|
|
259
|
+
this.nodeFS.mkdirSync(this.path(path), { mode: options.mode });
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
const fd = this.nodeFS.openSync(this.path(path), 'wx');
|
|
263
|
+
this.nodeFS.closeSync(fd);
|
|
264
|
+
}
|
|
265
|
+
return this.nodeFS.statSync(this.path(path));
|
|
311
266
|
}
|
|
312
267
|
catch (err) {
|
|
313
268
|
this.error(err, path);
|
|
@@ -338,44 +293,14 @@ export class PassthroughFS extends FileSystem {
|
|
|
338
293
|
/**
|
|
339
294
|
* Synchronize data to the file system.
|
|
340
295
|
*/
|
|
341
|
-
async sync(path
|
|
342
|
-
|
|
343
|
-
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
344
|
-
try {
|
|
345
|
-
const handle = __addDisposableResource(env_1, await this.nodeFS.promises.open(this.path(path), 'w'), true);
|
|
346
|
-
await handle.writeFile(data);
|
|
347
|
-
await handle.chmod(stats.mode);
|
|
348
|
-
await handle.chown(stats.uid, stats.gid);
|
|
349
|
-
await handle.utimes(stats.atimeMs, stats.mtimeMs);
|
|
350
|
-
}
|
|
351
|
-
catch (e_1) {
|
|
352
|
-
env_1.error = e_1;
|
|
353
|
-
env_1.hasError = true;
|
|
354
|
-
}
|
|
355
|
-
finally {
|
|
356
|
-
const result_1 = __disposeResources(env_1);
|
|
357
|
-
if (result_1)
|
|
358
|
-
await result_1;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
catch (err) {
|
|
362
|
-
this.error(err, path);
|
|
363
|
-
}
|
|
296
|
+
async sync(path) {
|
|
297
|
+
warn('Sync on passthrough is unnecessary');
|
|
364
298
|
}
|
|
365
299
|
/**
|
|
366
300
|
* Synchronize data to the file system synchronously.
|
|
367
301
|
*/
|
|
368
|
-
syncSync(path
|
|
369
|
-
|
|
370
|
-
const p = this.path(path);
|
|
371
|
-
this.nodeFS.writeFileSync(p, data);
|
|
372
|
-
this.nodeFS.chmodSync(p, stats.mode);
|
|
373
|
-
this.nodeFS.chownSync(p, stats.uid, stats.gid);
|
|
374
|
-
this.nodeFS.utimesSync(p, stats.atimeMs, stats.mtimeMs);
|
|
375
|
-
}
|
|
376
|
-
catch (err) {
|
|
377
|
-
this.error(err, path);
|
|
378
|
-
}
|
|
302
|
+
syncSync(path) {
|
|
303
|
+
warn('Sync on passthrough is unnecessary');
|
|
379
304
|
}
|
|
380
305
|
/**
|
|
381
306
|
* Create a hard link.
|
|
@@ -401,19 +326,19 @@ export class PassthroughFS extends FileSystem {
|
|
|
401
326
|
}
|
|
402
327
|
async read(path, buffer, offset, end) {
|
|
403
328
|
try {
|
|
404
|
-
const
|
|
329
|
+
const env_3 = { stack: [], error: void 0, hasError: false };
|
|
405
330
|
try {
|
|
406
|
-
const handle = __addDisposableResource(
|
|
331
|
+
const handle = __addDisposableResource(env_3, await this.nodeFS.promises.open(this.path(path), 'r'), true);
|
|
407
332
|
await handle.read({ buffer, offset, length: end - offset });
|
|
408
333
|
}
|
|
409
|
-
catch (
|
|
410
|
-
|
|
411
|
-
|
|
334
|
+
catch (e_3) {
|
|
335
|
+
env_3.error = e_3;
|
|
336
|
+
env_3.hasError = true;
|
|
412
337
|
}
|
|
413
338
|
finally {
|
|
414
|
-
const
|
|
415
|
-
if (
|
|
416
|
-
await
|
|
339
|
+
const result_3 = __disposeResources(env_3);
|
|
340
|
+
if (result_3)
|
|
341
|
+
await result_3;
|
|
417
342
|
}
|
|
418
343
|
}
|
|
419
344
|
catch (err) {
|
|
@@ -436,19 +361,19 @@ export class PassthroughFS extends FileSystem {
|
|
|
436
361
|
}
|
|
437
362
|
async write(path, buffer, offset) {
|
|
438
363
|
try {
|
|
439
|
-
const
|
|
364
|
+
const env_4 = { stack: [], error: void 0, hasError: false };
|
|
440
365
|
try {
|
|
441
|
-
const handle = __addDisposableResource(
|
|
366
|
+
const handle = __addDisposableResource(env_4, await this.nodeFS.promises.open(this.path(path), 'w'), true);
|
|
442
367
|
await handle.write(buffer, offset);
|
|
443
368
|
}
|
|
444
|
-
catch (
|
|
445
|
-
|
|
446
|
-
|
|
369
|
+
catch (e_4) {
|
|
370
|
+
env_4.error = e_4;
|
|
371
|
+
env_4.hasError = true;
|
|
447
372
|
}
|
|
448
373
|
finally {
|
|
449
|
-
const
|
|
450
|
-
if (
|
|
451
|
-
await
|
|
374
|
+
const result_4 = __disposeResources(env_4);
|
|
375
|
+
if (result_4)
|
|
376
|
+
await result_4;
|
|
452
377
|
}
|
|
453
378
|
}
|
|
454
379
|
catch (err) {
|
|
@@ -474,9 +399,9 @@ const _Passthrough = {
|
|
|
474
399
|
name: 'Passthrough',
|
|
475
400
|
options: {
|
|
476
401
|
fs: { type: 'object', required: true },
|
|
477
|
-
prefix: { type: 'string', required:
|
|
402
|
+
prefix: { type: 'string', required: true },
|
|
478
403
|
},
|
|
479
|
-
create({ fs, prefix
|
|
404
|
+
create({ fs, prefix }) {
|
|
480
405
|
return new PassthroughFS(fs, resolve(prefix));
|
|
481
406
|
},
|
|
482
407
|
};
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { TransferListItem } from 'node:worker_threads';
|
|
2
|
+
import type { MountConfiguration } from '../config.js';
|
|
3
|
+
import type { CreationOptions, UsageInfo } from '../internal/filesystem.js';
|
|
4
|
+
import type { InodeLike } from '../internal/inode.js';
|
|
5
|
+
import type { Backend, FilesystemOf } from './backend.js';
|
|
6
|
+
import { FileSystem } from '../internal/filesystem.js';
|
|
7
|
+
import { Inode } from '../internal/inode.js';
|
|
8
|
+
import '../polyfills.js';
|
|
9
|
+
type _MessageEvent<T = any> = T | {
|
|
10
|
+
data: T;
|
|
11
|
+
};
|
|
12
|
+
/** @internal */
|
|
13
|
+
export interface RPCPort {
|
|
14
|
+
postMessage(value: unknown, transfer?: TransferListItem[]): void;
|
|
15
|
+
on?(event: 'message' | 'online', listener: (value: unknown) => void): this;
|
|
16
|
+
off?(event: 'message', listener: (value: unknown) => void): this;
|
|
17
|
+
addEventListener?(type: 'message', listener: (ev: _MessageEvent) => void): void;
|
|
18
|
+
removeEventListener?(type: 'message', listener: (ev: _MessageEvent) => void): void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The options for the Port backend
|
|
22
|
+
* @category Backends and Configuration
|
|
23
|
+
*/
|
|
24
|
+
export interface PortOptions {
|
|
25
|
+
/**
|
|
26
|
+
* The target port that you want to connect to, or the current port if in a port context.
|
|
27
|
+
*/
|
|
28
|
+
port: RPCPort;
|
|
29
|
+
/**
|
|
30
|
+
* How long to wait for a request to complete
|
|
31
|
+
*/
|
|
32
|
+
timeout?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The API for remote procedure calls
|
|
36
|
+
* @category Internals
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export interface RPCMethods {
|
|
40
|
+
usage(): UsageInfo;
|
|
41
|
+
ready(): void;
|
|
42
|
+
rename(oldPath: string, newPath: string): void;
|
|
43
|
+
createFile(path: string, options: CreationOptions): Uint8Array;
|
|
44
|
+
unlink(path: string): void;
|
|
45
|
+
rmdir(path: string): void;
|
|
46
|
+
mkdir(path: string, options: CreationOptions): Uint8Array;
|
|
47
|
+
readdir(path: string): string[];
|
|
48
|
+
touch(path: string, metadata: Uint8Array): void;
|
|
49
|
+
exists(path: string): boolean;
|
|
50
|
+
link(target: string, link: string): void;
|
|
51
|
+
sync(path: string): void;
|
|
52
|
+
read(path: string, buffer: Uint8Array, start: number, end: number): Uint8Array;
|
|
53
|
+
write(path: string, buffer: Uint8Array, offset: number): void;
|
|
54
|
+
stat(path: string): Uint8Array;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The methods that can be called on the RPC port
|
|
58
|
+
* @category Internals
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
export type RPCMethod = keyof RPCMethods;
|
|
62
|
+
/**
|
|
63
|
+
* An RPC message
|
|
64
|
+
* @category Internals
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
67
|
+
export interface RPCMessage {
|
|
68
|
+
_zenfs: true;
|
|
69
|
+
id: string;
|
|
70
|
+
method: RPCMethod;
|
|
71
|
+
stack: string;
|
|
72
|
+
}
|
|
73
|
+
interface RPCRequest<TMethod extends RPCMethod = RPCMethod> extends RPCMessage {
|
|
74
|
+
method: TMethod;
|
|
75
|
+
args: Parameters<RPCMethods[TMethod]>;
|
|
76
|
+
}
|
|
77
|
+
export declare function attach<T extends RPCMessage>(port: RPCPort, handler: (message: T) => unknown): void;
|
|
78
|
+
export declare function detach<T extends RPCMessage>(port: RPCPort, handler: (message: T) => unknown): void;
|
|
79
|
+
export declare function catchMessages<T extends Backend>(port: RPCPort): (fs: FilesystemOf<T>) => Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
export declare function waitOnline(port: RPCPort): Promise<void>;
|
|
84
|
+
declare const PortFS_base: import("../index.js").Mixin<typeof FileSystem, import("../mixins/async.js").AsyncMixin>;
|
|
85
|
+
/**
|
|
86
|
+
* PortFS lets you access an FS instance that is running in a port, or the other way around.
|
|
87
|
+
*
|
|
88
|
+
* Note that *direct* synchronous operations are not permitted on the PortFS,
|
|
89
|
+
* regardless of the configuration option of the remote FS.
|
|
90
|
+
* @category Internals
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
export declare class PortFS extends PortFS_base {
|
|
94
|
+
readonly options: PortOptions;
|
|
95
|
+
readonly port: RPCPort;
|
|
96
|
+
/**`
|
|
97
|
+
* @hidden
|
|
98
|
+
*/
|
|
99
|
+
_sync: import("./index.js").StoreFS<import("./memory.js").InMemoryStore>;
|
|
100
|
+
/**
|
|
101
|
+
* Constructs a new PortFS instance that connects with the FS running on `options.port`.
|
|
102
|
+
*/
|
|
103
|
+
constructor(options: PortOptions);
|
|
104
|
+
protected rpc<const T extends RPCMethod>(method: T, ...args: Parameters<RPCMethods[T]>): Promise<Awaited<ReturnType<RPCMethods[T]>>>;
|
|
105
|
+
ready(): Promise<void>;
|
|
106
|
+
rename(oldPath: string, newPath: string): Promise<void>;
|
|
107
|
+
stat(path: string): Promise<Inode>;
|
|
108
|
+
touch(path: string, metadata: InodeLike | Inode): Promise<void>;
|
|
109
|
+
sync(path: string): Promise<void>;
|
|
110
|
+
createFile(path: string, options: CreationOptions): Promise<Inode>;
|
|
111
|
+
unlink(path: string): Promise<void>;
|
|
112
|
+
rmdir(path: string): Promise<void>;
|
|
113
|
+
mkdir(path: string, options: CreationOptions): Promise<Inode>;
|
|
114
|
+
readdir(path: string): Promise<string[]>;
|
|
115
|
+
exists(path: string): Promise<boolean>;
|
|
116
|
+
link(srcpath: string, dstpath: string): Promise<void>;
|
|
117
|
+
read(path: string, buffer: Uint8Array, start: number, end: number): Promise<void>;
|
|
118
|
+
write(path: string, buffer: Uint8Array, offset: number): Promise<void>;
|
|
119
|
+
}
|
|
120
|
+
/** @internal */
|
|
121
|
+
export declare function handleRequest(port: RPCPort, fs: FileSystem & {
|
|
122
|
+
_descriptors?: Map<number, File>;
|
|
123
|
+
}, request: RPCRequest): Promise<void>;
|
|
124
|
+
export declare function attachFS(port: RPCPort, fs: FileSystem): void;
|
|
125
|
+
export declare function detachFS(port: RPCPort, fs: FileSystem): void;
|
|
126
|
+
declare const _Port: {
|
|
127
|
+
name: string;
|
|
128
|
+
options: {
|
|
129
|
+
port: {
|
|
130
|
+
type: (arg: RPCPort) => boolean;
|
|
131
|
+
required: true;
|
|
132
|
+
};
|
|
133
|
+
timeout: {
|
|
134
|
+
type: string;
|
|
135
|
+
required: false;
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
create(options: PortOptions): PortFS;
|
|
139
|
+
};
|
|
140
|
+
type _Port = typeof _Port;
|
|
141
|
+
/**
|
|
142
|
+
* @category Backends and Configuration
|
|
143
|
+
*/
|
|
144
|
+
export interface Port extends _Port {
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* A backend for usage with ports and workers. See the examples below.
|
|
148
|
+
*
|
|
149
|
+
* #### Accessing an FS on a remote Worker from the main thread
|
|
150
|
+
*
|
|
151
|
+
* Main:
|
|
152
|
+
*
|
|
153
|
+
* ```ts
|
|
154
|
+
* import { configure } from '@zenfs/core';
|
|
155
|
+
* import { Port } from '@zenfs/port';
|
|
156
|
+
* import { Worker } from 'node:worker_threads';
|
|
157
|
+
*
|
|
158
|
+
* const worker = new Worker('worker.js');
|
|
159
|
+
*
|
|
160
|
+
* await configure({
|
|
161
|
+
* mounts: {
|
|
162
|
+
* '/worker': {
|
|
163
|
+
* backend: Port,
|
|
164
|
+
* port: worker,
|
|
165
|
+
* },
|
|
166
|
+
* },
|
|
167
|
+
* });
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* Worker:
|
|
171
|
+
*
|
|
172
|
+
* ```ts
|
|
173
|
+
* import { InMemory, resolveRemoteMount, attachFS } from '@zenfs/core';
|
|
174
|
+
* import { parentPort } from 'node:worker_threads';
|
|
175
|
+
*
|
|
176
|
+
* await resolveRemoteMount(parentPort, { backend: InMemory, name: 'tmp' });
|
|
177
|
+
* ```
|
|
178
|
+
*
|
|
179
|
+
* If you are using using web workers, you would use `self` instead of importing `parentPort` in the worker, and would not need to import `Worker` in the main thread.
|
|
180
|
+
*
|
|
181
|
+
* #### Using with multiple ports on the same thread
|
|
182
|
+
*
|
|
183
|
+
* ```ts
|
|
184
|
+
* import { InMemory, fs, resolveMountConfig, resolveRemoteMount, Port } from '@zenfs/core';
|
|
185
|
+
* import { MessageChannel } from 'node:worker_threads';
|
|
186
|
+
*
|
|
187
|
+
* const { port1: localPort, port2: remotePort } = new MessageChannel();
|
|
188
|
+
*
|
|
189
|
+
* fs.mount('/remote', await resolveRemoteMount(remotePort, { backend: InMemory, name: 'tmp' }));
|
|
190
|
+
* fs.mount('/port', await resolveMountConfig({ backend: Port, port: localPort }));
|
|
191
|
+
*
|
|
192
|
+
* const content = 'FS is in a port';
|
|
193
|
+
*
|
|
194
|
+
* await fs.promises.writeFile('/port/test', content);
|
|
195
|
+
*
|
|
196
|
+
* fs.readFileSync('/remote/test', 'utf8'); // FS is in a port
|
|
197
|
+
* await fs.promises.readFile('/port/test', 'utf8'); // FS is in a port
|
|
198
|
+
* ```
|
|
199
|
+
*
|
|
200
|
+
* @category Backends and Configuration
|
|
201
|
+
*/
|
|
202
|
+
export declare const Port: Port;
|
|
203
|
+
/**
|
|
204
|
+
* @category Backends and Configuration
|
|
205
|
+
*/
|
|
206
|
+
export declare function resolveRemoteMount<T extends Backend>(port: RPCPort, config: MountConfiguration<T>, _depth?: number): Promise<FilesystemOf<T>>;
|
|
207
|
+
export {};
|