npm package: @lidoravitan/salt-websocket-server
Description: Websocket server for ios
Author: SaltAudio
Latest version: 1.3.0

# @lidoravitan/salt-websocket-server

A production-ready Capacitor WebSocket server plugin for iOS, Android, and Web platforms. Perfect for building real-time communication features in Capacitor and Ionic applications.

## Features

✨ **Production-Ready**
- Full event-based architecture
- Type-safe TypeScript implementation
- Comprehensive error handling
- Support for iOS, Android, and Web

🚀 **Easy to Use**
- Simple API for starting/stopping server
- Send messages to individual clients or broadcast to all
- Real-time event listeners
- Client connection management

🔒 **Reliable**
- Proper connection lifecycle management
- Built-in error reporting
- Client tracking and status

## Install

### Using npm

```bash
npm install @lidoravitan/salt-websocket-server
npx cap sync
```

### Using yarn

```bash
yarn add @lidoravitan/salt-websocket-server
npx cap sync
```

### Using pnpm

```bash
pnpm add @lidoravitan/salt-websocket-server
npx cap sync
```

## Quick Start

### Basic Usage

```typescript
import { SaltWebsocketServer, SaltWebsocketServerEvent } from '@lidoravitan/salt-websocket-server';

// Start the server
await SaltWebsocketServer.connect({ port: 8080 });

// Listen for events
const serverStartListener = await SaltWebsocketServer.addListener(
  SaltWebsocketServerEvent.SERVER_START,
  () => {
    console.log('Server started!');
  }
);

// Listen for client connections
const clientConnectListener = await SaltWebsocketServer.addListener(
  SaltWebsocketServerEvent.CLIENT_CONNECT,
  (data) => {
    console.log('Client connected:', data.clientId);
  }
);

// Listen for incoming messages
const messageListener = await SaltWebsocketServer.addListener(
  SaltWebsocketServerEvent.MESSAGE,
  (data) => {
    console.log('Message from client:', data.clientId, data.message);
  }
);
```

### Sending Messages

```typescript
// Send to specific client
await SaltWebsocketServer.send({
  clientId: 'client-id-123',
  message: 'Hello client!',
});

// Broadcast to all connected clients
await SaltWebsocketServer.broadcast({
  message: 'Hello everyone!',
});
```

### Connection Lifecycle

```typescript
// Get connected clients
const { clients } = await SaltWebsocketServer.getConnectedClients();
console.log('Connected clients:', clients);

// Listen for disconnections
const disconnectListener = await SaltWebsocketServer.addListener(
  SaltWebsocketServerEvent.CLIENT_DISCONNECT,
  (data) => {
    console.log('Client disconnected:', data.clientId);
  }
);

// Stop the server
await SaltWebsocketServer.disconnect();
```

### Error Handling

```typescript
const errorListener = await SaltWebsocketServer.addListener(
  SaltWebsocketServerEvent.ERROR,
  (data) => {
    console.error('Server error:', data.error, data.code);
  }
);
```

### Cleanup

```typescript
// Remove specific listener
await serverStartListener.remove();

// Remove all listeners
await SaltWebsocketServer.removeListeners();
```

## API

<docgen-index>

