import { S as SockaContractBound, a as SockaWireFormat, I as InferSockaHandlers, m as SockaReportError, c as InferSockaPushPayload } from './socka-report-error-BALZPjd1.js';

/** Session data with no fields — `createData` may be omitted (defaults to `{}`). */
type EmptySockaSessionData$1 = Record<string, never>;
/**
 * Upgrade context passed into `createData` for {@link SockaWebSocketSession} when
 * **`strictUpgradeRequest: false`** is set (opt out of the default strict upgrade).
 *
 * **`request` is optional** because some call sites attach a socket without an HTTP upgrade
 * (custom tests, unusual adapters, Node **`ws`** without a **`Request`**, inner DO engine).
 * If you read query params or headers from the upgrade, either handle a missing
 * **`request`** here, or use the default strict mode (omit **`strictUpgradeRequest: false`**)
 * so {@link SockaStrictWebSocketInit} applies.
 */
type SockaWebSocketInit = {
    /**
     * Original HTTP **`Request`** for the WebSocket upgrade, when the adapter supplies it
     * (e.g. the optional fourth argument to **`attachSockaWebSocket`**).
     */
    request?: Request;
};
/**
 * Upgrade context for {@link SockaWebSocketSession} when using the default strict config
 * ({@link SockaWebSocketSessionConfig} — no `strictUpgradeRequest` field).
 *
 * **What this enables:** `createData` is typed so **`init.request` is always defined**.
 * You can use **`new URL(init.request.url)`**, read search params, and use **`Request`**
 * headers without optional chaining or a dummy base URL for **`URL`** parsing.
 *
 * **Runtime behavior:** If the adapter does not pass a `Request` while strict mode is on,
 * socka throws an error explaining how to wire the upgrade (e.g. Bun `data: { request: req }`,
 * or Hono default `sockaInit`).
 *
 * **Typical use:** Bun **`Bun.serve`** upgrades and Hono **`sockaHonoNodeWs`** /
 * **`sockaHonoCloudflare`** where the incoming HTTP request is available and should drive
 * `session.data` (names, cookies, etc.).
 */
type SockaStrictWebSocketInit = {
    request: Request;
};
type SockaWebSocketCreateData<TData> = [TData] extends [EmptySockaSessionData$1] ? {
    createData?: (init: SockaWebSocketInit) => TData;
} : {
    createData: (init: SockaWebSocketInit) => TData;
};
type SockaWebSocketCreateDataStrict<TData> = [TData] extends [
    EmptySockaSessionData$1
] ? {
    createData?: (init: SockaStrictWebSocketInit) => TData;
} : {
    createData: (init: SockaStrictWebSocketInit) => TData;
};
type SockaSessionForHandlers<TContract extends SockaContractBound, TData> = SockaWebSocketSession<TContract, TData>;
type SockaWebSocketSessionConfigBase<TContract extends SockaContractBound, TData> = {
    contract: TContract;
    /** Default `"json"`. Use `"msgpack"` for binary frames (must match client). */
    wireFormat?: SockaWireFormat;
    handlers: InferSockaHandlers<TContract, SockaSessionForHandlers<TContract, TData>>;
    /** Called when this WebSocket closes, before the socket is removed from `sessions`. */
    handleClose: (session: SockaSessionForHandlers<TContract, TData>) => Promise<void>;
    onHandlerError?: (error: unknown, rpcName: string, input: unknown, session: SockaSessionForHandlers<TContract, TData>) => void;
    onValidationError?: (error: unknown, originalMessage: unknown) => Promise<void>;
    /**
     * Optional sink for non-RPC failures (onAttached, adapter I/O). Defaults to
     * `console.error` with `socka:` prefixes; see `SockaReportError` in `@firtoz/socka/core`.
     */
    reportError?: (event: SockaReportError) => void;
    serializeJson?: (value: unknown) => string;
    deserializeJson?: (raw: string) => unknown;
    /**
     * Called once after this session is registered in the shared `sessions` map
     * (safe to broadcast to peers). Sync or async; async rejections are logged.
     */
    onAttached?: (session: SockaSessionForHandlers<TContract, TData>) => void | Promise<void>;
};
/**
 * Configuration for {@link SockaWebSocketSession} — **default (strict upgrade)**.
 *
 * Handlers receive the session as the second argument, or the only argument when the call
 * has no input schema.
 *
 * **`createData`** receives {@link SockaStrictWebSocketInit}: **`init.request`** is the
 * HTTP upgrade **`Request`**, required in TypeScript and enforced at runtime. Use for
 * normal Bun/Hono apps and **`attachSockaWebSocket(websocket, sessions, config, { request })`**.
 *
 * Bun helpers: store **`request`** on **`ServerWebSocket`** `data` and use
 * **`sockaBunInitFromWsData`** (see **`@firtoz/socka/bun`**). Hono: **`sockaHonoNodeWs`** /
 * **`sockaHonoCloudflare`** can supply **`sockaInit`** from the context so **`createData`**
 * still sees a **`Request`**.
 *
 * To allow a missing upgrade **`Request`** (tests, Node **`ws`**, inner DO engine), use
 * {@link SockaWebSocketSessionConfigLoose} instead. See the **Server** guide section
 * **Strict upgrade request** in the package docs.
 */
