BREAKING CHANGE(socketconnection): Stricter typings, smartserve hooks, connection fixes, and tag API change
This commit is contained in:
12
changelog.md
12
changelog.md
@@ -1,5 +1,17 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-12-04 - 4.0.0 - BREAKING CHANGE(socketconnection)
|
||||||
|
Stricter typings, smartserve hooks, connection fixes, and tag API change
|
||||||
|
|
||||||
|
- Add unified WebSocket types and adapter interface (TWebSocket, TMessageEvent, IWebSocketLike) for browser/Node and smartserve peers
|
||||||
|
- Expose smartserve integration via getSmartserveWebSocketHooks() and adapt smartserve peers to a WebSocket-like interface (readyState getter, message/close/error dispatch)
|
||||||
|
- Improve SmartsocketClient connection logic: prevent duplicate connect attempts with isConnecting flag, ensure flags are cleared on success/failure, and tighten timeout/reconnect behavior
|
||||||
|
- Improve message parsing logging to surface JSON parse errors during authentication and normal operation
|
||||||
|
- Tighten TypeScript message and payload types (use unknown instead of any, Record<string, unknown> for tag payloads)
|
||||||
|
- SocketConnection API change: getTagById() and removeTagById() are now synchronous (no longer return Promises) — this is a breaking API change
|
||||||
|
- SocketRequest: log errors when function invocation fails and ensure pending requests are removed on errors
|
||||||
|
- Bump dependency @push.rocks/smartserve to ^1.1.2 and update README to reflect SmartServe integration changes
|
||||||
|
|
||||||
## 2025-12-03 - 3.0.0 - BREAKING CHANGE(smartsocket)
|
## 2025-12-03 - 3.0.0 - BREAKING CHANGE(smartsocket)
|
||||||
Replace setExternalServer with hooks-based SmartServe integration and refactor SocketServer to support standalone and hooks modes
|
Replace setExternalServer with hooks-based SmartServe integration and refactor SocketServer to support standalone and hooks modes
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
"@git.zone/tsbundle": "^2.6.3",
|
"@git.zone/tsbundle": "^2.6.3",
|
||||||
"@git.zone/tsrun": "^2.0.0",
|
"@git.zone/tsrun": "^2.0.0",
|
||||||
"@git.zone/tstest": "^3.1.3",
|
"@git.zone/tstest": "^3.1.3",
|
||||||
"@push.rocks/smartserve": "^1.1.0",
|
"@push.rocks/smartserve": "^1.1.2",
|
||||||
"@types/node": "^24.10.1",
|
"@types/node": "^24.10.1",
|
||||||
"@types/ws": "^8.18.1"
|
"@types/ws": "^8.18.1"
|
||||||
},
|
},
|
||||||
|
|||||||
3768
pnpm-lock.yaml
generated
3768
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
24
readme.md
24
readme.md
@@ -143,20 +143,24 @@ await socketConnection.addTag({
|
|||||||
Use smartsocket with `@push.rocks/smartserve` for advanced HTTP/WebSocket handling:
|
Use smartsocket with `@push.rocks/smartserve` for advanced HTTP/WebSocket handling:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Smartserve } from '@push.rocks/smartserve';
|
import { SmartServe } from '@push.rocks/smartserve';
|
||||||
import { Smartsocket } from '@push.rocks/smartsocket';
|
import { Smartsocket } from '@push.rocks/smartsocket';
|
||||||
|
|
||||||
const smartserve = new Smartserve({ port: 3000 });
|
// Create smartsocket without a port (hooks mode)
|
||||||
const smartsocket = new Smartsocket({ alias: 'myServer' });
|
const smartsocket = new Smartsocket({ alias: 'myServer' });
|
||||||
|
|
||||||
// Set smartserve as external server
|
// Get WebSocket hooks and pass them to SmartServe
|
||||||
await smartsocket.setExternalServer('smartserve', smartserve);
|
const wsHooks = smartsocket.getSmartserveWebSocketHooks();
|
||||||
|
const smartserve = new SmartServe({
|
||||||
|
port: 3000,
|
||||||
|
websocket: wsHooks
|
||||||
|
});
|
||||||
|
|
||||||
// Get WebSocket hooks for smartserve
|
// Add socket functions as usual
|
||||||
const wsHooks = smartsocket.socketServer.getSmartserveWebSocketHooks();
|
smartsocket.addSocketFunction(myFunction);
|
||||||
|
|
||||||
// Configure smartserve with the hooks
|
// Start smartserve (smartsocket hooks mode doesn't need start())
|
||||||
// (see smartserve documentation for integration details)
|
await smartserve.start();
|
||||||
```
|
```
|
||||||
|
|
||||||
### Handling Disconnections
|
### Handling Disconnections
|
||||||
@@ -223,11 +227,11 @@ const response = await client.serverCall<IGreetRequest>('greet', { name: 'Bob' }
|
|||||||
|
|
||||||
| Method | Description |
|
| Method | Description |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `start()` | Start the WebSocket server |
|
| `start()` | Start the WebSocket server (not needed in hooks mode) |
|
||||||
| `stop()` | Stop the server and close all connections |
|
| `stop()` | Stop the server and close all connections |
|
||||||
| `addSocketFunction(fn)` | Register a function that clients can call |
|
| `addSocketFunction(fn)` | Register a function that clients can call |
|
||||||
| `clientCall(funcName, data, connection)` | Call a function on a specific client |
|
| `clientCall(funcName, data, connection)` | Call a function on a specific client |
|
||||||
| `setExternalServer(type, server)` | Use an external server (smartserve) |
|
| `getSmartserveWebSocketHooks()` | Get hooks for smartserve integration |
|
||||||
|
|
||||||
### SmartsocketClient
|
### SmartsocketClient
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartsocket',
|
name: '@push.rocks/smartsocket',
|
||||||
version: '3.0.0',
|
version: '4.0.0',
|
||||||
description: 'Provides easy and secure websocket communication mechanisms, including server and client implementation, function call routing, connection management, and tagging.'
|
description: 'Provides easy and secure websocket communication mechanisms, including server and client implementation, function call routing, connection management, and tagging.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export type TMessageType =
|
|||||||
/**
|
/**
|
||||||
* Base message interface for all smartsocket messages
|
* Base message interface for all smartsocket messages
|
||||||
*/
|
*/
|
||||||
export interface ISocketMessage<T = any> {
|
export interface ISocketMessage<T = unknown> {
|
||||||
type: TMessageType;
|
type: TMessageType;
|
||||||
id?: string; // For request/response correlation
|
id?: string; // For request/response correlation
|
||||||
payload: T;
|
payload: T;
|
||||||
@@ -44,16 +44,16 @@ export interface IAuthResponsePayload {
|
|||||||
/**
|
/**
|
||||||
* Function call payload
|
* Function call payload
|
||||||
*/
|
*/
|
||||||
export interface IFunctionCallPayload {
|
export interface IFunctionCallPayload<T = unknown> {
|
||||||
funcName: string;
|
funcName: string;
|
||||||
funcData: any;
|
funcData: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tag update payload
|
* Tag update payload
|
||||||
*/
|
*/
|
||||||
export interface ITagUpdatePayload {
|
export interface ITagUpdatePayload {
|
||||||
tags: { [key: string]: any };
|
tags: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export class Smartsocket {
|
|||||||
* Handle a new WebSocket connection
|
* Handle a new WebSocket connection
|
||||||
* Called by SocketServer when a new connection is established
|
* Called by SocketServer when a new connection is established
|
||||||
*/
|
*/
|
||||||
public async handleNewConnection(socket: WebSocket | pluginsTyped.ws.WebSocket) {
|
public async handleNewConnection(socket: pluginsTyped.TWebSocket | pluginsTyped.IWebSocketLike) {
|
||||||
const socketConnection: SocketConnection = new SocketConnection({
|
const socketConnection: SocketConnection = new SocketConnection({
|
||||||
alias: undefined,
|
alias: undefined,
|
||||||
authenticated: false,
|
authenticated: false,
|
||||||
@@ -76,8 +76,8 @@ export class Smartsocket {
|
|||||||
socketConnection.eventSubject.next('disconnected');
|
socketConnection.eventSubject.next('disconnected');
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.addEventListener('close', handleClose);
|
(socket as pluginsTyped.IWebSocketLike).addEventListener('close', handleClose);
|
||||||
socket.addEventListener('error', handleClose);
|
(socket as pluginsTyped.IWebSocketLike).addEventListener('error', handleClose);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await socketConnection.authenticate();
|
await socketConnection.authenticate();
|
||||||
|
|||||||
@@ -98,11 +98,18 @@ export class SmartsocketClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private isReconnecting = false;
|
private isReconnecting = false;
|
||||||
|
private isConnecting = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* connect the client to the server
|
* connect the client to the server
|
||||||
*/
|
*/
|
||||||
public async connect() {
|
public async connect() {
|
||||||
|
// Prevent duplicate connection attempts
|
||||||
|
if (this.isConnecting) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.isConnecting = true;
|
||||||
|
|
||||||
// Only reset retry counters on fresh connection (not during auto-reconnect)
|
// Only reset retry counters on fresh connection (not during auto-reconnect)
|
||||||
if (!this.isReconnecting) {
|
if (!this.isReconnecting) {
|
||||||
this.currentRetryCount = 0;
|
this.currentRetryCount = 0;
|
||||||
@@ -213,6 +220,7 @@ export class SmartsocketClient {
|
|||||||
await this.addTag(oldTagStore[tag]);
|
await this.addTag(oldTagStore[tag]);
|
||||||
}
|
}
|
||||||
this.updateStatus('connected');
|
this.updateStatus('connected');
|
||||||
|
this.isConnecting = false;
|
||||||
done.resolve();
|
done.resolve();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -262,6 +270,7 @@ export class SmartsocketClient {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.disconnectRunning = true;
|
this.disconnectRunning = true;
|
||||||
|
this.isConnecting = false;
|
||||||
this.updateStatus('disconnecting');
|
this.updateStatus('disconnecting');
|
||||||
this.tagStoreSubscription?.unsubscribe();
|
this.tagStoreSubscription?.unsubscribe();
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export interface ISocketConnectionConstructorOptions {
|
|||||||
authenticated: boolean;
|
authenticated: boolean;
|
||||||
side: TSocketConnectionSide;
|
side: TSocketConnectionSide;
|
||||||
smartsocketHost: Smartsocket | SmartsocketClient;
|
smartsocketHost: Smartsocket | SmartsocketClient;
|
||||||
socket: WebSocket | pluginsTyped.ws.WebSocket;
|
socket: pluginsTyped.TWebSocket | pluginsTyped.IWebSocketLike;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,7 +47,7 @@ export class SocketConnection {
|
|||||||
public side: TSocketConnectionSide;
|
public side: TSocketConnectionSide;
|
||||||
public authenticated: boolean = false;
|
public authenticated: boolean = false;
|
||||||
public smartsocketRef: Smartsocket | SmartsocketClient;
|
public smartsocketRef: Smartsocket | SmartsocketClient;
|
||||||
public socket: WebSocket | pluginsTyped.ws.WebSocket;
|
public socket: pluginsTyped.TWebSocket | pluginsTyped.IWebSocketLike;
|
||||||
|
|
||||||
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
||||||
public eventStatus: interfaces.TConnectionStatus = 'new';
|
public eventStatus: interfaces.TConnectionStatus = 'new';
|
||||||
@@ -82,13 +82,13 @@ export class SocketConnection {
|
|||||||
public handleMessage(messageData: interfaces.ISocketMessage): void {
|
public handleMessage(messageData: interfaces.ISocketMessage): void {
|
||||||
switch (messageData.type) {
|
switch (messageData.type) {
|
||||||
case 'function':
|
case 'function':
|
||||||
this.handleFunctionCall(messageData);
|
this.handleFunctionCall(messageData as interfaces.ISocketMessage<interfaces.IFunctionCallPayload>);
|
||||||
break;
|
break;
|
||||||
case 'functionResponse':
|
case 'functionResponse':
|
||||||
this.handleFunctionResponse(messageData);
|
this.handleFunctionResponse(messageData as interfaces.ISocketMessage<interfaces.IFunctionCallPayload>);
|
||||||
break;
|
break;
|
||||||
case 'tagUpdate':
|
case 'tagUpdate':
|
||||||
this.handleTagUpdate(messageData);
|
this.handleTagUpdate(messageData as interfaces.ISocketMessage<interfaces.ITagUpdatePayload>);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Authentication messages are handled by the server/client classes
|
// Authentication messages are handled by the server/client classes
|
||||||
@@ -96,7 +96,7 @@ export class SocketConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleFunctionCall(messageData: interfaces.ISocketMessage): void {
|
private handleFunctionCall(messageData: interfaces.ISocketMessage<interfaces.IFunctionCallPayload>): void {
|
||||||
const requestData: ISocketRequestDataObject<any> = {
|
const requestData: ISocketRequestDataObject<any> = {
|
||||||
funcCallData: {
|
funcCallData: {
|
||||||
funcName: messageData.payload.funcName,
|
funcName: messageData.payload.funcName,
|
||||||
@@ -123,7 +123,7 @@ export class SocketConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleFunctionResponse(messageData: interfaces.ISocketMessage): void {
|
private handleFunctionResponse(messageData: interfaces.ISocketMessage<interfaces.IFunctionCallPayload>): void {
|
||||||
const responseData: ISocketRequestDataObject<any> = {
|
const responseData: ISocketRequestDataObject<any> = {
|
||||||
funcCallData: {
|
funcCallData: {
|
||||||
funcName: messageData.payload.funcName,
|
funcName: messageData.payload.funcName,
|
||||||
@@ -141,7 +141,7 @@ export class SocketConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleTagUpdate(messageData: interfaces.ISocketMessage): void {
|
private handleTagUpdate(messageData: interfaces.ISocketMessage<interfaces.ITagUpdatePayload>): void {
|
||||||
const tagStoreArg = messageData.payload.tags as interfaces.TTagStore;
|
const tagStoreArg = messageData.payload.tags as interfaces.TTagStore;
|
||||||
if (!plugins.smartjson.deepEqualObjects(this.tagStore, tagStoreArg)) {
|
if (!plugins.smartjson.deepEqualObjects(this.tagStore, tagStoreArg)) {
|
||||||
this.tagStore = tagStoreArg;
|
this.tagStore = tagStoreArg;
|
||||||
@@ -181,17 +181,16 @@ export class SocketConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gets a tag by id
|
* Gets a tag by id
|
||||||
* @param tagIdArg
|
|
||||||
*/
|
*/
|
||||||
public async getTagById(tagIdArg: interfaces.ITag['id']) {
|
public getTagById(tagIdArg: interfaces.ITag['id']): interfaces.ITag | undefined {
|
||||||
return this.tagStore[tagIdArg];
|
return this.tagStore[tagIdArg];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* removes a tag from a connection
|
* Removes a tag from a connection
|
||||||
*/
|
*/
|
||||||
public async removeTagById(tagIdArg: interfaces.ITag['id']) {
|
public removeTagById(tagIdArg: interfaces.ITag['id']): void {
|
||||||
delete this.tagStore[tagIdArg];
|
delete this.tagStore[tagIdArg];
|
||||||
this.tagStoreObservable.next(this.tagStore);
|
this.tagStoreObservable.next(this.tagStore);
|
||||||
this.sendMessage({
|
this.sendMessage({
|
||||||
@@ -209,7 +208,7 @@ export class SocketConnection {
|
|||||||
const done = plugins.smartpromise.defer<SocketConnection>();
|
const done = plugins.smartpromise.defer<SocketConnection>();
|
||||||
|
|
||||||
// Set up message handler for authentication
|
// Set up message handler for authentication
|
||||||
const messageHandler = (event: MessageEvent | { data: string }) => {
|
const messageHandler = (event: pluginsTyped.TMessageEvent) => {
|
||||||
try {
|
try {
|
||||||
const data = typeof event.data === 'string' ? event.data : event.data.toString();
|
const data = typeof event.data === 'string' ? event.data : event.data.toString();
|
||||||
const message: interfaces.ISocketMessage = JSON.parse(data);
|
const message: interfaces.ISocketMessage = JSON.parse(data);
|
||||||
@@ -241,11 +240,11 @@ export class SocketConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Not a valid message, ignore
|
logger.log('warn', `Failed to parse auth message: ${err instanceof Error ? err.message : String(err)}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.socket.addEventListener('message', messageHandler as any);
|
(this.socket as pluginsTyped.IWebSocketLike).addEventListener('message', messageHandler);
|
||||||
|
|
||||||
// Request authentication
|
// Request authentication
|
||||||
const requestAuthPayload: interfaces.TAuthRequestMessage = {
|
const requestAuthPayload: interfaces.TAuthRequestMessage = {
|
||||||
@@ -268,17 +267,17 @@ export class SocketConnection {
|
|||||||
const done = plugins.smartpromise.defer();
|
const done = plugins.smartpromise.defer();
|
||||||
if (this.authenticated) {
|
if (this.authenticated) {
|
||||||
// Set up message handler for all messages
|
// Set up message handler for all messages
|
||||||
const messageHandler = (event: MessageEvent | { data: string }) => {
|
const messageHandler = (event: pluginsTyped.TMessageEvent) => {
|
||||||
try {
|
try {
|
||||||
const data = typeof event.data === 'string' ? event.data : event.data.toString();
|
const data = typeof event.data === 'string' ? event.data : event.data.toString();
|
||||||
const message: interfaces.ISocketMessage = JSON.parse(data);
|
const message: interfaces.ISocketMessage = JSON.parse(data);
|
||||||
this.handleMessage(message);
|
this.handleMessage(message);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Not a valid JSON message, ignore
|
logger.log('warn', `Failed to parse socket message: ${err instanceof Error ? err.message : String(err)}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.socket.addEventListener('message', messageHandler as any);
|
(this.socket as pluginsTyped.IWebSocketLike).addEventListener('message', messageHandler);
|
||||||
|
|
||||||
logger.log(
|
logger.log(
|
||||||
'info',
|
'info',
|
||||||
|
|||||||
@@ -128,6 +128,10 @@ export class SocketRequest<T extends plugins.typedrequestInterfaces.ITypedReques
|
|||||||
};
|
};
|
||||||
this.originSocketConnection.sendMessage(message);
|
this.originSocketConnection.sendMessage(message);
|
||||||
this.smartsocketRef.socketRequests.remove(this);
|
this.smartsocketRef.socketRequests.remove(this);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
logger.log('error', `Function invocation failed for ${this.funcCallData.funcName}: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
|
this.smartsocketRef.socketRequests.remove(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ export class SocketServer {
|
|||||||
onOpen: async (peer: pluginsTyped.ISmartserveWebSocketPeer) => {
|
onOpen: async (peer: pluginsTyped.ISmartserveWebSocketPeer) => {
|
||||||
// Create a wrapper that adapts ISmartserveWebSocketPeer to WebSocket-like interface
|
// Create a wrapper that adapts ISmartserveWebSocketPeer to WebSocket-like interface
|
||||||
const wsLikeSocket = this.createWsLikeFromPeer(peer);
|
const wsLikeSocket = this.createWsLikeFromPeer(peer);
|
||||||
await this.smartsocket.handleNewConnection(wsLikeSocket as any);
|
await this.smartsocket.handleNewConnection(wsLikeSocket);
|
||||||
},
|
},
|
||||||
onMessage: async (peer: pluginsTyped.ISmartserveWebSocketPeer, message: pluginsTyped.ISmartserveWebSocketMessage) => {
|
onMessage: async (peer: pluginsTyped.ISmartserveWebSocketPeer, message: pluginsTyped.ISmartserveWebSocketMessage) => {
|
||||||
// Dispatch message to the SocketConnection via the adapter
|
// Dispatch message to the SocketConnection via the adapter
|
||||||
@@ -153,8 +153,8 @@ export class SocketServer {
|
|||||||
* Creates a WebSocket-like object from a smartserve peer
|
* Creates a WebSocket-like object from a smartserve peer
|
||||||
* This allows our SocketConnection to work with both native WebSocket and smartserve peers
|
* This allows our SocketConnection to work with both native WebSocket and smartserve peers
|
||||||
*/
|
*/
|
||||||
private createWsLikeFromPeer(peer: pluginsTyped.ISmartserveWebSocketPeer): any {
|
private createWsLikeFromPeer(peer: pluginsTyped.ISmartserveWebSocketPeer): pluginsTyped.IWebSocketLike {
|
||||||
const messageListeners: Array<(event: any) => void> = [];
|
const messageListeners: Array<(event: pluginsTyped.TMessageEvent) => void> = [];
|
||||||
const closeListeners: Array<() => void> = [];
|
const closeListeners: Array<() => void> = [];
|
||||||
const errorListeners: Array<() => void> = [];
|
const errorListeners: Array<() => void> = [];
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ export class SocketServer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
readyState: peer.readyState,
|
get readyState() { return peer.readyState; },
|
||||||
send: (data: string) => peer.send(data),
|
send: (data: string) => peer.send(data),
|
||||||
close: (code?: number, reason?: string) => peer.close(code, reason),
|
close: (code?: number, reason?: string) => peer.close(code, reason),
|
||||||
addEventListener: (event: string, listener: any) => {
|
addEventListener: (event: string, listener: any) => {
|
||||||
|
|||||||
@@ -13,6 +13,29 @@ export namespace ws {
|
|||||||
export type RawData = wsTypes.RawData;
|
export type RawData = wsTypes.RawData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unified WebSocket type supporting both browser and Node.js environments
|
||||||
|
*/
|
||||||
|
export type TWebSocket = WebSocket | ws.WebSocket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message event type for WebSocket messages (browser and Node.js compatible)
|
||||||
|
*/
|
||||||
|
export type TMessageEvent = MessageEvent | { data: string };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WebSocket-like interface for adapters (e.g., smartserve peer adapter)
|
||||||
|
*/
|
||||||
|
export interface IWebSocketLike {
|
||||||
|
readyState: number;
|
||||||
|
send(data: string): void;
|
||||||
|
close(code?: number, reason?: string): void;
|
||||||
|
addEventListener(event: 'message', listener: (event: TMessageEvent) => void): void;
|
||||||
|
addEventListener(event: 'close', listener: () => void): void;
|
||||||
|
addEventListener(event: 'error', listener: () => void): void;
|
||||||
|
removeEventListener?(event: string, listener: (...args: any[]) => void): void;
|
||||||
|
}
|
||||||
|
|
||||||
// smartserve compatibility interface (for setExternalServer)
|
// smartserve compatibility interface (for setExternalServer)
|
||||||
// This mirrors the IWebSocketPeer interface from smartserve
|
// This mirrors the IWebSocketPeer interface from smartserve
|
||||||
export interface ISmartserveWebSocketPeer {
|
export interface ISmartserveWebSocketPeer {
|
||||||
|
|||||||
Reference in New Issue
Block a user