npm package: @ichaingo/web-socket
Description: 基于WebSocket的单例模式连接库，提供稳定可靠的WebSocket连接管理功能和React Hooks。
Latest version: 1.5.37
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# @ichaingo/socket

基于WebSocket的单例模式连接库，提供稳定可靠的WebSocket连接管理功能和React Hooks。

## 特性

- 🔄 **单例模式**: 确保全局只有一个WebSocket连接实例
- 🔁 **自动重连**: 连接断开时自动尝试重连，支持配置重连次数和间隔
- 💓 **心跳检测**: 定期发送心跳包保持连接活跃
- 📡 **事件驱动**: 支持多种事件监听（连接、消息、错误、状态变化等）
- 🛡️ **错误处理**: 完善的错误处理和状态管理
- 📝 **TypeScript**: 完整的TypeScript类型支持
- 🐛 **调试模式**: 支持调试日志输出
- ⚛️ **React Hooks**: 提供便捷的React Hooks用于组件集成

## 安装

```bash
npm install @ichaingo/socket
# 或
pnpm add @ichaingo/socket
# 或
yarn add @ichaingo/socket
```

## 快速开始

### 基本使用

```typescript
import SocketConnection, { ConnectionStatus } from '@ichaingo/socket';

// 创建连接实例
const socket = SocketConnection.getInstance({
  url: 'ws://localhost:8080',
  debug: true
});

// 连接WebSocket
await socket.connect();

// 发送消息
socket.send('Hello WebSocket!');
socket.sendJSON({ type: 'message', content: 'Hello!' });

// 监听消息
socket.on('message', (data) => {
  console.log('收到消息:', data);
});

// 监听连接状态变化
socket.on('statusChange', (status) => {
  console.log('连接状态:', status);
});
```

### React Hooks 使用

#### useSocket Hook

```tsx
import React from 'react';
import { useSocket } from '@ichaingo/socket';

function ChatComponent() {
  const socket = useSocket({
    url: 'ws://localhost:8080',
    debug: true,
    autoConnect: true
  });

  const [messages, setMessages] = useState<string[]>([]);

  useEffect(() => {
    socket.on('message', (data) => {
      if (typeof data === 'string') {
        setMessages(prev => [...prev, data]);
      }
    });

    return () => {
      socket.off('message');
    };
  }, [socket]);

  const sendMessage = (message: string) => {
    socket.send(message);
  };

  return (
    <div>
      <div>连接状态: {socket.status}</div>
      <div>是否已连接: {socket.isConnected ? '是' : '否'}</div>
      {/* 你的UI组件 */}
    </div>
  );
}
```

#### useSocketMessage Hook

专门用于监听特定类型消息的简化Hook：

```tsx
import React from 'react';
import { useSocketMessage } from '@ichaingo/socket';

interface ChatMessage {
  user: string;
  content: string;
  timestamp: number;
}

function ChatComponent() {
  const [messages, setMessages] = useState<ChatMessage[]>([]);

  const socket = useSocketMessage<ChatMessage>({
    url: 'ws://localhost:8080/chat',
    debug: true,
    autoConnect: true
  }, (message) => {
    setMessages(prev => [...prev, message]);
  });

  const sendMessage = (user: string, content: string) => {
    socket.sendJSON({
      user,
      content,
      timestamp: Date.now()
    });
  };

  return (
    <div>
      <div>连接状态: {socket.status}</div>
      {/* 你的UI组件 */}
    </div>
  );
}
```

#### useSocketStatus Hook

专门用于监听连接状态的简化Hook：

```tsx
import React from 'react';
import { useSocketStatus } from '@ichaingo/socket';

function StatusIndicator() {
  const status = useSocketStatus({
    url: 'ws://localhost:8080',
    debug: true,
    autoConnect: true
  });

  return (
    <div>
      <div>状态: {status.status}</div>
      <div>是否已连接: {status.isConnected ? '是' : '否'}</div>
      <div>是否正在连接: {status.isConnecting ? '是' : '否'}</div>
      <div>是否正在重连: {status.isReconnecting ? '是' : '否'}</div>
      <div>是否已断开: {status.isDisconnected ? '是' : '否'}</div>
      <div>是否有错误: {status.hasError ? '是' : '否'}</div>
    </div>
  );
}
```

## API 参考

### SocketConnection

#### 静态方法

- `getInstance(config?: WebSocketConfig): SocketConnection` - 获取单例实例

#### 实例方法

- `connect(): Promise<void>` - 连接WebSocket
- `disconnect(): void` - 断开连接
- `send(data: string | ArrayBuffer | Blob): boolean` - 发送消息
- `sendJSON(data: any): boolean` - 发送JSON消息
- `on<K extends keyof WebSocketEvents>(event: K, listener: WebSocketEvents[K]): void` - 添加事件监听器
- `off<K extends keyof WebSocketEvents>(event: K): void` - 移除事件监听器
- `getStatus(): ConnectionStatus` - 获取连接状态
- `isConnected(): boolean` - 检查是否已连接
- `destroy(): void` - 销毁实例

### React Hooks

#### useSocket

```typescript
function useSocket(config: UseSocketConfig): UseSocketReturn
```

**参数:**
- `config`: WebSocket配置选项，继承自`WebSocketConfig`并添加了React相关选项

**返回值:**
- `status`: 当前连接状态
- `isConnected`: 是否已连接
- `connect`: 连接方法
- `disconnect`: 断开连接方法
- `send`: 发送消息方法
- `sendJSON`: 发送JSON消息方法
- `on`: 添加事件监听器方法
- `off`: 移除事件监听器方法
- `error`: 当前错误状态
- `reconnectAttempts`: 重连次数
- `reconnect`: 手动重连方法

