npm package: @isreeks/chat-sdk
Description: Socket.io chat SDK for Next.js 14 with server-side API client
Author: Zestio
Latest version: 1.0.3

# @isreeks/socket-chat-sdk

A Socket.io-based chat SDK designed for Next.js 14 applications, providing real-time chat functionality with server-side API integration for room management. This package includes client-side hooks and a context provider for managing chat rooms and messages, along with server-side utilities for secure API calls.

## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
  - [Client-Side Setup](#client-side-setup)
  - [Server-Side Setup](#server-side-setup)
- [Configuration](#configuration)
- [API Reference](#api-reference)
  - [Client-Side API](#client-side-api)
  - [Server-Side API](#server-side-api)
- [Contributing](#contributing)
- [License](#license)

## Features
- Real-time chat functionality using Socket.io.
- Client-side hooks (`useSocket`, `useChatRoom`) for managing rooms and messages.
- Server-side API client for secure room management (create, join, add participants).
- TypeScript support with type definitions.
- Integration with Next.js 14 App Router.

## Installation

Install the package via npm:

```bash
npm install @isreeks/socket-chat-sdk
```

### Peer Dependencies
Ensure the following peer dependencies are installed in your project:
- `next@^14.0.0`
- `react@^18.2.0`
- `socket.io-client@^4.7.0`

### Additional Dependencies
- `react-hot-toast@^2.4.1` (included as a dependency for notifications)

## Usage

### Client-Side Setup
Wrap your application with `SocketProvider` in your root layout or `_app` file to enable chat functionality.

#### Example: `app/layout.tsx`
```typescript
"use client";

import { SocketProvider } from '@isreeks/socket-chat-sdk';
import { Toaster } from 'react-hot-toast';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  // Replace with your actual authentication logic
  const authToken = { userId: 'your-user-id', token: 'your-auth-token' };

  return (
    <html lang="en">
      <body>
        <SocketProvider
          socketUrl={process.env.NEXT_PUBLIC_SOCKET_URL!}
          authToken={authToken}
        >
          <Toaster />
          {children}
        </SocketProvider>
      </body>
    </html>
  );
}
```

#### Example Component: `components/ChatRoom.tsx`
```typescript
"use client";

import { useSocket, useChatRoom } from '@isreeks/socket-chat-sdk';
import { useEffect, useState } from 'react';

export default function ChatRoom({ roomId, userId }) {
  const { createRoom, addParticipants, rooms } = useSocket();
  const [selectedRoomId, setSelectedRoomId] = useState(roomId);
  const { messages, joinRoom, sendMessage, setTyping } = useChatRoom(selectedRoomId);

  useEffect(() => {
    if (roomId) joinRoom(roomId);
  }, [roomId, joinRoom]);

  const handleCreateRoom = async () => {
    const newRoom = await createRoom('New Room', [userId, 'anotherUserId']);
    joinRoom(newRoom._id);
    setSelectedRoomId(newRoom._id);
  };

  const handleSend = (content) => {
    sendMessage(content, undefined, userId);
  };

  return (
    <div>
      <button onClick={handleCreateRoom}>Create Room</button>
      <ul>
        {rooms.map((room) => (
          <li key={room._id} onClick={() => joinRoom(room._id)}>
            {room.name}
          </li>
        ))}
      </ul>
      <div>
        {messages.map((msg) => (
          <p key={msg._id}>{msg.content}</p>
        ))}
      </div>
      <input onChange={() => setTyping(true, userId, 'username')} />
      <button onClick={() => handleSend('Hello!')}>Send</button>
    </div>
  );
}
```

### Server-Side Setup
Create an API route to proxy client requests to your hosted room management API securely.

#### Example: `app/api/rooms/[[...slug]]/route.ts`
```typescript
import { NextRequest, NextResponse } from 'next/server';
import { RoomsApiClient } from '@isreeks/socket-chat-sdk/server';
import { Room } from '@isreeks/socket-chat-sdk/types';

const apiClient = new RoomsApiClient(process.env.API_URL!, process.env.API_KEY!);

export async function POST(request: NextRequest, { params }: { params: { slug: string[] } }) {
  const authToken = request.headers.get('authorization')?.split('Bearer ')[1];
  if (!authToken) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });

  const slug = params.slug || [];
  const url = `/api/rooms/${slug.join('/')}`;

  try {
    if (url === '/api/rooms') {
      const { name, participants } = await request.json();
      const room = await apiClient.createRoom({ name, participants });
      return NextResponse.json(room, { status: 201 });
    }
    if (url.match(/\/api\/rooms\/[^/]+\/participants/)) {
      const roomId = slug[0];
      const { participants } = await request.json();
      const room = await apiClient.addParticipants(roomId, participants);
      return NextResponse.json(room);
    }
    return NextResponse.json({ error: 'Method not allowed' }, { status: 405 });
  } catch (error) {
    return NextResponse.json({ error: (error as Error).message || 'Internal server error' }, { status: 500 });
  }
}

export async function GET(request: NextRequest, { params }: { params: { slug: string[] } }) {
  const authToken = request.headers.get('authorization')?.split('Bearer ')[1];
  if (!authToken) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });

  const slug = params.slug || [];
  const url = `/api/rooms/${slug.join('/')}`;

  try {
    if (url.match(/\/api/rooms\/user\/[^/]+/)) {
      const userId = slug[2];
      const rooms = await apiClient.getUserRooms(userId);
      return NextResponse.json(rooms);
    }
    if (url.match(/\/api/rooms\/[^/]+/)) {
      const roomId = slug[0];
      const room = await apiClient.getRoom(roomId);
      return NextResponse.json(room);
    }
    return NextResponse.json({ error: 'Not found' }, { status: 404 });
  } catch (error) {
    return NextResponse.json({ error: (error as Error).message || 'Internal server error' }, { status: 500 });
  }
}
```

## Configuration
Add the following environment variables to your `.env.local` file:

```
NEXT_PUBLIC_SOCKET_URL=https://your-socket-server.com
API_URL=https://your-api-server.com
API_KEY=your-secret-api-key
```

- `NEXT_PUBLIC_SOCKET_URL`: The public URL of your Socket.io server.
- `API_URL`: The base URL of your hosted room management API (kept secret on the server).
- `API_KEY`: The secret API key for authenticating API requests (kept secret on the server).

## API Reference

### Client-Side API

#### SocketProvider
**Props:**
- `socketUrl` (string): URL of the Socket.io server.
- `authToken` (object): Authentication token (e.g., `{ userId: string, token?: string }`).

**Usage:** Wraps your app to provide chat context.

#### useSocket
**Returns:** Object with:
- `createRoom(name: string, participants: string[]): Promise<Room>`
- `addParticipants(roomId: string, participants: string[]): Promise<Room>`
- `getRoom(roomId: string): Promise<Room>`
- `getUserRooms(userId: string): Promise<Room[]>`
- `rooms: Room[]`

#### useChatRoom(roomId: string)
**Returns:** Object with:
- `messages: Message[]`
- `joinRoom(roomId: string): void`
- `sendMessage(content: string, replyToId?: string, userId?: string): void`
- `setTyping(isTyping: boolean, userId: string, username: string): void`

### Server-Side API

#### RoomsApiClient
**Constructor:** `new RoomsApiClient(baseUrl: string, apiKey: string)`

**Methods:**
- `createRoom({ name, participants }): Promise<Room>`
- `addParticipants(roomId: string, participants: string[]): Promise<Room>`
- `getRoom(roomId: string): Promise<Room>`
- `getUserRooms(userId: string): Promise<Room[]>`

## Contributing
1. Fork the repository.
2. Create a new branch: `git checkout -b feature-name`
3. Make your changes and commit: `git commit -m "Add feature-name"`
4. Push to the branch: `git push origin feature-name`
5. Submit a pull request.

### Development
- Install dependencies: `npm install`
- Build the package: `npm run build`
- Test locally: Use `npm link` in the package directory, then `npm link @isreeks/socket-chat-sdk` in your Next.js app.

## License
This project is licensed under the MIT License. See the LICENSE file for details.

## Notes
- **Customization:** Adjust the examples to match your authentication system (e.g., NextAuth.js) and styling preferences.
- **Documentation:** Add more details to the API reference or include a changelog if you plan multiple releases.