npm package: @oichat/server-sdk
Description: OiChat Server SDK — Server-side SDK for token issuance, room management, and system messaging
Latest version: 0.1.1

<p align="center">
  <img src="https://oichatapi.com/og-image.png" alt="OiChat" width="100%" />
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/@oichat/server-sdk"><img src="https://img.shields.io/npm/v/@oichat/server-sdk?color=blue" alt="npm version" /></a>
  <a href="https://www.npmjs.com/package/@oichat/server-sdk"><img src="https://img.shields.io/npm/dm/@oichat/server-sdk" alt="npm downloads" /></a>
  <a href="https://github.com/oichatapi/oichat-samples/tree/main/react-client"><img src="https://img.shields.io/badge/sample-Node.js-339933?logo=nodedotjs" alt="Sample" /></a>
  <a href="https://oichatapi.com"><img src="https://img.shields.io/badge/docs-oichatapi.com-blue" alt="Docs" /></a>
  <a href="LICENSE"><img src="https://img.shields.io/npm/l/@oichat/server-sdk" alt="License" /></a>
</p>

# @oichat/server-sdk

OiChat Server SDK for Node.js — JWT token issuance, room management, and system messaging from your backend server.

> **[한국어](#한국어)** | [English](#installation)

## Installation

```bash
npm install @oichat/server-sdk
# or
yarn add @oichat/server-sdk
```

**Requirements**: Node.js 18+ (uses native `fetch`)

## Quick Start

```typescript
import { OiChat } from "@oichat/server-sdk";

const oichat = new OiChat({
  apiKey: "ak_live_xxxxxxxxxxxx",
  secretKey: "sk_xxxxxxxxxxxx",
  projectId: "proj_xxxxxxxxxxxx",
});

// 1. Issue JWT token for a user
const { token, expires_at } = await oichat.auth.createToken({
  user_id: "user-123",
  user_name: "John Doe",
});

// 2. Create a chat room
const room = await oichat.rooms.create({
  type: "group",
  name: "Order #1234 Support",
  participants: ["user-123", "agent-1"],
});

// 3. Send a system message
await oichat.messages.send({
  room_id: room.room_id,
  sender_id: "system",
  content: "Your order has been confirmed.",
  content_type: "system",
});
```

## Configuration

```typescript
const oichat = new OiChat({
  apiKey: "ak_live_xxxxxxxxxxxx", // Required
  secretKey: "sk_xxxxxxxxxxxx", // Required
  projectId: "proj_xxxxxxxxxxxx", // Required
  baseUrl: "https://api.oichatapi.com", // Optional (default)
  timeout: 10000, // Optional: request timeout in ms (default: 10000)
  maxRetries: 2, // Optional: retry count for 5xx/network errors (default: 2)
});
```

## API Reference

### Auth

```typescript
// Issue JWT token (24h TTL for server mode)
const { token, expires_at } = await oichat.auth.createToken({
  user_id: "user-123", // Required
  user_name: "John Doe", // Optional
  user_info: {
    // Optional
    avatar_url: "https://...",
    nickname: "Johnny",
    badge: "VIP",
    custom: { tier: "gold" },
  },
  channels: [], // Optional: additional channels to subscribe
  role: "user", // Optional: 'user' | 'agent'
});

// Refresh expired token
const { token: newToken } = await oichat.auth.refreshToken({
  token: "expired-jwt...",
});
```

### Rooms

```typescript
// Create room
const room = await oichat.rooms.create({
  type: "direct", // 'direct' | 'group'
  name: "Chat Room", // Optional
  participants: ["user-1", "user-2"], // Required (2-500)
  metadata: { order_id: "1234" }, // Optional
});

// List rooms for a user (cursor pagination)
const { data, next_cursor, has_more } = await oichat.rooms.list({
  user_id: "user-1",
  limit: 20, // Optional (1-100, default: 20)
  cursor: undefined, // Optional
});

// Get room details
const room = await oichat.rooms.get("room-abc");

// Update room
await oichat.rooms.update("room-abc", {
  name: "New Name",
  metadata: { updated: true },
  status: "resolved", // 'open' | 'resolved'
});

// Delete room (soft delete)
await oichat.rooms.delete("room-abc");

// Add participant
await oichat.rooms.addParticipant("room-abc", { user_id: "user-3" });

// Remove participant
await oichat.rooms.removeParticipant("room-abc", "user-3");

// Leave room (auto-destroys if 0 participants remain)
const result = await oichat.rooms.leave("room-abc", { user_id: "user-1" });
// result.destroyed === true if room was destroyed
```

### Messages

```typescript
// Send message (system message, bot response, etc.)
const message = await oichat.messages.send({
  room_id: "room-abc",
  sender_id: "system",
  content: "Transaction completed.",
  content_type: "system", // 'text' | 'image' | 'file' | 'system' | 'custom'
  metadata: { order_id: "1234" },
});
```

## Idempotency

POST requests automatically include an `Idempotency-Key` header to prevent duplicate operations during retries. You can also provide your own:

```typescript
await oichat.rooms.create(
  { type: "group", participants: ["user-1", "user-2"] },
  { idempotencyKey: "order-1234-room" },
);
```

## Error Handling

```typescript
import {
  OiChatApiError,
  OiChatServerError,
  OiChatNetworkError,
} from "@oichat/server-sdk";

try {
  await oichat.rooms.get("nonexistent");
} catch (error) {
  if (error instanceof OiChatApiError) {
    // 4xx: client error (bad request, not found, forbidden)
    console.error(error.statusCode, error.errorCode, error.message);
  } else if (error instanceof OiChatServerError) {
    // 5xx: server error (retries exhausted)
    console.error(error.statusCode, error.message);
  } else if (error instanceof OiChatNetworkError) {
    // Network failure or timeout
    console.error(error.message, error.cause);
  }
}
```

## TypeScript Types

All request/response types are exported for use in your code:

```typescript
import {
  OiChat,
  type Room,
  type TokenResponse,
  type SendMessageParams,
} from "@oichat/server-sdk";

async function createSupportRoom(orderId: string): Promise<Room> {
  return oichat.rooms.create({
    type: "group",
    name: `Order #${orderId}`,
    participants: ["customer", "support-agent"],
  });
}
```

## Links

- [Documentation](https://oichatapi.com) — Full guides and API reference
- [Sample: React + Next.js](https://github.com/oichatapi/oichat-samples/tree/main/react-client) — Complete working example with backend integration
- [Client SDK (@oichat/sdk)](https://www.npmjs.com/package/@oichat/sdk) — Frontend chat SDK
- [UI Components (@oichat/ui-react)](https://www.npmjs.com/package/@oichat/ui-react) — Pre-built chat widgets
- [Java Server SDK](https://central.sonatype.com/artifact/com.oichatapi/server-sdk) — For Spring Boot / Java backends

---

## 한국어

Node.js용 OiChat 서버 SDK — 백엔드에서 JWT 토큰 발급, 채팅방 관리, 시스템 메시지 전송을 처리합니다.

### 설치

```bash
npm install @oichat/server-sdk
# 또는
yarn add @oichat/server-sdk
```

**요구사항**: Node.js 18+ (네이티브 `fetch` 사용)

### 빠른 시작

```typescript
import { OiChat } from "@oichat/server-sdk";

