@zenfs/core
Version:
A filesystem, anywhere
144 lines (143 loc) • 5.26 kB
TypeScript
import type { ExceptionJSON } from 'kerium';
import type { TransferListItem } from 'node:worker_threads';
import type { WithOptional } from 'utilium';
import type { Backend, FilesystemOf } from '../backends/backend.js';
import type { PortFS } from '../backends/port.js';
import type { CreationOptions, FileSystem, UsageInfo } from '../internal/filesystem.js';
import '../polyfills.js';
export interface WebMessagePort {
postMessage(value: unknown, transfer?: TransferListItem[]): void;
addEventListener(type: 'message', listener: (ev: {
data: any;
}) => void): void;
removeEventListener(type: 'message', listener: (ev: {
data: any;
}) => void): void;
}
export interface NodeMessagePort {
postMessage(value: unknown, transfer?: TransferListItem[]): void;
on(type: 'message', listener: (ev: any) => void): void;
off(type: 'message', listener: (ev: any) => void): void;
}
export type Channel = NodeMessagePort | WebMessagePort | WebSocket;
/** @internal */
export interface Port<T extends Channel = Channel> {
readonly channel: T;
/** Send a request */
send<M extends Message>(message: M, transfer?: TransferListItem[]): void;
/** Add a response handler */
addHandler<M extends Message>(handler: (message: M) => void): void;
/** Remove a response handler */
removeHandler<M extends Message>(handler: (message: M) => void): void;
/** Remove all handlers */
disconnect?(): void;
}
export declare function isPort<T extends Channel>(port: unknown): port is Port<T>;
/**
* Creates a new RPC port from a `Worker` or `MessagePort` that extends `EventTarget`
*/
export declare function fromWeb<T extends WebMessagePort>(port: T): Port<T>;
/**
* Creates a new RPC port from a Node.js `Worker` or `MessagePort`.
*/
export declare function fromNode<T extends NodeMessagePort>(port: T): Port<T>;
/**
* Creates a new RPC port from a WebSocket.
* @experimental
*/
export declare function fromWebSocket<T extends WebSocket>(ws: T): Port<T>;
export declare function from<T extends Channel>(port: T | Port<T>): Port<T>;
/**
* The options for the RPC options
* @category Backends and Configuration
*/
export interface Options {
/**
* The target port that you want to connect to, or the current port if in a port context.
*/
port: Port;
/**
* How long to wait for a request to complete
*/
timeout?: number;
}
/**
* The API for remote procedure calls
* @category Internals
* @internal
*/
export interface Methods {
usage(): UsageInfo;
ready(): void;
rename(oldPath: string, newPath: string): void;
createFile(path: string, options: CreationOptions): Uint8Array;
unlink(path: string): void;
rmdir(path: string): void;
mkdir(path: string, options: CreationOptions): Uint8Array;
readdir(path: string): string[];
touch(path: string, metadata: Uint8Array): void;
exists(path: string): boolean;
link(target: string, link: string): void;
sync(): void;
read(path: string, buffer: Uint8Array, start: number, end: number): Uint8Array;
write(path: string, buffer: Uint8Array, offset: number): void;
stat(path: string): Uint8Array;
}
/**
* The methods that can be called on the RPC port
* @category Internals
* @internal
*/
export type Method = keyof Methods;
/**
* An RPC message
* @category Internals
* @internal
*/
export interface Message {
_zenfs: true;
id: string;
method: Method;
stack: string;
}
export interface Request<TMethod extends Method = Method> extends Message {
method: TMethod;
args: Parameters<Methods[TMethod]>;
}
export interface Response<TMethod extends Method = Method> extends Message {
error?: WithOptional<ExceptionJSON, 'code' | 'errno'>;
method: TMethod;
value: ReturnType<Methods[TMethod]>;
}
/**
* Encode a RPC message as a string using JSON.
* This is only done when structured cloning is not available.
* @internal
*/
export declare function encodeMessage(message: Message): string;
/**
* Decode a RPC message from a string using JSON.
* This is only done when structured cloning is not available.
* @internal
*/
export declare function decodeMessage<T extends Message>(message: string): T;
export declare function isMessage(arg: unknown): arg is Message;
/**
* An RPC executor
* @internal @hidden
*/
export interface Executor extends PromiseWithResolvers<any> {
fs: PortFS;
timeout: ReturnType<typeof setTimeout>;
}
export declare function request<const TRequest extends Request, TValue>(request: Omit<TRequest, 'id' | 'stack' | '_zenfs'>, { port, timeout: ms, fs }: Partial<Options> & {
fs: PortFS;
}): Promise<TValue>;
export declare function handleResponse<const TMethod extends Method>(response: Response<TMethod>): void;
export declare function attach<T extends Message>(port: Port, handler: (message: T) => unknown): void;
export declare function detach<T extends Message>(port: Port, handler: (message: T) => unknown): void;
export declare function catchMessages<T extends Backend>(port: Port): (fs: FilesystemOf<T>) => Promise<void>;
/** @internal */
export declare function handleRequest(port: Port, fs: FileSystem & {
_descriptors?: Map<number, File>;
}, request: Request): Promise<void>;