import { Duplex } from 'node:stream';
import { IncomingMessage } from 'node:http';
import WebSocket, { ServerOptions } from 'ws';

type SocketResponse<T = any> = {
  id?: number | null;
  jsonrpc: string;
  result?: T;
  notification?: string;
  params?: any;
  error?: {
    code: number;
    message: string;
    data?: any;
  };
};

type SocketSendOptions = {
  timeout?: number;
};

declare function Client(endpoint: string, opts?: SocketSendOptions): Promise<{
    subscribe: <T = any>(namespace: string, cb: (params: T) => void) => Promise<SocketResponse>;
    unsubscribe: (namespace: string) => Promise<SocketResponse<any>>;
    close: () => void;
} & {
    [k: string]: <T_1>(...args: any) => Promise<SocketResponse<T_1>>;
}>;

type RegisterFn<T = any> = (params: T, socketId: string) => Promise<any> | any;
type SocketEvents = {
    listening: () => Promise<void> | void;
    connection: (socket: WebSocket, socketId: string) => Promise<void> | void;
    disconnection: (socketId: string) => Promise<void> | void;
    error: (error: Error) => Promise<void> | void;
    "socket-error": (socketId: string, error: Error) => Promise<void> | void;
    close: () => Promise<void> | void;
};
declare function Server(opts: ServerOptions): {
    on: <EventKey extends keyof SocketEvents>(event: EventKey, cb: SocketEvents[EventKey]) => void;
    of: (ns: string) => {
        emit: (name: string, ...params: any[]) => void;
        clients: () => Map<string, WebSocket>;
        register: <T = any>(method: string, fn: RegisterFn<T>) => void;
        event: (name: string) => void;
    };
    event: (e: string) => void;
    handleUpgrade: (req: IncomingMessage, socket: Duplex, upgradeHead: Buffer, callback?: ((client: WebSocket.WebSocket, request: IncomingMessage) => void) | undefined) => Promise<void>;
    clients: () => Map<string, WebSocket>;
    register: <T_1 = any>(method: string, fn: RegisterFn<T_1>) => void;
    emit: (name: string, ...params: any[]) => void;
    close: () => Promise<unknown>;
};

export { Client, Server };