const oichat = new OiChat({
  apiKey: "ak_live_xxxxxxxxxxxx",
  secretKey: "sk_xxxxxxxxxxxx",
  projectId: "proj_xxxxxxxxxxxx",
});

// 1. 사용자 JWT 토큰 발급
const { token, expires_at } = await oichat.auth.createToken({
  user_id: "user-123",
  user_name: "홍길동",
});

// 2. 채팅방 생성
const room = await oichat.rooms.create({
  type: "group",
  name: "주문 #1234 상담",
  participants: ["user-123", "agent-1"],
});

// 3. 시스템 메시지 전송
await oichat.messages.send({
  room_id: room.room_id,
  sender_id: "system",
  content: "주문이 확인되었습니다.",
  content_type: "system",
});
```

### 주요 기능

| 기능        | 설명                                    |
| ----------- | --------------------------------------- |
| 토큰 발급   | JWT 토큰 생성/갱신 (24시간 TTL)         |
| 채팅방 관리 | 생성, 조회, 수정, 삭제, 참여자 관리     |
| 메시지 전송 | 시스템 메시지, 봇 응답 등               |
| 멱등성      | 자동 Idempotency-Key 헤더               |
| 에러 처리   | 타입별 예외 클래스 (4xx, 5xx, 네트워크) |
| 자동 재시도 | 5xx/네트워크 오류 시 자동 재시도        |

### 관련 링크

- [공식 문서](https://oichatapi.com) — 가이드 및 API 레퍼런스
- [샘플: React + Next.js](https://github.com/oichatapi/oichat-samples/tree/main/react-client) — 백엔드 연동 전체 예제
- [클라이언트 SDK (@oichat/sdk)](https://www.npmjs.com/package/@oichat/sdk) — 프론트엔드 채팅 SDK
- [UI 컴포넌트 (@oichat/ui-react)](https://www.npmjs.com/package/@oichat/ui-react) — 즉시 사용 가능한 채팅 위젯
- [Java 서버 SDK](https://central.sonatype.com/artifact/com.oichatapi/server-sdk) — Spring Boot / Java 백엔드용

## License

MIT