type SockaWebSocketSessionConfig<TContract extends SockaContractBound, TData = EmptySockaSessionData$1> = SockaWebSocketSessionConfigBase<TContract, TData> & SockaWebSocketCreateDataStrict<TData>;
/**
 * Configuration for {@link SockaWebSocketSession} — **loose upgrade** (opt out of strict).
 *
 * Sets **`strictUpgradeRequest: false`**. **`createData`** receives {@link SockaWebSocketInit};
 * **`init.request` may be `undefined`**.
 *
 * Use when:
 *
 * - Custom **`attachSockaWebSocket`** call sites or tests that do not attach an HTTP
 *   **`Request`**
 * - Node **`ws`** or other adapters where you only have a **`WebSocket`**
 * - The inner **`SockaWebSocketSession`** constructed inside **`SockaDoSession`** (socka sets
 *   this mode for you)
 *
 * If you read query params or headers from the upgrade, guard for a missing **`request`**
 * or switch to {@link SockaWebSocketSessionConfig} and wire the real **`Request`** through.
 */
type SockaWebSocketSessionConfigLoose<TContract extends SockaContractBound, TData = EmptySockaSessionData$1> = SockaWebSocketSessionConfigBase<TContract, TData> & {
    strictUpgradeRequest: false;
} & SockaWebSocketCreateData<TData>;
/**
 * Union of {@link SockaWebSocketSessionConfig} (strict) and {@link SockaWebSocketSessionConfigLoose}.
 * This is the type accepted by {@link SockaWebSocketSession}'s constructor,
 * **`attachSockaWebSocket`**, **`createSockaBunWebSocketHandlers`**, and Hono socka helpers.
 */
type SockaWebSocketSessionConfigUnion<TContract extends SockaContractBound, TData = EmptySockaSessionData$1> = SockaWebSocketSessionConfig<TContract, TData> | SockaWebSocketSessionConfigLoose<TContract, TData>;

/** Session data with no fields — `createData` may be omitted (defaults to `{}`). */
type EmptySockaSessionData = Record<string, never>;

/** Session that can send a wire-level server event (already validated). */
type SockaEmitCapable = {
    emitWireEvent(event: string, body: unknown): void;
};
/**
 * Contract-typed session surface for handlers that push to clients.
 */
interface SockaPushSession<TContract extends SockaContractBound> {
    emitPush<K extends keyof TContract["pushes"] & string>(name: K, body: InferSockaPushPayload<TContract, K>): Promise<void>;
    broadcastPush<K extends keyof TContract["pushes"] & string>(name: K, body: InferSockaPushPayload<TContract, K>, excludeSelf?: boolean): Promise<void>;
}
/**
 * Broadcast a socka server event to every session in the map (optionally
 * excluding the caller). Payload must already be contract-validated.
 *
 * Exclusion uses the **WebSocket** identity (`self.websocket`), not the session
 * object reference, so the same `sessions` map can hold `SockaDoSession` while
 * `broadcastPush` runs on `this.socka` (inner {@link SockaWebSocketSession}).
 *
 * When there is no caller session, use {@link broadcastSockaEventToAll} or
 * {@link broadcastContractPushToAll} instead of picking an arbitrary anchor.
 */
