import * as addon from 'warpsocket/addon-loader'; type ChannelDebug = { channel: Uint8Array; subscribers: { [socketId: number]: number; }; }; type SocketDebug = { ip: string; workerId: number; } | { targetSocketId: number; userPrefix?: Uint8Array; }; type WorkerDebug = { hasTextHandler: boolean; hasBinaryHandler: boolean; hasCloseHandler: boolean; hasOpenHandler: boolean; hasHttpHandler: boolean; }; type KVDebug = { key: Uint8Array; value: Uint8Array; }; declare module "warpsocket/addon-loader" { function start(bind: string): void; function registerWorkerThread(worker: WorkerInterface): number; function deregisterWorkerThread(workerId: number): boolean; function send(target: number | number[] | Uint8Array | ArrayBuffer | string | (number | Uint8Array | ArrayBuffer | string)[], data: Uint8Array | ArrayBuffer | string): number; function subscribe(socketIdOrChannelName: number | number[] | Uint8Array | ArrayBuffer | string | (number | Uint8Array | ArrayBuffer | string)[], channelName: Uint8Array | ArrayBuffer | string, delta?: number): number[]; function hasSubscriptions(channelName: Uint8Array | ArrayBuffer | string): boolean; function createVirtualSocket(socketId: number, userPrefix?: Uint8Array | ArrayBuffer | string): number; function deleteVirtualSocket(virtualSocketId: number, expectedTargetSocketId?: number): boolean; function getKey(key: Uint8Array | ArrayBuffer | string): Uint8Array | undefined; function setKey(key: Uint8Array | ArrayBuffer | string, value?: Uint8Array | ArrayBuffer | string | undefined): Uint8Array | undefined; function setKeyIf(key: Uint8Array | ArrayBuffer | string, newValue?: Uint8Array | ArrayBuffer | string | undefined, checkValue?: Uint8Array | ArrayBuffer | string | undefined): boolean; function getDebugState(mode: "channels"): ChannelDebug[]; function getDebugState(mode: "channels", channelName: Uint8Array | ArrayBuffer | string): ChannelDebug | undefined; function getDebugState(mode: "channels", filterSocketId: number): ChannelDebug[]; function getDebugState(mode: "sockets"): Record; function getDebugState(mode: "sockets", socketId: number): SocketDebug | undefined; function getDebugState(mode: "workers"): Record; function getDebugState(mode: "workers", workerId: number): WorkerDebug | undefined; function getDebugState(mode: "kv"): KVDebug[]; } /** * Incoming HTTP request passed to `handleHttpRequest`. * * Extends Node.js `stream.Readable` — `req.pipe()`, `req.on('data')`, and `req.on('end')` all * work as expected. The body is pre-read by WarpSocket and pushed synchronously as a single * chunk, so the stream is immediately readable without waiting for async I/O. * * The API is a useful subset of Node's `http.IncomingMessage`. There are no `'data'` / `'end'` * events beyond what the Readable provides, no access to the underlying socket, and no HTTP/2. * WebSocket upgrade requests are detected automatically and routed through the normal * `handleOpen` flow — they never reach `handleHttpRequest`. */ export interface HttpRequest extends NodeJS.ReadableStream { method: string; url: string; httpVersion: string; httpVersionMajor: number; httpVersionMinor: number; headers: Record; /** Raw headers as a flat alternating `[name, value, name, value, ...]` array, * preserving the original wire order. Header names are lowercased (as normalised * by the HTTP/1.1 parser). */ rawHeaders: string[]; remoteAddress: string; /** Always `true` — the body is fully pre-buffered before the handler is called. */ complete: boolean; /** Pre-read full request body. Also available via the Readable stream interface. */ body: Buffer; } /** * Outgoing HTTP response passed to `handleHttpRequest`. * * Instances are proper Node.js `stream.Writable` objects — `someReadable.pipe(res)` works. * Chunks from `write()` / `end()` and piped data are buffered; the complete response is sent * once the handler's Promise resolves. Real-time streaming to the client is not supported; * for push-based patterns use WebSockets instead. * * `setHeader()`, `getHeader()`, `removeHeader()`, `writeHead(status, [reason,] [headers])`, * `statusCode = N`, `write(chunk)` and `end([chunk])` all work as expected. * Array values for `setHeader()` produce multiple header lines (e.g. for `Set-Cookie`). * There are no trailers and no upgrade hook for non-WebSocket upgrades. */ export interface HttpResponse extends NodeJS.EventEmitter { statusCode: number; setHeader(name: string, value: string | string[]): void; getHeader(name: string): string | string[] | undefined; getHeaders(): Record; hasHeader(name: string): boolean; removeHeader(name: string): void; writeHead(statusCode: number, headers?: Record): this; writeHead(statusCode: number, reasonPhrase: string, headers?: Record): this; write(chunk: string | Buffer | Uint8Array, encoding?: string, cb?: () => void): boolean; end(chunk?: string | Buffer | Uint8Array, encoding?: string, cb?: () => void): this; /** True once `end()` has been called. */ readonly writableEnded: boolean; /** True once the 'finish' event has fired. */ readonly writableFinished: boolean; } /** * Interface that worker threads must implement to handle WebSocket events. * All handler methods are optional - if not provided, the respective functionality will be unavailable. */ export interface WorkerInterface { /** * Called when the worker is starting up, before registering with the native addon. * This allows for initialization logic that needs to run before handling WebSocket events. * @param workerArg - Optional argument passed from the start() function's workerArg option. */ handleStart?(workerArg?: any): Promise | void; /** * Handles new WebSocket connections and can reject them. If not provided, all connections are accepted. * @param socketId - The unique identifier of the WebSocket connection. * @param ip - The client's IP address. * @param headers - HTTP headers from the WebSocket handshake request. * @returns true to accept the connection, false to reject it. */ handleOpen?(socketId: number, ip: string, headers: Record): Promise | boolean; /** * Handles incoming WebSocket text messages from clients. * @param data - The message data as a string. * @param socketId - The unique identifier of the WebSocket connection. */ handleTextMessage?(data: string, socketId: number): Promise | void; /** * Handles incoming WebSocket binary messages from clients. * @param data - The message data as a Uint8Array. * @param socketId - The unique identifier of the WebSocket connection. */ handleBinaryMessage?(data: Uint8Array, socketId: number): Promise | void; /** * Handles WebSocket connection closures. * @param socketId - The unique identifier of the closed WebSocket connection. */ handleClose?(socketId: number): Promise | void; /** * Handles plain HTTP/1.1 requests arriving on the same port as the WebSocket server. * Handy for health checks, landing pages, or webhook endpoints without a second server. * HTTP requests are load-balanced across worker threads using round-robin (no per-connection * pinning), since each HTTP request is independent. * * `req` exposes `method`, `url`, `headers`, `rawHeaders`, `httpVersion`, `remoteAddress`, * and `body` (a pre-read `Buffer`). It also implements Node.js `stream.Readable` — * `req.pipe()`, `req.on('data')`, etc. work synchronously (body is pushed before your * handler is called, so no async I/O is needed before reading). * * `res` implements Node.js `stream.Writable`. Written chunks are buffered; the complete * response is sent once the handler's Promise resolves. `statusCode`, `setHeader()`, * `getHeader()`, `removeHeader()`, `writeHead()`, `write()`, and `end()` all work as * expected. Array values for `setHeader()` produce multiple header lines (e.g. `Set-Cookie`). * Real-time streaming is not supported — use WebSockets for that. * * For small JSON/HTML responses or proxying webhook bodies to `send()`, these APIs are * drop-in compatible with code written against `http.createServer`. * * There is no HTTP/2, no trailers, and no upgrade hook for non-WebSocket upgrades. * WebSocket upgrade requests are detected automatically and routed through `handleOpen`. * * @param req - The incoming request. * @param res - The response object. */ handleHttpRequest?(req: HttpRequest, res: HttpResponse): Promise | void; } /** * Starts a WebSocket server bound to the given address and spawns worker threads * that handle WebSocket events. * * @param options - Configuration object: * * bind: Required. Address string to bind the server to (e.g. "127.0.0.1:8080"), * or an array of such strings to bind multiple addresses. * * workerPath: Required. Path (absolute or relative to process.cwd()) to the * worker JavaScript module. This module will be imported in each * worker thread and its exported handlers will be registered with * the native addon. Worker modules may export any subset of the * `WorkerInterface` handlers. * * threads: Optional. Number of worker threads to spawn. When a positive * integer is provided, that number of Node.js `Worker` threads * are created and set up to handle WebSocket events. When omitted, * defaults to the number of CPU cores or 4, whichever is higher. * * workerArg: Optional. Argument to pass to the handleStart() method of * worker modules, if they implement it. This allows passing * initialization data or configuration to workers. * * @returns A Promise that resolves after worker threads (if any) have been * started and the native addon has been instructed to bind to the * address. The Promise rejects if worker initialization fails. * * @throws If `options` is or the `bind` and `workerPath` properties are * missing or invalid, or if already started. */ export declare function start(options: { bind: string | string[]; workerPath?: string; threads?: number; workerArg?: any; }): Promise; /** * Sends data to a specific WebSocket connection, multiple connections, or broadcasts to all subscribers of a channel. * @param target - The target for the message: * - A socket ID (number): sends to that specific socket * - A channel name (Buffer, ArrayBuffer, or string): broadcasts to all subscribers of that channel * - An array of socket IDs and/or channel names: sends to each socket and broadcasts to each channel * @param data - The data to send (Buffer, ArrayBuffer, or string). * @returns the number of recipients that got sent the message. * * When target is a virtual socket with user prefix (or a channel that has such a subscriber), that prefix is prepended to the message. In case of a text message, the prefix bytes are assumed to be valid UTF-8. * * When target is an array, the message is sent to each target in the array. */ export declare const send: typeof addon.send; /** * Subscribes one or more WebSocket connections to a channel, or copies subscriptions from one channel to another. * Multiple subscriptions to the same channel by the same connection are reference-counted. * * @param socketIdOrChannelName - Can be: * - A single socket ID (number): applies delta to that socket's subscription * - An array of socket IDs (number[]): applies delta to all sockets' subscriptions * - A channel name (Buffer/ArrayBuffer/string): applies delta to all subscribers of this source channel * - An array mixing socket IDs and channel names: applies delta to sockets and source channel subscribers * @param channelName - The target channel name (Buffer, ArrayBuffer, or string). * @param delta - Optional. The amount to change the subscription count by (default: 1). * Positive values add subscriptions, negative values remove them. When the count reaches zero, the subscription is removed. * @returns An array of socket IDs that were affected by the operation: * - For positive delta: socket IDs that became newly subscribed (reference count went from 0 to positive) * - For negative delta: socket IDs that became completely unsubscribed (reference count reached 0) */ export declare const subscribe: typeof addon.subscribe; /** * Exactly the same as `subscribe`, only with a negative delta (defaulting to 1, which means a single unsubscribe, or a subscribe with delta -1). */ export declare function unsubscribe(socketIdOrChannelName: number | number[] | Uint8Array | ArrayBuffer | string | (number | Uint8Array | ArrayBuffer | string)[], channelName: Uint8Array | ArrayBuffer | string, delta?: number): number[]; /** * **DEPRECATED:** Use subscribe(fromChannelName, toChannelName) instead. * * Copies all subscribers from one channel to another channel. Uses reference counting - if a subscriber * is already subscribed to the destination channel, their reference count will be incremented instead * of creating duplicate subscriptions. * @param fromChannelName - The source channel name (Buffer, ArrayBuffer, or string). * @param toChannelName - The destination channel name (Buffer, ArrayBuffer, or string). * @returns An array of socket IDs that were newly added to the destination channel. Sockets that were * already subscribed (and had their reference count incremented) are not included. */ export declare function copySubscriptions(fromChannelName: Uint8Array | ArrayBuffer | string, toChannelName: Uint8Array | ArrayBuffer | string): number[]; /** * Checks if a channel has any subscribers. * @param channelName - The name of the channel to check (Buffer, ArrayBuffer, or string). * @returns True if the channel has subscribers, false otherwise. */ export declare const hasSubscriptions: typeof addon.hasSubscriptions; /** * Creates a virtual socket that points to an actual WebSocket connection. * Virtual sockets can be subscribed to channels, and messages will be relayed to the underlying actual socket. * This allows for convenient bulk unsubscription by deleting the virtual socket. * Virtual sockets can also point to other virtual sockets, creating a chain that resolves to an actual socket. * @param socketId - The identifier of the actual WebSocket connection or another virtual socket to point to. * @param userPrefix - Optional user prefix (up to 15 bytes) that will be prepended to all messages sent to this virtual socket (possibly through a channel). For text messages, this prefix is assumed to be valid UTF-8. * @returns The unique identifier of the newly created virtual socket, which can be used just like another socket. */ export declare const createVirtualSocket: typeof addon.createVirtualSocket; /** * Deletes a virtual socket and unsubscribes it from all channels. * This is a convenient way to bulk-unsubscribe a virtual socket from all its channels at once. * @param virtualSocketId - The unique identifier of the virtual socket to delete. * @param expectedTargetSocketId - Optional. If provided, the virtual socket will only be deleted * if it points to this specific target socket ID. This can help prevent unauthorized unsubscribes. * @returns true if the virtual socket was deleted, false if it was not found or target didn't match. */ export declare const deleteVirtualSocket: typeof addon.deleteVirtualSocket; /** * Reads the raw bytes stored for a key in the shared in-memory store. * @param key - Key to read (Buffer, ArrayBuffer, or string). * @returns A Uint8Array when the key exists, or undefined otherwise. */ export declare const getKey: typeof addon.getKey; /** * Stores or deletes a value in the shared key/value store. * @param key - Key to upsert (Buffer, ArrayBuffer, or string). * @param value - Optional value to store. Pass `undefined` to delete the key instead. * @returns The previous value as a Uint8Array when the key existed, or undefined if it did not. */ export declare const setKey: typeof addon.setKey; /** * Atomically updates a key only when its current value matches the expected check value. * @param key - Key to update (Buffer, ArrayBuffer, or string). * @param newValue - Optional replacement value. Pass `undefined` to delete the key on success. * @param checkValue - Optional expected value. Pass `undefined` to require that the key is absent. * @returns true when the compare-and-set succeeds, false otherwise. */ export declare const setKeyIf: typeof addon.setKeyIf; /** * Retrieves debug state information about the internal WarpSocket data structures. * @param mode - The type of data to retrieve: "channels" for channel subscriptions, "sockets" for socket details, "workers" for worker thread info, "kv" for key-value store entries. * @param singleKey - Optional. When provided, returns only the data for a specific item: for "channels", a channel name (bytes) or socket ID (number); for "sockets" and "workers", a socket ID or worker ID (number); for "kv", a key (bytes). * @returns For "channels" and "kv", an array of objects with detailed state information, capped at 2000 entries. For "sockets" and "workers", an object keyed by socketId/workerId with values being the debug info objects. When singleKey is provided, a single object or undefined is returned instead of an array/object (except when mode is "channels" and singleKey is a number). */ export declare const getDebugState: typeof addon.getDebugState; export {};