npm package: @roomkit/client
Description: Client SDK for Gateway-Worker Framework - Colyseus-inspired TypeScript SDK
Latest version: 1.3.1

# @roomkit/client

Client SDK for Gateway-Worker Framework - A TypeScript SDK inspired by Colyseus.

## Features

- 🎯 **Colyseus-inspired API** - Familiar and intuitive for game developers
- 🔐 **Type-safe** - Full TypeScript support with generics
- 🔌 **WebSocket-based** - Real-time bidirectional communication
- 🔄 **Auto-reconnection** - Configurable reconnection strategy
- ❤️ **Heartbeat** - Automatic connection health monitoring
- 🎮 **Room abstraction** - Easy room management and state synchronization
- 📦 **Lightweight** - Minimal dependencies

## Installation

```bash
pnpm add @roomkit/client
```

## Quick Start

### 1. Create a Client

```typescript
import { Client } from '@roomkit/client';

const client = new Client('ws://localhost:27100/ws', {
  autoReconnect: true,
  reconnectDelay: 1000,
  maxReconnectAttempts: 10,
});
```

### 2. Authenticate

```typescript
await client.auth('your-auth-token');
console.log('Authenticated as:', client.userId);
```

### 3. Join or Create a Room

```typescript
interface GameState {
  players: { [id: string]: PlayerData };
  gameStatus: 'waiting' | 'playing' | 'finished';
}

const room = await client.joinOrCreate<GameState>('my-game', {
  maxPlayers: 4,
});

console.log('Joined room:', room.id);
```

### 4. Listen to State Changes

```typescript
room.onStateChange((state) => {
  console.log('State updated:', state);
  // Update your UI based on new state
});
```

### 5. Listen to Messages

```typescript
// Listen to specific message types
room.onMessage('player_joined', (message) => {
  console.log('New player:', message);
});

// Listen to game events
room.onMessage('game_started', (message) => {
  console.log('Game started!');
});
```

### 6. Send Messages

```typescript
// Send game actions
room.send('player_action', {
  type: 'move',
  x: 100,
  y: 200,
});

// Request with response
const result = await room.request('make_move', {
  position: 5,
});
console.log('Move result:', result);
```

### 7. Leave Room

```typescript
await room.leave();
```

## API Reference

### Client

#### Constructor

```typescript
new Client(url: string, options?: ClientOptions)
```

**Options:**
- `autoReconnect?: boolean` - Auto-reconnect on disconnect (default: `true`)
- `reconnectDelay?: number` - Delay between reconnection attempts in ms (default: `1000`)
- `maxReconnectAttempts?: number` - Maximum reconnection attempts (default: `10`)
- `requestTimeout?: number` - Request timeout in ms (default: `10000`)
- `heartbeatInterval?: number` - Heartbeat interval in ms (default: `20000`)

#### Methods

##### `async auth(token: string): Promise<void>`
Authenticate with the server.

##### `async create<State>(roomName: string, options?: RoomOptions): Promise<Room<State>>`
Create a new room.

##### `async join<State>(roomId: string, options?: RoomOptions): Promise<Room<State>>`
Join an existing room.

##### `async joinOrCreate<State>(roomName: string, options?: RoomOptions): Promise<Room<State>>`
Join an existing room or create a new one (recommended).

##### `async getAvailableRooms(roomName?: string): Promise<AvailableRoom[]>`
Get list of available rooms.

##### `disconnect(): void`
Disconnect from the server.

#### Properties

- `state: ConnectionState` - Current connection state
- `userId: string | null` - Current user ID (after auth)
- `isConnected: boolean` - Whether client is connected
- `isAuthenticated: boolean` - Whether client is authenticated

### Room

#### Properties

- `id: string` - Room ID
- `sessionId: string` - Session ID
- `name: string` - Room name
- `state: State | null` - Current room state

#### Methods

##### `onStateChange(callback: (state: State) => void): () => void`
Listen to state changes. Returns an unsubscribe function.

##### `onJoin(callback: () => void): () => void`
Listen to room join event.

##### `onLeave(callback: (code: number) => void): () => void`
Listen to room leave event.

##### `onError(callback: (code: number, message: string) => void): () => void`
Listen to error events.

##### `onMessage<T>(type: number | string, callback: (message: T) => void): () => void`
Listen to custom messages.

##### `send(type: number | string, message?: any): void`
Send a message to the room.

##### `async request<T>(type: number | string, message?: any): Promise<T>`
Send a request and wait for response.

##### `async leave(consented?: boolean): Promise<void>`
Leave the room.

## Examples

### Basic Game Client

```typescript
import { Client } from '@roomkit/client';

class GameClient {
  private client: Client;
  private room: Room | null = null;

  constructor() {
    this.client = new Client('ws://localhost:27100/ws');
  }

  async connect(token: string) {
    await this.client.auth(token);
  }

  async joinGame(gameType: string) {
    this.room = await this.client.joinOrCreate(gameType);
    
    this.room.onStateChange((state) => {
      this.onStateUpdate(state);
    });
    
    this.room.onMessage('game_event', (event) => {
      this.onGameEvent(event);
    });
    
    this.room.onLeave(() => {
      console.log('Left room');
      this.room = null;
    });
  }

  async sendAction(action: any) {
    if (this.room) {
      this.room.send('player_action', action);
    }
  }

  private onStateUpdate(state: any) {
    // Update UI
  }

  private onGameEvent(event: any) {
    // Handle game events
  }
}
```

### Chat Client Example

See [examples/simple-chat-client.ts](./examples/simple-chat-client.ts) for a complete example.

## Type Safety

The SDK provides full TypeScript support:

```typescript
interface MyGameState {
  round: number;
  players: {
    id: string;
    score: number;
    ready: boolean;
  }[];
}

const room = await client.joinOrCreate<MyGameState>('my-game');

// state is typed as MyGameState
room.onStateChange((state) => {
  console.log(state.round); // TypeScript knows this exists
  console.log(state.players); // Fully typed
});
```

## Advanced Usage

### Custom Message IDs

```typescript
import { MessageId } from '@roomkit/client';

// Use predefined message IDs
room.send(MessageId.PLAYER_READY, { ready: true });

// Or use custom string types (auto-hashed)
room.send('my_custom_action', { data: 'value' });
```

### Connection State Monitoring

```typescript
client.onStateChange((state) => {
  console.log('Connection state:', state);
  // 'disconnected' | 'connecting' | 'connected' | 'authenticated'
});
```

### Error Handling

```typescript
room.onError((code, message) => {
  console.error(`Room error ${code}:`, message);
});

try {
  await room.leave();
} catch (error) {
  console.error('Failed to leave room:', error);
}
```

## License

MIT