Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@agentick/client

Package Overview
Dependencies
Maintainers
2
Versions
97
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@agentick/client - npm Package Compare versions

Comparing version
0.0.1
to
0.1.9
+7
-2
package.json
{
"name": "@agentick/client",
"version": "0.0.1",
"version": "0.1.9",
"description": "Client SDK for Agentick - multiplexed sessions over SSE",

@@ -30,3 +30,3 @@ "keywords": [

"dependencies": {
"@agentick/shared": "0.0.1"
"@agentick/shared": "0.1.9"
},

@@ -36,2 +36,7 @@ "devDependencies": {

},
"repository": {
"type": "git",
"url": "git+https://github.com/agenticklabs/agentick.git",
"directory": "packages/client"
},
"scripts": {

@@ -38,0 +43,0 @@ "build": "tsc -p tsconfig.build.json",

/**
* HTTP/SSE Transport - Default transport implementation
*
* - Server → Client: Server-Sent Events (SSE)
* - Client → Server: HTTP POST
*
* @module @tentickle/client/transports/http
*/
import type { Transport, ClientConfig, ConnectionState, ConnectionMetadata, ChannelEvent } from "../types.js";
/**
* Custom fetch function signature.
* Allows replacing the default fetch with axios, ky, or a custom wrapper.
*/
export type FetchFn = typeof fetch;
/**
* EventSource constructor signature.
* Allows replacing the default EventSource (e.g., for polyfills or custom implementations).
*/
export interface EventSourceConstructor {
new (url: string | URL, init?: {
withCredentials?: boolean;
}): EventSource;
}
/**
* HTTP transport configuration.
*/
export interface HTTPTransportConfig extends ClientConfig {
/**
* Custom headers to include in all requests.
* These are merged with defaults (Content-Type: application/json).
* User-provided headers take precedence over defaults.
*
* Use this for custom auth schemes, API keys, or any other headers.
*
* @example
* ```typescript
* // Basic auth
* const transport = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* headers: { Authorization: 'Basic ' + btoa('user:pass') },
* });
*
* // API key
* const transport = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* headers: { 'X-API-Key': 'my-api-key' },
* });
* ```
*/
headers?: Record<string, string>;
/**
* Send cookies with requests and SSE (EventSource withCredentials).
* Defaults to false.
*/
withCredentials?: boolean;
/**
* Include auth token in SSE query params (EventSource lacks headers).
* Defaults to false to avoid token leakage in logs.
*/
authTokenInQuery?: boolean;
/**
* Custom fetch implementation.
* Use this to inject axios, ky, or a fetch wrapper with custom credentials/interceptors.
*
* @example
* ```typescript
* import ky from 'ky';
*
* const transport = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* fetch: ky as unknown as FetchFn,
* });
* ```
*/
fetch?: FetchFn;
/**
* Custom EventSource constructor.
* Use this for polyfills (e.g., eventsource package in Node.js) or custom implementations.
*
* @example
* ```typescript
* import EventSource from 'eventsource';
*
* const transport = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* EventSource: EventSource,
* });
* ```
*/
EventSource?: EventSourceConstructor;
}
/**
* HTTP/SSE Transport implementation.
*
* This is the default transport for Tentickle clients.
* Uses SSE for server-to-client streaming and HTTP POST for client-to-server messages.
*
* Supports custom fetch and EventSource implementations for:
* - Server-side (Node.js) usage with polyfills
* - Custom HTTP clients (axios, ky, got)
* - Credentials/interceptors
* - Testing with mocks
*/
export declare class HTTPTransport implements Transport {
readonly name = "http";
private _state;
private sessionId?;
private metadata?;
private eventSource?;
private reconnectAttempts;
private reconnectTimer?;
private receiveHandlers;
private stateHandlers;
private readonly baseUrl;
private readonly eventsPath;
private readonly timeout;
private readonly reconnectDelay;
private readonly maxReconnectAttempts;
private readonly withCredentials;
private readonly authTokenInQuery;
/** Token for SSE query param auth (EventSource doesn't support headers) */
private readonly token?;
/** Custom headers to merge with defaults for fetch requests */
private readonly customHeaders;
/** Custom fetch implementation (defaults to global fetch) */
private readonly fetchFn;
/** Custom EventSource constructor (defaults to global EventSource) */
private readonly EventSourceCtor;
constructor(config: HTTPTransportConfig);
get state(): ConnectionState;
private setState;
/**
* Connect to the SSE stream.
*/
connect(sessionId: string, metadata?: ConnectionMetadata): Promise<void>;
private connectSSE;
private handleReconnect;
private closeEventSource;
/**
* Disconnect from the server.
*/
disconnect(): Promise<void>;
/**
* Send event via HTTP POST.
*/
send(event: ChannelEvent): Promise<void>;
/**
* Register receive handler.
*/
onReceive(handler: (event: ChannelEvent) => void): () => void;
/**
* Register state change handler.
*/
onStateChange(handler: (state: ConnectionState) => void): () => void;
private notifyReceive;
}
/**
* Create HTTP/SSE transport.
*
* @example
* ```typescript
* // Default usage
* const transport = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* });
*
* // With custom headers (API key, Basic auth, etc.)
* const transportWithApiKey = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* headers: { 'X-API-Key': 'my-api-key' },
* });
*
* const transportWithBasicAuth = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* headers: { Authorization: 'Basic ' + btoa('user:pass') },
* });
*
* // With Bearer token (convenience - same as headers: { Authorization: 'Bearer ...' })
* const transportWithToken = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* token: 'my-jwt-token',
* });
*
* // With custom fetch (e.g., for credentials)
* const transportWithCredentials = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* fetch: (url, init) => fetch(url, { ...init, credentials: 'include' }),
* });
*
* // With cookie-based auth for SSE + POST
* const transportWithCookies = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* withCredentials: true,
* });
*
* // If you must pass auth token to SSE via query params
* const transportWithQueryToken = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* token: 'my-jwt-token',
* authTokenInQuery: true,
* });
*
* // Node.js with polyfills
* import EventSource from 'eventsource';
*
* const nodeTransport = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* EventSource,
* });
* ```
*/
export declare function createHTTPTransport(config: HTTPTransportConfig): Transport;
//# sourceMappingURL=http.d.ts.map
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"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"}
/**
* HTTP/SSE Transport - Default transport implementation
*
* - Server → Client: Server-Sent Events (SSE)
* - Client → Server: HTTP POST
*
* @module @tentickle/client/transports/http
*/
/**
* HTTP/SSE Transport implementation.
*
* This is the default transport for Tentickle clients.
* Uses SSE for server-to-client streaming and HTTP POST for client-to-server messages.
*
* Supports custom fetch and EventSource implementations for:
* - Server-side (Node.js) usage with polyfills
* - Custom HTTP clients (axios, ky, got)
* - Credentials/interceptors
* - Testing with mocks
*/
export class HTTPTransport {
name = "http";
_state = "disconnected";
sessionId;
metadata;
eventSource;
reconnectAttempts = 0;
reconnectTimer;
receiveHandlers = new Set();
stateHandlers = new Set();
baseUrl;
eventsPath;
timeout;
reconnectDelay;
maxReconnectAttempts;
withCredentials;
authTokenInQuery;
/** Token for SSE query param auth (EventSource doesn't support headers) */
token;
/** Custom headers to merge with defaults for fetch requests */
customHeaders;
/** Custom fetch implementation (defaults to global fetch) */
fetchFn;
/** Custom EventSource constructor (defaults to global EventSource) */
EventSourceCtor;
constructor(config) {
this.baseUrl = config.baseUrl.replace(/\/$/, ""); // Remove trailing slash
this.eventsPath = config.paths?.events ?? "/events";
this.timeout = config.timeout ?? 30000;
this.reconnectDelay = config.reconnectDelay ?? 1000;
this.maxReconnectAttempts = config.maxReconnectAttempts ?? 10;
this.withCredentials = config.withCredentials ?? false;
this.authTokenInQuery = config.authTokenInQuery ?? false;
// Token is used for SSE query param (EventSource doesn't support custom headers)
this.token = config.token;
// Build custom headers for fetch requests - token adds Bearer auth if no custom Authorization
this.customHeaders = { ...config.headers };
if (config.token && !this.customHeaders["Authorization"]) {
this.customHeaders["Authorization"] = `Bearer ${config.token}`;
}
// Use custom implementations or fall back to globals
this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
this.EventSourceCtor = config.EventSource ?? globalThis.EventSource;
}
get state() {
return this._state;
}
setState(state) {
if (this._state === state)
return;
this._state = state;
for (const handler of this.stateHandlers) {
try {
handler(state);
}
catch (error) {
console.error("Error in state handler:", error);
}
}
}
/**
* Connect to the SSE stream.
*/
async connect(sessionId, metadata) {
if (this._state === "connected") {
throw new Error("Already connected");
}
this.sessionId = sessionId;
this.metadata = metadata;
this.reconnectAttempts = 0;
this.setState("connecting");
try {
await this.connectSSE();
this.setState("connected");
}
catch (error) {
this.setState("error");
throw error;
}
}
async connectSSE() {
if (!this.sessionId) {
throw new Error("Session ID required");
}
// Close existing connection
this.closeEventSource();
// Build SSE URL with query params
const url = new URL(`${this.baseUrl}${this.eventsPath}`);
url.searchParams.set("sessionId", this.sessionId);
if (this.metadata?.userId) {
url.searchParams.set("userId", String(this.metadata.userId));
}
if (this.token && this.authTokenInQuery) {
url.searchParams.set("token", this.token);
}
return new Promise((resolve, reject) => {
try {
this.eventSource = new this.EventSourceCtor(url.toString(), {
withCredentials: this.withCredentials,
});
const onOpen = () => {
this.reconnectAttempts = 0;
resolve();
};
const onMessage = (event) => {
try {
const channelEvent = JSON.parse(event.data);
this.notifyReceive(channelEvent);
}
catch (error) {
console.error("Failed to parse SSE event:", error);
}
};
const onError = () => {
if (this._state === "connecting") {
this.closeEventSource();
reject(new Error("SSE connection failed"));
}
else {
this.handleReconnect();
}
};
this.eventSource.addEventListener("open", onOpen);
this.eventSource.addEventListener("message", onMessage);
this.eventSource.addEventListener("error", onError);
}
catch (error) {
reject(error);
}
});
}
handleReconnect() {
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
console.error("Max reconnection attempts reached");
this.setState("error");
return;
}
this.reconnectAttempts++;
const delay = this.reconnectDelay * Math.min(this.reconnectAttempts, 5); // Cap backoff
this.reconnectTimer = setTimeout(() => {
if (this.sessionId && this._state !== "disconnected") {
this.connectSSE()
.then(() => this.setState("connected"))
.catch((error) => {
console.error("Reconnection failed:", error);
});
}
}, delay);
}
closeEventSource() {
if (this.eventSource) {
this.eventSource.close();
this.eventSource = undefined;
}
}
/**
* Disconnect from the server.
*/
async disconnect() {
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
this.reconnectTimer = undefined;
}
this.closeEventSource();
this.sessionId = undefined;
this.metadata = undefined;
this.reconnectAttempts = 0;
this.setState("disconnected");
}
/**
* Send event via HTTP POST.
*/
async send(event) {
if (!this.sessionId) {
throw new Error("Not connected");
}
// Merge default headers with custom headers (custom takes precedence)
const headers = {
"Content-Type": "application/json",
...this.customHeaders,
};
const response = await this.fetchFn(`${this.baseUrl}${this.eventsPath}`, {
method: "POST",
headers,
credentials: this.withCredentials ? "include" : "same-origin",
body: JSON.stringify({
...event,
metadata: {
...event.metadata,
sessionId: this.sessionId,
userId: this.metadata?.userId,
timestamp: Date.now(),
},
}),
signal: AbortSignal.timeout(this.timeout),
});
if (!response.ok) {
const text = await response.text();
throw new Error(`Failed to send event: ${response.status} ${text}`);
}
}
/**
* Register receive handler.
*/
onReceive(handler) {
this.receiveHandlers.add(handler);
return () => {
this.receiveHandlers.delete(handler);
};
}
/**
* Register state change handler.
*/
onStateChange(handler) {
this.stateHandlers.add(handler);
return () => {
this.stateHandlers.delete(handler);
};
}
notifyReceive(event) {
for (const handler of this.receiveHandlers) {
try {
handler(event);
}
catch (error) {
console.error("Error in receive handler:", error);
}
}
}
}
/**
* Create HTTP/SSE transport.
*
* @example
* ```typescript
* // Default usage
* const transport = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* });
*
* // With custom headers (API key, Basic auth, etc.)
* const transportWithApiKey = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* headers: { 'X-API-Key': 'my-api-key' },
* });
*
* const transportWithBasicAuth = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* headers: { Authorization: 'Basic ' + btoa('user:pass') },
* });
*
* // With Bearer token (convenience - same as headers: { Authorization: 'Bearer ...' })
* const transportWithToken = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* token: 'my-jwt-token',
* });
*
* // With custom fetch (e.g., for credentials)
* const transportWithCredentials = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* fetch: (url, init) => fetch(url, { ...init, credentials: 'include' }),
* });
*
* // With cookie-based auth for SSE + POST
* const transportWithCookies = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* withCredentials: true,
* });
*
* // If you must pass auth token to SSE via query params
* const transportWithQueryToken = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* token: 'my-jwt-token',
* authTokenInQuery: true,
* });
*
* // Node.js with polyfills
* import EventSource from 'eventsource';
*
* const nodeTransport = createHTTPTransport({
* baseUrl: 'https://api.example.com',
* EventSource,
* });
* ```
*/
export function createHTTPTransport(config) {
return new HTTPTransport(config);
}
//# sourceMappingURL=http.js.map
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/transports/http.ts"],"names":[],"mappings":"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"}
/**
* Transport implementations for @tentickle/client
*
* Default: HTTP/SSE transport
* Alternative: WebSocket transport
*
* Both transports support custom implementations for:
* - Server-side (Node.js) usage with polyfills
* - Custom HTTP clients (axios, ky, got)
* - Testing with mocks
*
* @module @tentickle/client/transports
*/
export { HTTPTransport, createHTTPTransport, type HTTPTransportConfig, type FetchFn, type EventSourceConstructor, } from "./http.js";
export { WebSocketTransport, createWebSocketTransport, type WebSocketConfig, type WebSocketConstructor, } from "./websocket.js";
//# sourceMappingURL=index.d.ts.map
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transports/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,OAAO,EACZ,KAAK,sBAAsB,GAC5B,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,KAAK,eAAe,EACpB,KAAK,oBAAoB,GAC1B,MAAM,gBAAgB,CAAC"}
/**
* Transport implementations for @tentickle/client
*
* Default: HTTP/SSE transport
* Alternative: WebSocket transport
*
* Both transports support custom implementations for:
* - Server-side (Node.js) usage with polyfills
* - Custom HTTP clients (axios, ky, got)
* - Testing with mocks
*
* @module @tentickle/client/transports
*/
// Default HTTP/SSE transport
export { HTTPTransport, createHTTPTransport, } from "./http.js";
// Alternative WebSocket transport
export { WebSocketTransport, createWebSocketTransport, } from "./websocket.js";
//# sourceMappingURL=index.js.map
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transports/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,6BAA6B;AAC7B,OAAO,EACL,aAAa,EACb,mBAAmB,GAIpB,MAAM,WAAW,CAAC;AAEnB,kCAAkC;AAClC,OAAO,EACL,kBAAkB,EAClB,wBAAwB,GAGzB,MAAM,gBAAgB,CAAC"}
/**
* WebSocket Transport - Alternative transport implementation
*
* Bidirectional communication over WebSocket.
* Use when you need lower latency or when SSE is not available.
*
* @module @tentickle/client/transports/websocket
*/
import type { Transport, ClientConfig, ConnectionState, ConnectionMetadata, ChannelEvent } from "../types.js";
/**
* WebSocket constructor signature.
* Allows replacing the default WebSocket (e.g., with 'ws' package in Node.js).
*/
export interface WebSocketConstructor {
new (url: string | URL, protocols?: string | string[]): WebSocket;
}
/**
* WebSocket transport configuration.
*/
export interface WebSocketConfig extends ClientConfig {
/** WebSocket URL (ws:// or wss://) - overrides baseUrl */
wsUrl?: string;
/** WebSocket protocols */
protocols?: string[];
/**
* Custom WebSocket constructor.
* Use this for Node.js (ws package) or custom implementations.
*
* @example
* ```typescript
* import WebSocket from 'ws';
*
* const transport = createWebSocketTransport({
* baseUrl: 'wss://api.example.com',
* WebSocket: WebSocket as unknown as WebSocketConstructor,
* });
* ```
*/
WebSocket?: WebSocketConstructor;
}
/**
* WebSocket Transport implementation.
*
* Use this when:
* - You need bidirectional real-time communication
* - SSE is blocked or unavailable
* - You want lower latency
*/
export declare class WebSocketTransport implements Transport {
readonly name = "websocket";
private _state;
private sessionId?;
private metadata?;
private ws?;
private reconnectAttempts;
private reconnectTimer?;
private receiveHandlers;
private stateHandlers;
private readonly wsUrl;
private readonly protocols?;
private readonly token?;
private readonly reconnectDelay;
private readonly maxReconnectAttempts;
/** Custom WebSocket constructor (defaults to global WebSocket) */
private readonly WebSocketCtor;
constructor(config: WebSocketConfig);
get state(): ConnectionState;
private setState;
/**
* Connect to WebSocket server.
*/
connect(sessionId: string, metadata?: ConnectionMetadata): Promise<void>;
private connectWebSocket;
private handleReconnect;
private closeWebSocket;
/**
* Disconnect from server.
*/
disconnect(): Promise<void>;
/**
* Send event via WebSocket.
*/
send(event: ChannelEvent): Promise<void>;
/**
* Register receive handler.
*/
onReceive(handler: (event: ChannelEvent) => void): () => void;
/**
* Register state change handler.
*/
onStateChange(handler: (state: ConnectionState) => void): () => void;
private notifyReceive;
}
/**
* Create WebSocket transport.
*
* @example
* ```typescript
* // Browser usage
* const transport = createWebSocketTransport({
* baseUrl: 'wss://api.example.com',
* });
*
* // Node.js with ws package
* import WebSocket from 'ws';
*
* const nodeTransport = createWebSocketTransport({
* baseUrl: 'wss://api.example.com',
* WebSocket: WebSocket as unknown as WebSocketConstructor,
* });
* ```
*/
export declare function createWebSocketTransport(config: WebSocketConfig): Transport;
//# sourceMappingURL=websocket.d.ts.map
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/transports/websocket.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,YAAY,EACb,MAAM,aAAa,CAAC;AAMrB;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,KAAK,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;CACnE;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,oBAAoB,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,qBAAa,kBAAmB,YAAW,SAAS;IAClD,QAAQ,CAAC,IAAI,eAAe;IAE5B,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAqB;IACtC,OAAO,CAAC,EAAE,CAAC,CAAY;IACvB,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,cAAc,CAAC,CAAgC;IACvD,OAAO,CAAC,eAAe,CAA4C;IACnE,OAAO,CAAC,aAAa,CAA+C;IAEpE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAW;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAE9C,kEAAkE;IAClE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuB;gBAEzC,MAAM,EAAE,eAAe;IAiBnC,IAAI,KAAK,IAAI,eAAe,CAE3B;IAED,OAAO,CAAC,QAAQ;IAYhB;;OAEG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;YAmBhE,gBAAgB;IAuD9B,OAAO,CAAC,eAAe;IAqBvB,OAAO,CAAC,cAAc;IAOtB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC;;OAEG;IACG,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB9C;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI;IAO7D;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI;IAOpE,OAAO,CAAC,aAAa;CAStB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAE3E"}
/**
* WebSocket Transport - Alternative transport implementation
*
* Bidirectional communication over WebSocket.
* Use when you need lower latency or when SSE is not available.
*
* @module @tentickle/client/transports/websocket
*/
/**
* WebSocket Transport implementation.
*
* Use this when:
* - You need bidirectional real-time communication
* - SSE is blocked or unavailable
* - You want lower latency
*/
export class WebSocketTransport {
name = "websocket";
_state = "disconnected";
sessionId;
metadata;
ws;
reconnectAttempts = 0;
reconnectTimer;
receiveHandlers = new Set();
stateHandlers = new Set();
wsUrl;
protocols;
token;
reconnectDelay;
maxReconnectAttempts;
/** Custom WebSocket constructor (defaults to global WebSocket) */
WebSocketCtor;
constructor(config) {
// Convert HTTP URL to WebSocket URL if needed
const baseUrl = config.wsUrl ?? config.baseUrl;
this.wsUrl = baseUrl
.replace(/^http:/, "ws:")
.replace(/^https:/, "wss:")
.replace(/\/$/, "");
this.protocols = config.protocols;
this.token = config.token;
this.reconnectDelay = config.reconnectDelay ?? 1000;
this.maxReconnectAttempts = config.maxReconnectAttempts ?? 10;
// Use custom implementation or fall back to global
this.WebSocketCtor = config.WebSocket ?? globalThis.WebSocket;
}
get state() {
return this._state;
}
setState(state) {
if (this._state === state)
return;
this._state = state;
for (const handler of this.stateHandlers) {
try {
handler(state);
}
catch (error) {
console.error("Error in state handler:", error);
}
}
}
/**
* Connect to WebSocket server.
*/
async connect(sessionId, metadata) {
if (this._state === "connected") {
throw new Error("Already connected");
}
this.sessionId = sessionId;
this.metadata = metadata;
this.reconnectAttempts = 0;
this.setState("connecting");
try {
await this.connectWebSocket();
this.setState("connected");
}
catch (error) {
this.setState("error");
throw error;
}
}
async connectWebSocket() {
if (!this.sessionId) {
throw new Error("Session ID required");
}
// Close existing connection
this.closeWebSocket();
// Build WebSocket URL with query params
const url = new URL(this.wsUrl);
url.searchParams.set("sessionId", this.sessionId);
if (this.metadata?.userId) {
url.searchParams.set("userId", String(this.metadata.userId));
}
if (this.token) {
url.searchParams.set("token", this.token);
}
return new Promise((resolve, reject) => {
try {
this.ws = new this.WebSocketCtor(url.toString(), this.protocols);
this.ws.onopen = () => {
this.reconnectAttempts = 0;
resolve();
};
this.ws.onmessage = (event) => {
try {
const channelEvent = JSON.parse(event.data);
this.notifyReceive(channelEvent);
}
catch (error) {
console.error("Failed to parse WebSocket message:", error);
}
};
this.ws.onerror = () => {
if (this._state === "connecting") {
reject(new Error("WebSocket connection failed"));
}
};
this.ws.onclose = () => {
if (this._state === "disconnected") {
// Intentional disconnect
return;
}
this.handleReconnect();
};
}
catch (error) {
reject(error);
}
});
}
handleReconnect() {
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
console.error("Max reconnection attempts reached");
this.setState("error");
return;
}
this.reconnectAttempts++;
const delay = this.reconnectDelay * Math.min(this.reconnectAttempts, 5);
this.reconnectTimer = setTimeout(() => {
if (this.sessionId && this._state !== "disconnected") {
this.connectWebSocket()
.then(() => this.setState("connected"))
.catch((error) => {
console.error("Reconnection failed:", error);
});
}
}, delay);
}
closeWebSocket() {
if (this.ws) {
this.ws.close();
this.ws = undefined;
}
}
/**
* Disconnect from server.
*/
async disconnect() {
if (this.reconnectTimer) {
clearTimeout(this.reconnectTimer);
this.reconnectTimer = undefined;
}
this.setState("disconnected"); // Set before close to prevent reconnect
this.closeWebSocket();
this.sessionId = undefined;
this.metadata = undefined;
this.reconnectAttempts = 0;
}
/**
* Send event via WebSocket.
*/
async send(event) {
if (!this.ws || this._state !== "connected") {
throw new Error("Not connected");
}
this.ws.send(JSON.stringify({
...event,
metadata: {
...event.metadata,
sessionId: this.sessionId,
userId: this.metadata?.userId,
timestamp: Date.now(),
},
}));
}
/**
* Register receive handler.
*/
onReceive(handler) {
this.receiveHandlers.add(handler);
return () => {
this.receiveHandlers.delete(handler);
};
}
/**
* Register state change handler.
*/
onStateChange(handler) {
this.stateHandlers.add(handler);
return () => {
this.stateHandlers.delete(handler);
};
}
notifyReceive(event) {
for (const handler of this.receiveHandlers) {
try {
handler(event);
}
catch (error) {
console.error("Error in receive handler:", error);
}
}
}
}
/**
* Create WebSocket transport.
*
* @example
* ```typescript
* // Browser usage
* const transport = createWebSocketTransport({
* baseUrl: 'wss://api.example.com',
* });
*
* // Node.js with ws package
* import WebSocket from 'ws';
*
* const nodeTransport = createWebSocketTransport({
* baseUrl: 'wss://api.example.com',
* WebSocket: WebSocket as unknown as WebSocketConstructor,
* });
* ```
*/
export function createWebSocketTransport(config) {
return new WebSocketTransport(config);
}
//# sourceMappingURL=websocket.js.map
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/transports/websocket.ts"],"names":[],"mappings":"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"}