import type { BinaryReader, BinaryWriter } from '@bufbuild/protobuf/wire';
import type { ClassType } from '@deepkit/core';
import { ScopedLogger } from '@deepkit/logger';
import WebSocket from 'ws';
import type { IByteStreamable } from './SrpcByteStream';
export type RequestKeys<T> = {
    [K in keyof T]: K extends `${infer _X}Request` ? K : never;
}[keyof T];
export type ResponseKeys<T> = {
    [K in keyof T]: K extends `${infer _X}Response` ? K : never;
}[keyof T];
/**
 * Extract prefix from Request keys (e.g., 'uEcho' from 'uEchoRequest')
 */
export type RequestPrefix<K> = K extends `${infer P}Request` ? P : never;
/**
 * Extract prefix from Response keys (e.g., 'uEcho' from 'uEchoResponse')
 */
export type ResponsePrefix<K> = K extends `${infer P}Response` ? P : never;
/**
 * Get all valid invoke prefixes where TReq has `${P}Request` and TRes has `${P}Response`.
 * Excludes string index signatures to prevent overly permissive typing.
 */
export type InvokePrefixes<TReq, TRes> = {
    [K in keyof TReq]: K extends string ? (K extends `${infer P}Request` ? (`${P}Response` extends keyof TRes ? P : never) : never) : never;
}[keyof TReq];
/**
 * Get the request data type for a given prefix (for sending requests).
 */
export type RequestData<TReq, P extends string> = `${P}Request` extends keyof TReq ? NonNullable<TReq[`${P}Request`]> : never;
/**
 * Get the response data type for a given prefix.
 */
export type ResponseData<TRes, P extends string> = `${P}Response` extends keyof TRes ? NonNullable<TRes[`${P}Response`]> : never;
/**
 * Get the request data type for a handler (for receiving requests).
 */
export type HandlerRequestData<TReq, P extends string> = `${P}Request` extends keyof TReq ? NonNullable<TReq[`${P}Request`]> : never;
export type SrpcMeta = Record<string, any>;
export interface BaseMessage {
    requestId?: string;
    reply?: boolean;
    error?: string;
    userError?: boolean;
    trace?: {
        traceId: string;
        spanId: string;
        traceFlags: number;
    };
    pingPong?: {};
    byteStreamOperation?: {
        streamId: number;
        write?: {
            chunk: Uint8Array;
        };
        finish?: {};
        destroy?: {
            error?: string;
        };
    };
}
/**
 * Interface for ts-proto generated message types with encode/decode functions.
 * This matches the MessageFns interface generated by ts-proto.
 */
export interface SrpcMessageFns<T> {
    encode(message: T, writer?: BinaryWriter): BinaryWriter;
    decode(input: BinaryReader | Uint8Array, length?: number): T;
}
export type SrpcDisconnectCause = 'disconnect' | 'conflict' | 'supersede' | 'timeout' | 'badArg';
export interface IQueuedRequest {
    exp: number;
    resolve: (value: any) => void;
    reject: (err: any) => void;
}
export declare class SrpcError extends Error {
    message: string;
    isUserError?: boolean | undefined;
    constructor(message: string, isUserError?: boolean | undefined);
}
export interface ISrpcServerOptions<TClientOutput extends BaseMessage, TServerOutput extends BaseMessage> {
    logger: ScopedLogger;
    /** ts-proto generated ClientMessage type with encode/decode */
    clientMessage: SrpcMessageFns<TClientOutput>;
    /** ts-proto generated ServerMessage type with encode/decode */
    serverMessage: SrpcMessageFns<TServerOutput>;
    wsPath: string;
    debug?: boolean;
    /** Controls SRPC log output. 'info' (default) logs normally, 'debug' downgrades to debug level, false suppresses all logs. */
    logLevel?: 'info' | 'debug' | false;
}
export interface SrpcStream<T = SrpcMeta> extends IByteStreamable {
    $ws: WebSocket;
    $queue: Map<string, IQueuedRequest>;
    readonly id: string;
    readonly clientStreamId: string;
    readonly address: string;
    readonly clientId: string;
    readonly appVersion: string;
    readonly configureTs: number;
    readonly protocolVersion: number;
    readonly supersede: boolean;
    readonly meta: T;
    readonly connectedAt: number;
    isActivated: boolean;
    lastPingAt: number;
}
export type SrpcMessageHandlerFn<C, I, O> = (wrappedStream: C, data: I) => Promise<O>;
export interface ISrpcMessageHandler<C, I, O> {
    handle: SrpcMessageHandlerFn<C, I, O>;
}
export type TSrpcMessageHandlerClass<C, I, O> = ClassType<ISrpcMessageHandler<C, I, O>>;
export type TSrpcMessageHandlerFnOrClass<C, I, O> = SrpcMessageHandlerFn<C, I, O> | TSrpcMessageHandlerClass<C, I, O>;
export declare const isSrpcMessageHandlerClass: <C, I, O>(handler: TSrpcMessageHandlerFnOrClass<C, I, O>) => handler is TSrpcMessageHandlerClass<C, I, O>;
export declare type __ΩRequestKeys = any[];
export declare type __ΩResponseKeys = any[];
export declare type __ΩRequestPrefix = any[];
export declare type __ΩResponsePrefix = any[];
export declare type __ΩInvokePrefixes = any[];
export declare type __ΩRequestData = any[];
export declare type __ΩResponseData = any[];
export declare type __ΩHandlerRequestData = any[];
export declare type __ΩSrpcMeta = any[];
export declare type __ΩBaseMessage = any[];
export declare type __ΩSrpcMessageFns = any[];
export declare type __ΩSrpcDisconnectCause = any[];
export declare type __ΩIQueuedRequest = any[];
export declare type __ΩISrpcServerOptions = any[];
export declare type __ΩSrpcStream = any[];
export declare type __ΩSrpcMessageHandlerFn = any[];
export declare type __ΩISrpcMessageHandler = any[];
export declare type __ΩTSrpcMessageHandlerClass = any[];
export declare type __ΩTSrpcMessageHandlerFnOrClass = any[];
//# sourceMappingURL=types.d.ts.map