declare function broadcastSockaEventToPeers(sessions: Map<WebSocket, SockaEmitCapable>, self: SockaEmitCapable & {
    readonly websocket: WebSocket;
}, event: string, body: unknown, excludeSelf?: boolean): void;
/**
 * Broadcast a socka server event to **every** session in the map. Payload must
 * already be contract-validated.
 *
 * Use when there is no originating WebSocket session (HTTP admin routes, alarms,
 * cron). Prefer {@link broadcastContractPushToAll} so validation stays centralized.
 */
declare function broadcastSockaEventToAll(sessions: Map<WebSocket, SockaEmitCapable>, event: string, body: unknown): void;
/**
 * Validate a contract push payload and broadcast it to every session in the map.
 *
 * Works with any session type that implements {@link SockaEmitCapable} (including
 * {@link SockaDoSession} on Durable Objects). No-op when `sessions` is empty.
 */
declare function broadcastContractPushToAll<TContract extends SockaContractBound, K extends keyof TContract["pushes"] & string>(sessions: Map<WebSocket, SockaEmitCapable>, contract: TContract, name: K, body: InferSockaPushPayload<TContract, K>): Promise<void>;
/**
 * Runtime-agnostic socka server session: standard {@link WebSocket} wire
 * dispatch without Cloudflare Durable Object APIs.
 */
declare class SockaWebSocketSession<TContract extends SockaContractBound, TData = EmptySockaSessionData> implements SockaPushSession<TContract> {
    readonly websocket: WebSocket;
    protected readonly sessions: Map<WebSocket, SockaWebSocketSession<TContract, TData>>;
    private readonly config;
    private readonly wireFormat;
    private _data;
    constructor(websocket: WebSocket, sessions: Map<WebSocket, SockaWebSocketSession<TContract, TData>>, config: SockaWebSocketSessionConfigUnion<TContract, TData>, init?: SockaWebSocketInit);
    get data(): TData;
    /**
     * Session data for every connection in the same {@link sessions} map (same room),
     * optionally excluding this socket.
     */
    listPeers(options?: {
        excludeSelf?: boolean;
    }): TData[];
    /**
     * Like {@link listPeers} but maps each peer {@link SockaWebSocketSession}
     * (e.g. when you need more than {@link #data}).
     */
    listPeersWith<R>(map: (session: SockaWebSocketSession<TContract, TData>) => R, options?: {
        excludeSelf?: boolean;
    }): R[];
    /** Count of sessions in this room (same {@link sessions} map), optionally excluding self. */
    peerCount(options?: {
        excludeSelf?: boolean;
    }): number;
    /** Whether any peer sessions exist (optionally excluding self). */
    hasPeers(options?: {
        excludeSelf?: boolean;
    }): boolean;
    /**
     * Invokes the user {@link typeof SockaWebSocketSessionConfig.handleClose} callback.
     * Server adapters should call this when the WebSocket closes, **before** deleting
     * this session from the shared `sessions` map.
     */
    invokeHandleClose(): Promise<void>;
    handleRawMessage(rawMessage: string): Promise<void>;
    handleBinaryMessage(buffer: ArrayBuffer): Promise<void>;
    private dispatchAfterParsed;
    private dispatchClientRequest;
    private encodeOutgoing;
    private sendWireFrame;
    /**
     * Send a server event frame (wire). Prefer {@link emitPush} so
     * payloads are validated against the contract.
     */
    emitWireEvent(event: string, body: unknown): void;
    emitPush<K extends keyof TContract["pushes"] & string>(name: K, body: InferSockaPushPayload<TContract, K>): Promise<void>;
    broadcastPush<K extends keyof TContract["pushes"] & string>(name: K, body: InferSockaPushPayload<TContract, K>, excludeSelf?: boolean): Promise<void>;
    private reportValidationError;
}
/**
 * Invoke {@link SockaWebSocketSessionConfig.onAttached} after the session is
 * registered in the shared map.
 */
declare function runSockaSessionOnAttached<TContract extends SockaContractBound, TData>(config: SockaWebSocketSessionConfigUnion<TContract, TData>, session: SockaWebSocketSession<TContract, TData>): void;

export { SockaWebSocketSession as S, type SockaWebSocketSessionConfigUnion as a, type SockaStrictWebSocketInit as b, type SockaWebSocketInit as c, type SockaWebSocketSessionConfig as d, type SockaEmitCapable as e, type SockaPushSession as f, type SockaWebSocketSessionConfigLoose as g, broadcastContractPushToAll as h, broadcastSockaEventToAll as i, broadcastSockaEventToPeers as j, runSockaSessionOnAttached as r };