#### useSocketMessage

```typescript
function useSocketMessage<T>(
  config: UseSocketConfig,
  messageHandler: (data: T) => void
): UseSocketReturn
```

专门用于监听特定类型消息的简化Hook。

#### useSocketStatus

```typescript
function useSocketStatus(config: UseSocketConfig): {
  status: ConnectionStatus;
  isConnected: boolean;
  isConnecting: boolean;
  isReconnecting: boolean;
  isDisconnected: boolean;
  hasError: boolean;
}
```

专门用于监听连接状态的简化Hook。

### 类型定义

#### ConnectionStatus

```typescript
enum ConnectionStatus {
  CONNECTING = 'connecting',
  CONNECTED = 'connected',
  DISCONNECTED = 'disconnected',
  RECONNECTING = 'reconnecting',
  ERROR = 'error'
}
```

#### WebSocketConfig

```typescript
interface WebSocketConfig {
  url: string;                    // WebSocket服务器URL
  protocols?: string | string[];  // 子协议
  reconnectInterval?: number;     // 重连间隔（默认3000ms）
  maxReconnectAttempts?: number;  // 最大重连次数（默认5次）
  heartbeatInterval?: number;     // 心跳间隔（默认30000ms）
  debug?: boolean;               // 调试模式（默认false）
}
```

#### UseSocketConfig

```typescript
interface UseSocketConfig extends WebSocketConfig {
  autoConnect?: boolean;          // 是否自动连接（默认true）
  reconnectOnMount?: boolean;     // 组件挂载时是否重连（默认true）
}
```

#### WebSocketEvents

```typescript
interface WebSocketEvents {
  open: () => void;                                    // 连接打开
  message: (data: string | ArrayBuffer | Blob) => void; // 收到消息
  close: (event: CloseEvent) => void;                  // 连接关闭
  error: (error: Event) => void;                       // 连接错误
  statusChange: (status: ConnectionStatus) => void;    // 状态变化
}
```

## 使用示例

### 聊天应用

```tsx
import React, { useState, useEffect } from 'react';
import { useSocket } from '@ichaingo/socket';

interface Message {
  id: string;
  user: string;
  content: string;
  timestamp: number;
}

function ChatApp() {
  const [messages, setMessages] = useState<Message[]>([]);
  const [inputMessage, setInputMessage] = useState('');
  const [username, setUsername] = useState('');

  const socket = useSocket({
    url: 'ws://localhost:8080/chat',
    debug: true,
    autoConnect: true
  });

  useEffect(() => {
    socket.on('message', (data) => {
      if (typeof data === 'string') {
        try {
          const message = JSON.parse(data) as Message;
          setMessages(prev => [...prev, message]);
        } catch (err) {
          console.error('Failed to parse message:', err);
        }
      }
    });

    return () => {
      socket.off('message');
    };
  }, [socket]);

  const sendMessage = () => {
    if (inputMessage.trim() && username.trim()) {
      const message: Message = {
        id: Date.now().toString(),
        user: username,
        content: inputMessage,
        timestamp: Date.now()
      };
      
      socket.sendJSON(message);
      setInputMessage('');
    }
  };

  return (
    <div>
      <div>连接状态: {socket.status}</div>
      
      <div>
        <input
          value={username}
          onChange={(e) => setUsername(e.target.value)}
          placeholder="用户名"
        />
        <input
          value={inputMessage}
          onChange={(e) => setInputMessage(e.target.value)}
          placeholder="输入消息"
          onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
        />
        <button onClick={sendMessage} disabled={!socket.isConnected}>
          发送
        </button>
      </div>

      <div>
        {messages.map((message) => (
          <div key={message.id}>
            <strong>{message.user}:</strong> {message.content}
            <small> ({new Date(message.timestamp).toLocaleTimeString()})</small>
          </div>
        ))}
      </div>
    </div>
  );
}
```

### 实时通知系统

```tsx
import React, { useState } from 'react';
import { useSocketMessage } from '@ichaingo/socket';

interface Notification {
  id: string;
  type: 'info' | 'warning' | 'error';
  title: string;
  content: string;
  timestamp: number;
}

function NotificationSystem() {
  const [notifications, setNotifications] = useState<Notification[]>([]);

  const socket = useSocketMessage<Notification>({
    url: 'ws://localhost:8080/notifications',
    debug: true,
    autoConnect: true
  }, (notification) => {
    setNotifications(prev => [notification, ...prev]);
  });

  const clearNotifications = () => {
    setNotifications([]);
  };

  return (
    <div>
      <div>连接状态: {socket.status}</div>
      <button onClick={clearNotifications}>清空通知</button>
      
      <div>
        {notifications.map((notification) => (
          <div
            key={notification.id}
            style={{
              padding: '10px',
              margin: '5px 0',
              border: '1px solid #ccc',
              borderRadius: '4px',
              backgroundColor: notification.type === 'error' ? '#ffebee' : 
                              notification.type === 'warning' ? '#fff3e0' : '#e3f2fd'
            }}
          >
            <strong>{notification.title}</strong>
            <div>{notification.content}</div>
            <small>{new Date(notification.timestamp).toLocaleString()}</small>
          </div>
        ))}
      </div>
    </div>
  );
}
```

## 构建

```bash
nx build socket
```

## 测试

```bash
nx test socket
```

## 许可证

MIT