npm package: @soapjs/soap-node-socket
Description: Seamless Socket integration for SoapJS projects, facilitating clean architecture practices and streamlined real-time communication.
Author: Radoslaw Kamysz
Latest version: 0.0.2

# @soapjs/soap-node-socket

Seamless Socket integration for SoapJS projects, facilitating clean architecture practices and streamlined real-time communication.

## Features

- **Multiple Socket Libraries Support**: WebSocket (`ws`) and Socket.IO adapters
- **Abstract Interfaces**: Clean separation between socket implementations and business logic
- **Advanced Features**: Heartbeat monitoring, rate limiting, message queuing, subscriptions
- **TypeScript Support**: Full type safety with generic message types
- **SoapJS Integration**: Built on top of SoapJS common infrastructure
- **Optional Dependencies**: Choose your preferred socket library without forcing both

## Installation

```bash
npm install @soapjs/soap-node-socket
```

### Optional Dependencies

Choose one or both socket libraries:

```bash
# For WebSocket support
npm install ws

# For Socket.IO support  
npm install socket.io

# Or install both
npm install ws socket.io
```

## Quick Start

### WebSocket Example

```typescript
import { SocketClient, SocketServer, WebSocketAdapter, WebSocketServerAdapter } from "@soapjs/soap-node-socket";

// Server
const server = new SocketServer(new WebSocketServerAdapter(8080), {
  port: 8080,
  onConnection: (clientId) => console.log(`Client connected: ${clientId}`),
  onMessage: (clientId, message) => {
    console.log(`Message from ${clientId}:`, message);
    server.sendToClient(clientId, {
      type: "echo",
      payload: `You said: ${message.payload}`
    });
  }
});

// Client
const client = new SocketClient(new WebSocketAdapter("ws://localhost:8080"), {
  url: "ws://localhost:8080",
  onOpen: () => console.log("Connected"),
  onMessage: (message) => console.log("Received:", message)
});

await client.connect();
await client.send({ type: "greeting", payload: "Hello Server!" });
```

### Socket.IO Example

```typescript
import { SocketClient, SocketServer, SocketIOAdapter, SocketIOServerAdapter } from "@soapjs/soap-node-socket";

// Server
const server = new SocketServer(new SocketIOServerAdapter(3000), {
  port: 3000,
  onConnection: (clientId) => console.log(`Client connected: ${clientId}`),
  onMessage: (clientId, message) => {
    server.broadcast({
      type: "broadcast",
      payload: `Client ${clientId} said: ${message.payload}`
    });
  }
});

// Client
const client = new SocketClient(new SocketIOAdapter("http://localhost:3000"), {
  url: "http://localhost:3000",
  onOpen: () => console.log("Connected"),
  onMessage: (message) => console.log("Received:", message)
});

await client.connect();
await client.send({ type: "message", payload: "Hello everyone!" });
```

## Core Components

### SocketClient

Enhanced client with advanced features:

```typescript
const client = new SocketClient(adapter, {
  url: "ws://localhost:8080",
  heartbeatInterval: 30000,    // Heartbeat every 30 seconds
  maxRate: 10,                 // Max 10 messages per second
  reconnect: {
    retries: 5,
    delay: 1000
  },
  onOpen: () => console.log("Connected"),
  onClose: () => console.log("Disconnected"),
  onError: (error) => console.error("Error:", error)
});

// Subscribe to specific message types
client.subscribe("notification", (message) => {
  console.log("Notification:", message.payload);
});

// Send messages
await client.send({
  type: "chat",
  payload: { message: "Hello!", user: "Alice" }
});
```

### SocketServer

Advanced server with client management:

```typescript
const server = new SocketServer(adapter, {
  port: 8080,
  heartbeatInterval: 30000,
  rateLimit: 100,              // Max 100 messages per client per minute
  onConnection: (clientId) => {
    console.log(`Client connected: ${clientId}`);
    server.subscribe(clientId, "general"); // Auto-subscribe to general room
  },
  onDisconnection: (clientId) => {
    console.log(`Client disconnected: ${clientId}`);
  },
  onMessage: (clientId, message) => {
    // Handle different message types
    switch (message.type) {
      case "join_room":
        server.subscribe(clientId, message.payload.room);
        break;
      case "chat":
        server.sendToSubscribers(message.payload.room, message);
        break;
    }
  }
});

// Broadcasting
server.broadcast({ type: "announcement", payload: "Server maintenance in 5 minutes" });

// Send to specific subscribers
server.sendToSubscribers("general", { type: "chat", payload: "Hello room!" });
```

## Adapters

### WebSocketAdapter

