@zenfs/core 0.15.2 → 0.16.1
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/port/fs.d.ts +23 -1
- package/dist/backends/port/fs.js +14 -11
- package/dist/backends/port/rpc.d.ts +20 -14
- package/dist/backends/port/rpc.js +16 -3
- package/dist/backends/store/fs.d.ts +1 -1
- package/dist/backends/store/fs.js +11 -12
- package/dist/browser.min.js +4 -4
- package/dist/browser.min.js.map +4 -4
- package/dist/config.d.ts +1 -2
- package/dist/emulation/promises.d.ts +1 -1
- package/dist/emulation/promises.js +3 -3
- package/dist/emulation/sync.js +2 -2
- package/dist/stats.d.ts +2 -5
- package/dist/stats.js +2 -25
- package/package.json +8 -2
- package/src/backends/port/fs.ts +31 -17
- package/src/backends/port/readme.md +7 -12
- package/src/backends/port/rpc.ts +37 -17
- package/src/backends/store/fs.ts +12 -12
- package/src/config.ts +1 -1
- package/src/emulation/promises.ts +3 -3
- package/src/emulation/sync.ts +1 -1
- package/src/stats.ts +4 -21
|
@@ -6,9 +6,17 @@ import type { Cred } from '../../cred.js';
|
|
|
6
6
|
import { File } from '../../file.js';
|
|
7
7
|
import { FileSystem, type FileSystemMetadata } from '../../filesystem.js';
|
|
8
8
|
import { Stats, type FileType } from '../../stats.js';
|
|
9
|
+
import type { Backend, FilesystemOf } from '../backend.js';
|
|
9
10
|
import * as RPC from './rpc.js';
|
|
10
|
-
|
|
11
|
+
import { type MountConfiguration } from '../../config.js';
|
|
12
|
+
type FileMethods = Omit<ExtractProperties<File, (...args: any[]) => Promise<any>>, typeof Symbol.asyncDispose>;
|
|
11
13
|
type FileMethod = keyof FileMethods;
|
|
14
|
+
interface FileRequest<TMethod extends FileMethod = FileMethod> extends RPC.Request {
|
|
15
|
+
fd: number;
|
|
16
|
+
scope: 'file';
|
|
17
|
+
method: TMethod;
|
|
18
|
+
args: Parameters<FileMethods[TMethod]>;
|
|
19
|
+
}
|
|
12
20
|
export declare class PortFile extends File {
|
|
13
21
|
readonly fs: PortFS;
|
|
14
22
|
readonly fd: number;
|
|
@@ -40,6 +48,11 @@ export declare class PortFile extends File {
|
|
|
40
48
|
}
|
|
41
49
|
type FSMethods = ExtractProperties<FileSystem, (...args: any[]) => Promise<any> | FileSystemMetadata>;
|
|
42
50
|
type FSMethod = keyof FSMethods;
|
|
51
|
+
interface FSRequest<TMethod extends FSMethod = FSMethod> extends RPC.Request {
|
|
52
|
+
scope: 'fs';
|
|
53
|
+
method: TMethod;
|
|
54
|
+
args: Parameters<FSMethods[TMethod]>;
|
|
55
|
+
}
|
|
43
56
|
declare const PortFS_base: import("../../filesystem.js").Mixin<typeof FileSystem, {
|
|
44
57
|
_sync?: FileSystem | undefined;
|
|
45
58
|
queueDone(): Promise<void>;
|
|
@@ -88,6 +101,14 @@ export declare class PortFS extends PortFS_base {
|
|
|
88
101
|
exists(path: string, cred: Cred): Promise<boolean>;
|
|
89
102
|
link(srcpath: string, dstpath: string, cred: Cred): Promise<void>;
|
|
90
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* @internal
|
|
106
|
+
*/
|
|
107
|
+
export type FileOrFSRequest = FSRequest | FileRequest;
|
|
108
|
+
/**
|
|
109
|
+
* @internal
|
|
110
|
+
*/
|
|
111
|
+
export declare function handleRequest(port: RPC.Port, fs: FileSystem, request: FileOrFSRequest): Promise<void>;
|
|
91
112
|
export declare function attachFS(port: RPC.Port, fs: FileSystem): void;
|
|
92
113
|
export declare function detachFS(port: RPC.Port, fs: FileSystem): void;
|
|
93
114
|
export declare const Port: {
|
|
@@ -108,4 +129,5 @@ export declare const Port: {
|
|
|
108
129
|
isAvailable(): Promise<boolean>;
|
|
109
130
|
create(options: RPC.Options): PortFS;
|
|
110
131
|
};
|
|
132
|
+
export declare function resolveRemoteMount<T extends Backend>(port: RPC.Port, config: MountConfiguration<T>, _depth?: number): Promise<FilesystemOf<T>>;
|
|
111
133
|
export {};
|
package/dist/backends/port/fs.js
CHANGED
|
@@ -4,6 +4,7 @@ import { Async, FileSystem } from '../../filesystem.js';
|
|
|
4
4
|
import { Stats } from '../../stats.js';
|
|
5
5
|
import { InMemory } from '../memory.js';
|
|
6
6
|
import * as RPC from './rpc.js';
|
|
7
|
+
import { resolveMountConfig } from '../../config.js';
|
|
7
8
|
export class PortFile extends File {
|
|
8
9
|
constructor(fs, fd, path, position) {
|
|
9
10
|
super();
|
|
@@ -159,7 +160,10 @@ export class PortFS extends Async(FileSystem) {
|
|
|
159
160
|
}
|
|
160
161
|
let nextFd = 0;
|
|
161
162
|
const descriptors = new Map();
|
|
162
|
-
|
|
163
|
+
/**
|
|
164
|
+
* @internal
|
|
165
|
+
*/
|
|
166
|
+
export async function handleRequest(port, fs, request) {
|
|
163
167
|
if (!RPC.isMessage(request)) {
|
|
164
168
|
return;
|
|
165
169
|
}
|
|
@@ -195,18 +199,10 @@ async function handleRequest(port, fs, request) {
|
|
|
195
199
|
}
|
|
196
200
|
}
|
|
197
201
|
catch (e) {
|
|
198
|
-
value = e;
|
|
202
|
+
value = e instanceof ErrnoError ? e.toJSON() : e.toString();
|
|
199
203
|
error = true;
|
|
200
204
|
}
|
|
201
|
-
port.postMessage({
|
|
202
|
-
_zenfs: true,
|
|
203
|
-
scope,
|
|
204
|
-
id,
|
|
205
|
-
error,
|
|
206
|
-
method,
|
|
207
|
-
stack,
|
|
208
|
-
value: value instanceof ErrnoError ? value.toJSON() : value,
|
|
209
|
-
});
|
|
205
|
+
port.postMessage({ _zenfs: true, scope, id, error, method, stack, value });
|
|
210
206
|
}
|
|
211
207
|
export function attachFS(port, fs) {
|
|
212
208
|
RPC.attach(port, request => handleRequest(port, fs, request));
|
|
@@ -241,3 +237,10 @@ export const Port = {
|
|
|
241
237
|
return new PortFS(options);
|
|
242
238
|
},
|
|
243
239
|
};
|
|
240
|
+
export async function resolveRemoteMount(port, config, _depth = 0) {
|
|
241
|
+
const stopAndReplay = RPC.catchMessages(port);
|
|
242
|
+
const fs = await resolveMountConfig(config, _depth);
|
|
243
|
+
attachFS(port, fs);
|
|
244
|
+
stopAndReplay(fs);
|
|
245
|
+
return fs;
|
|
246
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
|
|
3
|
-
import type {
|
|
2
|
+
import { type ErrnoErrorJSON } from '../../error.js';
|
|
3
|
+
import type { Backend, FilesystemOf } from '../backend.js';
|
|
4
4
|
import { type PortFS } from './fs.js';
|
|
5
5
|
type _MessageEvent<T = any> = T | {
|
|
6
6
|
data: T;
|
|
7
7
|
};
|
|
8
8
|
export interface Port {
|
|
9
|
-
postMessage(value: unknown
|
|
9
|
+
postMessage(value: unknown): void;
|
|
10
10
|
on?(event: 'message', listener: (value: unknown) => void): this;
|
|
11
11
|
off?(event: 'message', listener: (value: unknown) => void): this;
|
|
12
|
-
addEventListener?(type: 'message', listener: (
|
|
13
|
-
removeEventListener?(type: 'message', listener: (
|
|
12
|
+
addEventListener?(type: 'message', listener: (ev: _MessageEvent) => void): void;
|
|
13
|
+
removeEventListener?(type: 'message', listener: (ev: _MessageEvent) => void): void;
|
|
14
14
|
}
|
|
15
15
|
export interface Options {
|
|
16
16
|
/**
|
|
@@ -25,27 +25,32 @@ export interface Options {
|
|
|
25
25
|
/**
|
|
26
26
|
* An RPC message
|
|
27
27
|
*/
|
|
28
|
-
export interface Message
|
|
28
|
+
export interface Message {
|
|
29
29
|
_zenfs: true;
|
|
30
|
-
scope:
|
|
30
|
+
scope: 'fs' | 'file';
|
|
31
31
|
id: string;
|
|
32
|
-
method:
|
|
32
|
+
method: string;
|
|
33
33
|
stack: string;
|
|
34
34
|
}
|
|
35
|
-
export interface Request
|
|
36
|
-
args:
|
|
35
|
+
export interface Request extends Message {
|
|
36
|
+
args: unknown[];
|
|
37
|
+
}
|
|
38
|
+
interface _ResponseWithError extends Message {
|
|
39
|
+
error: true;
|
|
40
|
+
value: ErrnoErrorJSON | string;
|
|
37
41
|
}
|
|
38
|
-
|
|
39
|
-
error:
|
|
40
|
-
value: Awaited<
|
|
42
|
+
interface _ResponseWithValue<T> extends Message {
|
|
43
|
+
error: false;
|
|
44
|
+
value: Awaited<T> extends File ? FileData : Awaited<T>;
|
|
41
45
|
}
|
|
46
|
+
export type Response<T = unknown> = _ResponseWithError | _ResponseWithValue<T>;
|
|
42
47
|
export interface FileData {
|
|
43
48
|
fd: number;
|
|
44
49
|
path: string;
|
|
45
50
|
position: number;
|
|
46
51
|
}
|
|
47
52
|
export { FileData as File };
|
|
48
|
-
export declare function isMessage(arg: unknown): arg is Message
|
|
53
|
+
export declare function isMessage(arg: unknown): arg is Message;
|
|
49
54
|
type _Executor = Parameters<ConstructorParameters<typeof Promise<any>>[0]>;
|
|
50
55
|
export interface Executor {
|
|
51
56
|
resolve: _Executor[0];
|
|
@@ -58,3 +63,4 @@ export declare function request<const TRequest extends Request, TValue>(request:
|
|
|
58
63
|
export declare function handleResponse<const TResponse extends Response>(response: TResponse): void;
|
|
59
64
|
export declare function attach<T extends Message>(port: Port, handler: (message: T) => unknown): void;
|
|
60
65
|
export declare function detach<T extends Message>(port: Port, handler: (message: T) => unknown): void;
|
|
66
|
+
export declare function catchMessages<T extends Backend>(port: Port): (fs: FilesystemOf<T>) => void;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { Errno, ErrnoError } from '../../error.js';
|
|
3
|
+
import { handleRequest, PortFile } from './fs.js';
|
|
3
4
|
function isFileData(value) {
|
|
4
5
|
return typeof value == 'object' && value != null && 'fd' in value && 'path' in value && 'position' in value;
|
|
5
6
|
}
|
|
@@ -38,7 +39,7 @@ export function handleResponse(response) {
|
|
|
38
39
|
}
|
|
39
40
|
const { resolve, reject, fs } = executors.get(id);
|
|
40
41
|
if (error) {
|
|
41
|
-
const e = ErrnoError.fromJSON(value);
|
|
42
|
+
const e = typeof value == 'string' ? new Error(value) : ErrnoError.fromJSON(value);
|
|
42
43
|
e.stack += stack;
|
|
43
44
|
reject(e);
|
|
44
45
|
executors.delete(id);
|
|
@@ -71,3 +72,15 @@ export function detach(port, handler) {
|
|
|
71
72
|
handler('data' in message ? message.data : message);
|
|
72
73
|
});
|
|
73
74
|
}
|
|
75
|
+
export function catchMessages(port) {
|
|
76
|
+
const events = [];
|
|
77
|
+
const handler = events.push.bind(events);
|
|
78
|
+
attach(port, handler);
|
|
79
|
+
return function (fs) {
|
|
80
|
+
detach(port, handler);
|
|
81
|
+
for (const event of events) {
|
|
82
|
+
const request = 'data' in event ? event.data : event;
|
|
83
|
+
handleRequest(port, fs, request);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
@@ -2,7 +2,7 @@ import type { Cred } from '../../cred.js';
|
|
|
2
2
|
import { PreloadFile } from '../../file.js';
|
|
3
3
|
import { FileSystem, type FileSystemMetadata } from '../../filesystem.js';
|
|
4
4
|
import { type Ino, Inode } from '../../inode.js';
|
|
5
|
-
import {
|
|
5
|
+
import type { FileType, Stats } from '../../stats.js';
|
|
6
6
|
import type { Store, Transaction } from './store.js';
|
|
7
7
|
/**
|
|
8
8
|
* A file system which uses a key-value store.
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { R_OK, S_IFDIR, S_IFREG, W_OK } from '../../emulation/constants.js';
|
|
2
|
+
import { basename, dirname, join, resolve } from '../../emulation/path.js';
|
|
3
|
+
import { Errno, ErrnoError } from '../../error.js';
|
|
4
4
|
import { PreloadFile, flagToMode } from '../../file.js';
|
|
5
5
|
import { FileSystem } from '../../filesystem.js';
|
|
6
|
-
import { Inode,
|
|
7
|
-
import {
|
|
8
|
-
import { encodeDirListing, encode, decodeDirListing } from '../../utils.js';
|
|
6
|
+
import { Inode, randomIno, rootIno } from '../../inode.js';
|
|
7
|
+
import { decodeDirListing, encode, encodeDirListing } from '../../utils.js';
|
|
9
8
|
const maxInodeAllocTries = 5;
|
|
10
9
|
/**
|
|
11
10
|
* A file system which uses a key-value store.
|
|
@@ -199,11 +198,11 @@ export class StoreFS extends FileSystem {
|
|
|
199
198
|
}
|
|
200
199
|
async createFile(path, flag, mode, cred) {
|
|
201
200
|
const data = new Uint8Array(0);
|
|
202
|
-
const file = await this.commitNew(this.store.transaction(), path,
|
|
201
|
+
const file = await this.commitNew(this.store.transaction(), path, S_IFREG, mode, cred, data);
|
|
203
202
|
return new PreloadFile(this, path, flag, file.toStats(), data);
|
|
204
203
|
}
|
|
205
204
|
createFileSync(path, flag, mode, cred) {
|
|
206
|
-
this.commitNewSync(path,
|
|
205
|
+
this.commitNewSync(path, S_IFREG, mode, cred);
|
|
207
206
|
return this.openFileSync(path, flag, cred);
|
|
208
207
|
}
|
|
209
208
|
async openFile(path, flag, cred) {
|
|
@@ -251,10 +250,10 @@ export class StoreFS extends FileSystem {
|
|
|
251
250
|
}
|
|
252
251
|
async mkdir(path, mode, cred) {
|
|
253
252
|
const tx = this.store.transaction(), data = encode('{}');
|
|
254
|
-
await this.commitNew(tx, path,
|
|
253
|
+
await this.commitNew(tx, path, S_IFDIR, mode, cred, data);
|
|
255
254
|
}
|
|
256
255
|
mkdirSync(path, mode, cred) {
|
|
257
|
-
this.commitNewSync(path,
|
|
256
|
+
this.commitNewSync(path, S_IFDIR, mode, cred, encode('{}'));
|
|
258
257
|
}
|
|
259
258
|
async readdir(path, cred) {
|
|
260
259
|
const tx = this.store.transaction();
|
|
@@ -378,7 +377,7 @@ export class StoreFS extends FileSystem {
|
|
|
378
377
|
}
|
|
379
378
|
// Create new inode. o777, owned by root:root
|
|
380
379
|
const inode = new Inode();
|
|
381
|
-
inode.mode = 0o777 |
|
|
380
|
+
inode.mode = 0o777 | S_IFDIR;
|
|
382
381
|
// If the root doesn't exist, the first random ID shouldn't exist either.
|
|
383
382
|
await tx.set(inode.ino, encode('{}'));
|
|
384
383
|
await tx.set(rootIno, inode.data);
|
|
@@ -394,7 +393,7 @@ export class StoreFS extends FileSystem {
|
|
|
394
393
|
}
|
|
395
394
|
// Create new inode, mode o777, owned by root:root
|
|
396
395
|
const inode = new Inode();
|
|
397
|
-
inode.mode = 0o777 |
|
|
396
|
+
inode.mode = 0o777 | S_IFDIR;
|
|
398
397
|
// If the root doesn't exist, the first random ID shouldn't exist either.
|
|
399
398
|
tx.setSync(inode.ino, encode('{}'));
|
|
400
399
|
tx.setSync(rootIno, inode.data);
|