Client for the realtime Engine providing bidirectional communication with WebSocket, polling, and WebTransport support
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pluggable transport layer supporting WebSocket, polling, and WebTransport protocols with automatic fallback mechanisms and upgrade capabilities for reliable cross-platform connectivity.
Comprehensive configuration interface for controlling transport behavior, connection parameters, and protocol options.
/**
* Configuration options for Socket instances
* Controls transport selection, connection parameters, and protocol behavior
*/
interface SocketOptions {
// Connection parameters
host?: string;
hostname?: string;
secure?: boolean;
port?: string | number;
query?: { [key: string]: any };
// Transport configuration
transports?: ("polling" | "websocket" | "webtransport" | string)[] | TransportCtor[];
upgrade?: boolean;
tryAllTransports?: boolean;
rememberUpgrade?: boolean;
// Protocol options
forceBase64?: boolean;
timestampParam?: string;
timestampRequests?: boolean;
requestTimeout?: number;
path?: string;
addTrailingSlash?: boolean;
protocols?: string | string[];
// Node.js specific options
agent?: string | boolean;
transportOptions?: Object;
// SSL/TLS options
pfx?: string;
key?: string;
passphrase?: string;
cert?: string;
ca?: string | string[];
ciphers?: string;
rejectUnauthorized?: boolean;
// HTTP options
extraHeaders?: { [header: string]: string };
withCredentials?: boolean;
// Behavior options
closeOnBeforeunload?: boolean;
useNativeTimers?: boolean;
autoUnref?: boolean;
perMessageDeflate?: { threshold: number };
}Usage Examples:
import { Socket } from "engine.io-client";
// Basic configuration
const socket = new Socket("ws://localhost:3000", {
transports: ["websocket", "polling"],
upgrade: true,
query: { userId: "123" }
});
// Advanced configuration
const socket = new Socket({
hostname: "api.example.com",
secure: true,
port: 443,
path: "/realtime/",
transports: ["polling", "websocket", "webtransport"],
tryAllTransports: true,
rememberUpgrade: true,
extraHeaders: {
"Authorization": "Bearer token123"
},
transportOptions: {
polling: {
extraHeaders: {
"X-Custom-Header": "value"
}
}
}
});
// Node.js specific configuration
const socket = new Socket("https://secure.example.com", {
key: fs.readFileSync("client.key"),
cert: fs.readFileSync("client.crt"),
ca: fs.readFileSync("ca.crt"),
rejectUnauthorized: true
});Abstract base class for all transport implementations providing common interface and event handling.
/**
* Abstract base class for all transport implementations
* Provides common interface and event handling capabilities
*/
abstract class Transport extends Emitter<
Record<never, never>,
Record<never, never>,
TransportReservedEvents
> {
// Public properties
query: Record<string, string>;
writable: boolean;
// Abstract properties
abstract get name(): string;
// Public methods
open(): Transport;
close(): Transport;
send(packets: Packet[]): void;
pause(onPause: () => void): void;
// Abstract methods (must be implemented by subclasses)
protected abstract doOpen(): void;
protected abstract doClose(): void;
protected abstract write(packets: Packet[]): void;
// Protected methods (for subclass use)
protected onError(reason: string, description: any, context?: any): Transport;
protected onOpen(): void;
protected onData(data: RawData): void;
protected onPacket(packet: Packet): void;
protected onClose(details?: CloseDetails): void;
// Protected properties (for implementation)
protected opts: SocketOptions;
protected supportsBinary: boolean;
protected readyState: TransportState;
protected socket: Socket;
protected setTimeoutFn: typeof setTimeout;
}
type TransportState = "opening" | "open" | "closed" | "pausing" | "paused";
interface TransportReservedEvents {
open: () => void;
error: (err: TransportError) => void;
packet: (packet: Packet) => void;
close: (details?: CloseDetails) => void;
poll: () => void;
pollComplete: () => void;
drain: () => void;
}Specialized error class for transport-specific errors with context information.
/**
* Transport-specific error class with context information
* Provides detailed error information for debugging transport issues
*/
class TransportError extends Error {
readonly type: "TransportError";
readonly description: any;
readonly context: any;
constructor(reason: string, description: any, context: any);
}
interface CloseDetails {
description: string;
context?: unknown;
}Usage Examples:
socket.on("error", (error) => {
if (error instanceof TransportError) {
console.error("Transport error:", error.description);
console.error("Context:", error.context);
}
});Built-in transport implementations for different environments and protocols.
/**
* Available transport constructors
* Platform-specific implementations are automatically selected
*/
const transports: {
websocket: typeof WS;
webtransport: typeof WT;
polling: typeof XHR;
};
// Individual transport classes
class XHR extends BaseXHR {
// XMLHttpRequest-based polling transport for browsers
}
class NodeXHR extends BaseXHR {
// HTTP-based polling transport for Node.js
}
class Fetch extends Polling {
// Fetch API-based polling transport
}
class WebSocket extends BaseWS {
// Browser WebSocket transport
}
class NodeWebSocket extends BaseWS {
// Node.js WebSocket transport
}
class WebTransport extends Transport {
// WebTransport-based transport
}Usage Examples:
import { Socket, transports } from "engine.io-client";
// Use all available transports
const socket = new Socket("ws://localhost:3000");
// Use specific transports only
const socket = new Socket("ws://localhost:3000", {
transports: ["websocket"]
});
// Tree-shaking with specific transport imports
import { SocketWithoutUpgrade, WebSocket } from "engine.io-client";
const socket = new SocketWithoutUpgrade({
hostname: "localhost",
port: 3000,
transports: [WebSocket]
});Detailed configuration options for each transport type and protocol behavior.
interface TransportSpecificOptions {
// Polling transport options
requestTimeout?: number;
// WebSocket options
protocols?: string | string[];
perMessageDeflate?: { threshold: number };
// General transport options
transportOptions?: {
polling?: {
extraHeaders?: { [header: string]: string };
};
websocket?: {
extraHeaders?: { [header: string]: string };
};
webtransport?: {
[key: string]: any;
};
};
}Usage Examples:
// Configure polling timeout
const socket = new Socket("http://localhost:3000", {
transports: ["polling"],
requestTimeout: 10000
});
// Configure WebSocket subprotocols
const socket = new Socket("ws://localhost:3000", {
transports: ["websocket"],
protocols: ["echo-protocol", "chat"]
});
// Configure per-message deflate
const socket = new Socket("ws://localhost:3000", {
perMessageDeflate: {
threshold: 1024
}
});
// Transport-specific headers
const socket = new Socket("http://localhost:3000", {
transportOptions: {
polling: {
extraHeaders: {
"X-Polling-Token": "abc123"
}
},
websocket: {
extraHeaders: {
"X-WebSocket-Token": "def456"
}
}
}
});Automatic transport upgrading for improved performance and reliability.
interface UpgradeOptions {
upgrade?: boolean;
tryAllTransports?: boolean;
rememberUpgrade?: boolean;
}Usage Examples:
// Enable automatic upgrading (default behavior)
const socket = new Socket("http://localhost:3000", {
upgrade: true,
transports: ["polling", "websocket"]
});
// Test all transports on connection failure
const socket = new Socket("http://localhost:3000", {
tryAllTransports: true
});
// Remember successful WebSocket upgrades
const socket = new Socket("http://localhost:3000", {
rememberUpgrade: true
});
// Listen for upgrade events
socket.on("upgrading", (transport) => {
console.log("Upgrading to:", transport.name);
});
socket.on("upgrade", (transport) => {
console.log("Upgraded to:", transport.name);
});
socket.on("upgradeError", (error) => {
console.error("Upgrade failed:", error);
});type TransportName = "polling" | "websocket" | "webtransport";
type TransportState = "opening" | "open" | "closed" | "pausing" | "paused";
type TransportCtor = { new (o: any): Transport };
interface BaseSocketOptions extends Omit<SocketOptions, "transports"> {
transports: TransportCtor[];
}
interface Packet {
type: PacketType;
data?: RawData;
}
type PacketType = "open" | "close" | "ping" | "pong" | "message" | "upgrade" | "noop";Install with Tessl CLI
npx tessl i tessl/npm-engine-io-client