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>;