```typescript
import { WebSocketAdapter, WebSocketServerAdapter } from "@soapjs/soap-node-socket";

// Client
const clientAdapter = new WebSocketAdapter("ws://localhost:8080", {
  headers: { Authorization: "Bearer token" }
});

// Server
const serverAdapter = new WebSocketServerAdapter(8080, {
  perMessageDeflate: false
});
```

### SocketIOAdapter

```typescript
import { SocketIOAdapter, SocketIOServerAdapter } from "@soapjs/soap-node-socket";

// Client
const clientAdapter = new SocketIOAdapter("http://localhost:3000", {
  auth: { token: "jwt-token" },
  transports: ["websocket"]
});

// Server
const serverAdapter = new SocketIOServerAdapter(3000, {
  cors: { origin: "*" },
  transports: ["websocket"]
});
```

## Advanced Features

### Message Queuing

Messages are automatically queued when disconnected and sent when reconnected:

```typescript
const client = new SocketClient(adapter, {
  url: "ws://localhost:8080",
  onOpen: () => {
    console.log(`Queued messages: ${client.queuedMessages}`);
  }
});

// These will be queued if not connected
await client.send({ type: "message1", payload: "Hello" });
await client.send({ type: "message2", payload: "World" });
```

### Rate Limiting

Control message flow to prevent abuse:

```typescript
const client = new SocketClient(adapter, {
  url: "ws://localhost:8080",
  maxRate: 5  // Max 5 messages per second
});

// Messages exceeding the rate limit will be queued
for (let i = 0; i < 10; i++) {
  await client.send({ type: "message", payload: `Message ${i}` });
}
```

### Subscriptions

Manage client subscriptions for different message types:

```typescript
// Server side
server.subscribe(clientId, "notifications");
server.subscribe(clientId, "updates");
server.unsubscribe(clientId, "notifications");

// Send to specific subscribers
server.sendToSubscribers("notifications", {
  type: "notification",
  payload: { message: "New update available!" }
});
```

### Heartbeat Monitoring

Automatic connection health monitoring:

```typescript
const server = new SocketServer(adapter, {
  port: 8080,
  heartbeatInterval: 30000  // Ping clients every 30 seconds
});

const client = new SocketClient(adapter, {
  url: "ws://localhost:8080",
  heartbeatInterval: 30000  // Send ping every 30 seconds
});
```

## Integration with SoapJS

This package integrates seamlessly with SoapJS infrastructure:

```typescript
import { Result, Failure, IO } from "@soapjs/soap";
import { SocketClient, SocketServer } from "@soapjs/soap-node-socket";

// Use Result/Failure for error handling
const handleMessage = async (message: any): Promise<Result<any>> => {
  try {
    // Process message
    return Result.withSuccess(processedData);
  } catch (error) {
    return Result.withFailure(Failure.fromError(error as Error));
  }
};

// Use IO for data transformation
class MessageIO implements IO<InputType, OutputType> {
  from<T>(source: T): InputType {
    // Transform incoming data
  }
  
  to<T>(result: OutputType, target: T): void {
    // Transform outgoing data
  }
}
```

## Examples

Check the `examples/` directory for complete working examples:

- `websocket-example.ts` - WebSocket chat application
- `socketio-example.ts` - Socket.IO chat and notification system

## API Reference

### SocketClient

#### Constructor
```typescript
constructor(socket: AbstractSocket, options: SocketClientOptions<MessageType, HeadersType>)
```

#### Methods
- `connect(): Promise<void>` - Connect to server
- `send(message: SocketMessage): Promise<void>` - Send message
- `subscribe(type: string, handler: Function): void` - Subscribe to message type
- `unsubscribe(type: string): void` - Unsubscribe from message type
- `disconnect(): Promise<void>` - Disconnect from server

#### Properties
- `connected: boolean` - Connection status
- `queuedMessages: number` - Number of queued messages
- `activeSubscriptions: string[]` - Active subscriptions

### SocketServer

#### Constructor
```typescript
constructor(server: AbstractSocketServer, options: SocketServerOptions)
```

#### Methods
- `broadcast(message: SocketMessage): void` - Broadcast to all clients
- `sendToClient(clientId: string, message: SocketMessage): void` - Send to specific client
- `sendToSubscribers(type: string, message: SocketMessage): void` - Send to subscribers
- `subscribe(clientId: string, type: string): void` - Subscribe client to type
- `unsubscribe(clientId: string, type: string): void` - Unsubscribe client from type
- `shutdown(): void` - Gracefully shutdown server

#### Properties
- `connectedClients: string[]` - List of connected client IDs
- `clientCount: number` - Number of connected clients
- `subscriptionTypes: string[]` - Available subscription types

## License

MIT

## Contributing

Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.

## Support

For support and questions, please visit our documentation at [https://docs.soapjs.com](https://docs.soapjs.com) or open an issue on GitHub.