* [`connect(...)`](#connect)
* [`disconnect()`](#disconnect)
* [`send(...)`](#send)
* [`broadcast(...)`](#broadcast)
* [`getConnectedClients()`](#getconnectedclients)
* [`removeListeners()`](#removelisteners)
* [Interfaces](#interfaces)
* [Type Aliases](#type-aliases)
* [Enums](#enums)

</docgen-index>

<docgen-api>
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->

Main WebSocket Server Plugin Interface

### connect(...)

```typescript
connect(options: ConnectOptions) => Promise<void>
```

Start the WebSocket server

| Param         | Type                                                      | Description                                         |
| ------------- | --------------------------------------------------------- | --------------------------------------------------- |
| **`options`** | <code><a href="#connectoptions">ConnectOptions</a></code> | Connection options including port and optional host |

--------------------


### disconnect()

```typescript
disconnect() => Promise<void>
```

Stop the WebSocket server

--------------------


### send(...)

```typescript
send(options: SendOptions) => Promise<void>
```

Send a message to a specific client

| Param         | Type                                                | Description                            |
| ------------- | --------------------------------------------------- | -------------------------------------- |
| **`options`** | <code><a href="#sendoptions">SendOptions</a></code> | Send options with clientId and message |

--------------------


### broadcast(...)

```typescript
broadcast(options: BroadcastOptions) => Promise<void>
```

Broadcast a message to all connected clients

| Param         | Type                                                          | Description                    |
| ------------- | ------------------------------------------------------------- | ------------------------------ |
| **`options`** | <code><a href="#broadcastoptions">BroadcastOptions</a></code> | Broadcast options with message |

--------------------


### getConnectedClients()

```typescript
getConnectedClients() => Promise<{ clients: string[]; }>
```

Get list of connected clients

**Returns:** <code>Promise&lt;{ clients: string[]; }&gt;</code>

--------------------


### removeListeners()

```typescript
removeListeners() => Promise<void>
```

Remove all event listeners

--------------------


### Interfaces


#### ConnectOptions

Options for connecting to start the WebSocket server

| Prop       | Type                | Description              |
| ---------- | ------------------- | ------------------------ |
| **`port`** | <code>number</code> | Port number to listen on |


#### SendOptions

Options for sending a message to a client

| Prop           | Type                | Description                          |
| -------------- | ------------------- | ------------------------------------ |
| **`clientId`** | <code>string</code> | The client ID to send the message to |
| **`message`**  | <code>string</code> | The message content to send          |


#### BroadcastOptions

Broadcast options to send a message to all connected clients

| Prop          | Type                | Description                      |
| ------------- | ------------------- | -------------------------------- |
| **`message`** | <code>string</code> | The message content to broadcast |


#### ClientConnectData

Data emitted with CLIENT_CONNECT event

| Prop           | Type                |
| -------------- | ------------------- |
| **`clientId`** | <code>string</code> |


#### ClientDisconnectData

Data emitted with CLIENT_DISCONNECT event

| Prop           | Type                |
| -------------- | ------------------- |
| **`clientId`** | <code>string</code> |


#### MessageData

Data emitted with MESSAGE event

| Prop           | Type                |
| -------------- | ------------------- |
| **`clientId`** | <code>string</code> |
| **`message`**  | <code>string</code> |


#### ErrorData

Data emitted with ERROR event

| Prop        | Type                |
| ----------- | ------------------- |
| **`error`** | <code>string</code> |
| **`code`**  | <code>string</code> |


#### PluginListenerHandle

| Prop         | Type                                      |
| ------------ | ----------------------------------------- |
| **`remove`** | <code>() =&gt; Promise&lt;void&gt;</code> |


### Type Aliases


#### SaltWebsocketServerAddListenerOverloads

Overloads for the addListener method to provide type-safe event callbacks

<code>{ (eventName: <a href="#saltwebsocketserverevent">SaltWebsocketServerEvent.SERVER_START</a>, cb: () =&gt; void): T; (eventName: <a href="#saltwebsocketserverevent">SaltWebsocketServerEvent.SERVER_STOP</a>, cb: () =&gt; void): T; (eventName: <a href="#saltwebsocketserverevent">SaltWebsocketServerEvent.CLIENT_CONNECT</a>, cb: (data: <a href="#clientconnectdata">ClientConnectData</a>) =&gt; void): T; (eventName: <a href="#saltwebsocketserverevent">SaltWebsocketServerEvent.CLIENT_DISCONNECT</a>, cb: (data: <a href="#clientdisconnectdata">ClientDisconnectData</a>) =&gt; void): T; (eventName: <a href="#saltwebsocketserverevent">SaltWebsocketServerEvent.MESSAGE</a>, cb: (data: <a href="#messagedata">MessageData</a>) =&gt; void): T; (eventName: <a href="#saltwebsocketserverevent">SaltWebsocketServerEvent.ERROR</a>, cb: (data: <a href="#errordata">ErrorData</a>) =&gt; void): T; }</code>


### Enums


#### SaltWebsocketServerEvent

| Members                 | Value                           | Description                                     |
| ----------------------- | ------------------------------- | ----------------------------------------------- |
| **`SERVER_START`**      | <code>'serverStart'</code>      | Fired when the server starts listening          |
| **`SERVER_STOP`**       | <code>'serverStop'</code>       | Fired when the server stops listening           |
| **`CLIENT_CONNECT`**    | <code>'clientConnect'</code>    | Fired when a client connects to the server      |
| **`CLIENT_DISCONNECT`** | <code>'clientDisconnect'</code> | Fired when a client disconnects from the server |
| **`MESSAGE`**           | <code>'message'</code>          | Fired when a message is received from a client  |
| **`ERROR`**             | <code>'error'</code>            | Fired when an error occurs                      |

</docgen-api>

## Best Practices

### Connection Management

```typescript
// Always disconnect when done
try {
  await SaltWebsocketServer.connect({ port: 8080 });
  // Use the server
} finally {
  await SaltWebsocketServer.disconnect();
}
```

### Listener Management

```typescript
// Store listener handles and clean up
const listeners = [];

listeners.push(
  await SaltWebsocketServer.addListener(
    SaltWebsocketServerEvent.MESSAGE,
    handleMessage
  )
);

// Later, clean up individual listeners
for (const listener of listeners) {
  await listener.remove();
}

// Or remove all at once
await SaltWebsocketServer.removeListeners();
```

### Error Handling

```typescript
try {
  await SaltWebsocketServer.connect({ port: 8080 });
} catch (error) {
  console.error('Failed to start server:', error);
  // Handle error appropriately
}
```

## Capacitor App Integration

### React Example

```typescript
import { useEffect, useState } from 'react';
import { SaltWebsocketServer, SaltWebsocketServerEvent } from '@lidoravitan/salt-websocket-server';

export function WebSocketComponent() {
  const [clients, setClients] = useState<string[]>([]);
  const [isRunning, setIsRunning] = useState(false);

  useEffect(() => {
    const setupServer = async () => {
      try {
        await SaltWebsocketServer.connect({ port: 8080 });
        setIsRunning(true);

        await SaltWebsocketServer.addListener(
          SaltWebsocketServerEvent.CLIENT_CONNECT,
          async (data) => {
            const { clients: allClients } = await SaltWebsocketServer.getConnectedClients();
            setClients(allClients);
          }
        );
      } catch (error) {
        console.error('Server setup failed:', error);
      }
    };

    setupServer();

    return () => {
      SaltWebsocketServer.disconnect();
    };
  }, []);

  return (
    <div>
      <h1>WebSocket Server {isRunning ? '✅ Running' : '❌ Offline'}</h1>
      <p>Connected clients: {clients.length}</p>
      <ul>
        {clients.map(client => <li key={client}>{client}</li>)}
      </ul>
    </div>
  );
}
```

### Angular Example

```typescript
import { Component, OnInit, OnDestroy } from '@angular/core';
import { SaltWebsocketServer, SaltWebsocketServerEvent, PluginListenerHandle } from '@lidoravitan/salt-websocket-server';

@Component({
  selector: 'app-websocket',
  template: `
    <div>
      <h1>WebSocket Server {{ isRunning ? '✅' : '❌' }}</h1>
      <p>Connected: {{ connectedClients.length }}</p>
      <button (click)="startServer()">Start</button>
      <button (click)="stopServer()">Stop</button>
    </div>
  `,
})
export class WebSocketComponent implements OnInit, OnDestroy {
  isRunning = false;
  connectedClients: string[] = [];
  private listeners: PluginListenerHandle[] = [];

  async ngOnInit() {
    await this.startServer();
  }

  async startServer() {
    try {
      await SaltWebsocketServer.connect({ port: 8080 });
      this.isRunning = true;
      
      const listener = await SaltWebsocketServer.addListener(
        SaltWebsocketServerEvent.MESSAGE,
        (data) => this.handleMessage(data)
      );
      this.listeners.push(listener);
    } catch (error) {
      console.error('Failed to start server:', error);
    }
  }

  async stopServer() {
    await SaltWebsocketServer.disconnect();
    this.isRunning = false;
  }

  private async handleMessage(data: any) {
    console.log('Message:', data);
  }

  async ngOnDestroy() {
    await SaltWebsocketServer.disconnect();
    for (const listener of this.listeners) {
      await listener.remove();
    }
  }
}
```

## Troubleshooting

### Port in Use
If you get an error about the port being in use, try:
- Using a different port
- Making sure the previous server instance is properly disconnected
- Restarting the application

### Connection Issues
- Check that the device/emulator network settings allow connections on the specified port
- Verify the app has required permissions in AndroidManifest.xml and Info.plist
- Check native logs (Xcode Console for iOS, Logcat for Android)

### Message Not Received
- Ensure the client ID is correct
- Verify the client is still connected (check `getConnectedClients()`)
- Check for errors in the error listener

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md)

## License

MIT