mirror of
https://github.com/xtr-dev/rondevu-client.git
synced 2025-12-09 18:33:25 +00:00
Initial commit: Rondevu TypeScript client
TypeScript client library for Rondevu peer signaling and discovery server. Features: - Fully typed API with TypeScript definitions - Support for all Rondevu server endpoints - Configurable base URL for any server instance - Browser and Node.js compatible - Comprehensive documentation and examples - Type-safe request/response handling 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
|
*.tsbuildinfo
|
||||||
6
.npmignore
Normal file
6
.npmignore
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
src/
|
||||||
|
tsconfig.json
|
||||||
|
*.tsbuildinfo
|
||||||
|
node_modules/
|
||||||
|
.DS_Store
|
||||||
|
*.log
|
||||||
234
README.md
Normal file
234
README.md
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
# @rondevu/client
|
||||||
|
|
||||||
|
TypeScript client for interacting with the Rondevu peer signaling and discovery server. Provides a simple, type-safe API for WebRTC peer discovery and connection establishment.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @rondevu/client
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Basic Setup
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { RondevuClient } from '@rondevu/client';
|
||||||
|
|
||||||
|
const client = new RondevuClient({
|
||||||
|
baseUrl: 'https://rondevu.example.com',
|
||||||
|
// Optional: custom origin for session isolation
|
||||||
|
origin: 'https://myapp.com'
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Peer Discovery Flow
|
||||||
|
|
||||||
|
#### 1. List Available Topics
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Get all topics with peer counts
|
||||||
|
const { topics, pagination } = await client.listTopics();
|
||||||
|
|
||||||
|
topics.forEach(topic => {
|
||||||
|
console.log(`${topic.topic}: ${topic.count} peers available`);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Create an Offer (Peer A)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Announce availability in a topic
|
||||||
|
const { code } = await client.createOffer('my-room', {
|
||||||
|
info: 'peer-A-unique-id',
|
||||||
|
offer: webrtcOfferData
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('Session code:', code);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Discover Peers (Peer B)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Find available peers in a topic
|
||||||
|
const { sessions } = await client.listSessions('my-room');
|
||||||
|
|
||||||
|
// Filter out your own sessions
|
||||||
|
const otherPeers = sessions.filter(s => s.info !== 'my-peer-id');
|
||||||
|
|
||||||
|
if (otherPeers.length > 0) {
|
||||||
|
const peer = otherPeers[0];
|
||||||
|
console.log('Found peer:', peer.info);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Send Answer (Peer B)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Connect to a peer by answering their offer
|
||||||
|
await client.sendAnswer({
|
||||||
|
code: peer.code,
|
||||||
|
answer: webrtcAnswerData,
|
||||||
|
side: 'answerer'
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5. Poll for Data (Both Peers)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Offerer polls for answer
|
||||||
|
const offererData = await client.poll(code, 'offerer');
|
||||||
|
if (offererData.answer) {
|
||||||
|
console.log('Received answer from peer');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Answerer polls for offer details
|
||||||
|
const answererData = await client.poll(code, 'answerer');
|
||||||
|
console.log('Offer candidates:', answererData.offerCandidates);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 6. Exchange ICE Candidates
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Send additional signaling data
|
||||||
|
await client.sendAnswer({
|
||||||
|
code: sessionCode,
|
||||||
|
candidate: iceCandidate,
|
||||||
|
side: 'offerer' // or 'answerer'
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Health Check
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const health = await client.health();
|
||||||
|
console.log('Server status:', health.status);
|
||||||
|
console.log('Timestamp:', health.timestamp);
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
### `RondevuClient`
|
||||||
|
|
||||||
|
#### Constructor
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
new RondevuClient(options: RondevuClientOptions)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Options:**
|
||||||
|
- `baseUrl` (string, required): Base URL of the Rondevu server
|
||||||
|
- `origin` (string, optional): Origin header for session isolation (defaults to baseUrl origin)
|
||||||
|
- `fetch` (function, optional): Custom fetch implementation (for Node.js)
|
||||||
|
|
||||||
|
#### Methods
|
||||||
|
|
||||||
|
##### `listTopics(page?, limit?)`
|
||||||
|
|
||||||
|
Lists all topics with peer counts.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `page` (number, optional): Page number, default 1
|
||||||
|
- `limit` (number, optional): Results per page, default 100, max 1000
|
||||||
|
|
||||||
|
**Returns:** `Promise<ListTopicsResponse>`
|
||||||
|
|
||||||
|
##### `listSessions(topic)`
|
||||||
|
|
||||||
|
Discovers available peers for a given topic.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `topic` (string): Topic identifier
|
||||||
|
|
||||||
|
**Returns:** `Promise<ListSessionsResponse>`
|
||||||
|
|
||||||
|
##### `createOffer(topic, request)`
|
||||||
|
|
||||||
|
Announces peer availability and creates a new session.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `topic` (string): Topic identifier (max 256 characters)
|
||||||
|
- `request` (CreateOfferRequest):
|
||||||
|
- `info` (string): Peer identifier/metadata (max 1024 characters)
|
||||||
|
- `offer` (string): WebRTC signaling data
|
||||||
|
|
||||||
|
**Returns:** `Promise<CreateOfferResponse>`
|
||||||
|
|
||||||
|
##### `sendAnswer(request)`
|
||||||
|
|
||||||
|
Sends an answer or candidate to an existing session.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `request` (AnswerRequest):
|
||||||
|
- `code` (string): Session UUID
|
||||||
|
- `answer` (string, optional): Answer signaling data
|
||||||
|
- `candidate` (string, optional): ICE candidate data
|
||||||
|
- `side` ('offerer' | 'answerer'): Which peer is sending
|
||||||
|
|
||||||
|
**Returns:** `Promise<AnswerResponse>`
|
||||||
|
|
||||||
|
##### `poll(code, side)`
|
||||||
|
|
||||||
|
Polls for session data from the other peer.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
- `code` (string): Session UUID
|
||||||
|
- `side` ('offerer' | 'answerer'): Which side is polling
|
||||||
|
|
||||||
|
**Returns:** `Promise<PollOffererResponse | PollAnswererResponse>`
|
||||||
|
|
||||||
|
##### `health()`
|
||||||
|
|
||||||
|
Checks server health.
|
||||||
|
|
||||||
|
**Returns:** `Promise<HealthResponse>`
|
||||||
|
|
||||||
|
## TypeScript Types
|
||||||
|
|
||||||
|
All types are exported from the main package:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import {
|
||||||
|
RondevuClient,
|
||||||
|
Session,
|
||||||
|
TopicInfo,
|
||||||
|
CreateOfferRequest,
|
||||||
|
AnswerRequest,
|
||||||
|
PollRequest,
|
||||||
|
Side,
|
||||||
|
// ... and more
|
||||||
|
} from '@rondevu/client';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Node.js Usage
|
||||||
|
|
||||||
|
For Node.js environments (v18+), the built-in fetch is used automatically. For older Node.js versions, provide a fetch implementation:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import fetch from 'node-fetch';
|
||||||
|
import { RondevuClient } from '@rondevu/client';
|
||||||
|
|
||||||
|
const client = new RondevuClient({
|
||||||
|
baseUrl: 'https://rondevu.example.com',
|
||||||
|
fetch: fetch as any
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
All API methods throw errors with descriptive messages:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
try {
|
||||||
|
await client.createOffer('my-room', {
|
||||||
|
info: 'peer-id',
|
||||||
|
offer: data
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to create offer:', error.message);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
28
package.json
Normal file
28
package.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "@rondevu/client",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "TypeScript client for Rondevu peer signaling and discovery server",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"typecheck": "tsc --noEmit",
|
||||||
|
"prepublishOnly": "npm run build"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"webrtc",
|
||||||
|
"p2p",
|
||||||
|
"signaling",
|
||||||
|
"peer-discovery",
|
||||||
|
"rondevu"
|
||||||
|
],
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"README.md"
|
||||||
|
]
|
||||||
|
}
|
||||||
223
src/client.ts
Normal file
223
src/client.ts
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
import {
|
||||||
|
RondevuClientOptions,
|
||||||
|
ListTopicsResponse,
|
||||||
|
ListSessionsResponse,
|
||||||
|
CreateOfferRequest,
|
||||||
|
CreateOfferResponse,
|
||||||
|
AnswerRequest,
|
||||||
|
AnswerResponse,
|
||||||
|
PollRequest,
|
||||||
|
PollOffererResponse,
|
||||||
|
PollAnswererResponse,
|
||||||
|
HealthResponse,
|
||||||
|
ErrorResponse,
|
||||||
|
Side,
|
||||||
|
} from './types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP client for Rondevu peer signaling and discovery server
|
||||||
|
*/
|
||||||
|
export class RondevuClient {
|
||||||
|
private readonly baseUrl: string;
|
||||||
|
private readonly origin: string;
|
||||||
|
private readonly fetchImpl: typeof fetch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Rondevu client instance
|
||||||
|
* @param options - Client configuration options
|
||||||
|
*/
|
||||||
|
constructor(options: RondevuClientOptions) {
|
||||||
|
this.baseUrl = options.baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
||||||
|
this.origin = options.origin || new URL(this.baseUrl).origin;
|
||||||
|
this.fetchImpl = options.fetch || fetch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes an HTTP request to the Rondevu server
|
||||||
|
*/
|
||||||
|
private async request<T>(
|
||||||
|
endpoint: string,
|
||||||
|
options: RequestInit = {}
|
||||||
|
): Promise<T> {
|
||||||
|
const url = `${this.baseUrl}${endpoint}`;
|
||||||
|
|
||||||
|
const headers: Record<string, string> = {
|
||||||
|
'Origin': this.origin,
|
||||||
|
...(options.headers as Record<string, string>),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (options.body) {
|
||||||
|
headers['Content-Type'] = 'application/json';
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await this.fetchImpl(url, {
|
||||||
|
...options,
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const error = data as ErrorResponse;
|
||||||
|
throw new Error(error.error || `HTTP ${response.status}: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all topics with peer counts
|
||||||
|
*
|
||||||
|
* @param page - Page number (starting from 1)
|
||||||
|
* @param limit - Results per page (max 1000)
|
||||||
|
* @returns List of topics with pagination info
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
||||||
|
* const { topics, pagination } = await client.listTopics();
|
||||||
|
* console.log(`Found ${topics.length} topics`);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
async listTopics(page = 1, limit = 100): Promise<ListTopicsResponse> {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
page: page.toString(),
|
||||||
|
limit: limit.toString(),
|
||||||
|
});
|
||||||
|
return this.request<ListTopicsResponse>(`/?${params}`, {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discovers available peers for a given topic
|
||||||
|
*
|
||||||
|
* @param topic - Topic identifier
|
||||||
|
* @returns List of available sessions
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
||||||
|
* const { sessions } = await client.listSessions('my-room');
|
||||||
|
* const otherPeers = sessions.filter(s => s.info !== myPeerId);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
async listSessions(topic: string): Promise<ListSessionsResponse> {
|
||||||
|
return this.request<ListSessionsResponse>(`/${encodeURIComponent(topic)}/sessions`, {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Announces peer availability and creates a new session
|
||||||
|
*
|
||||||
|
* @param topic - Topic identifier for grouping peers (max 256 characters)
|
||||||
|
* @param request - Offer details including peer info and signaling data
|
||||||
|
* @returns Unique session code (UUID)
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
||||||
|
* const { code } = await client.createOffer('my-room', {
|
||||||
|
* info: 'peer-123',
|
||||||
|
* offer: signalingData
|
||||||
|
* });
|
||||||
|
* console.log('Session code:', code);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
async createOffer(
|
||||||
|
topic: string,
|
||||||
|
request: CreateOfferRequest
|
||||||
|
): Promise<CreateOfferResponse> {
|
||||||
|
return this.request<CreateOfferResponse>(
|
||||||
|
`/${encodeURIComponent(topic)}/offer`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(request),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an answer or candidate to an existing session
|
||||||
|
*
|
||||||
|
* @param request - Answer details including session code and signaling data
|
||||||
|
* @returns Success confirmation
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
||||||
|
*
|
||||||
|
* // Send answer
|
||||||
|
* await client.sendAnswer({
|
||||||
|
* code: sessionCode,
|
||||||
|
* answer: answerData,
|
||||||
|
* side: 'answerer'
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // Send candidate
|
||||||
|
* await client.sendAnswer({
|
||||||
|
* code: sessionCode,
|
||||||
|
* candidate: candidateData,
|
||||||
|
* side: 'offerer'
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
async sendAnswer(request: AnswerRequest): Promise<AnswerResponse> {
|
||||||
|
return this.request<AnswerResponse>('/answer', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(request),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Polls for session data from the other peer
|
||||||
|
*
|
||||||
|
* @param code - Session UUID
|
||||||
|
* @param side - Which side is polling ('offerer' or 'answerer')
|
||||||
|
* @returns Session data including offers, answers, and candidates
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
||||||
|
*
|
||||||
|
* // Offerer polls for answer
|
||||||
|
* const offererData = await client.poll(sessionCode, 'offerer');
|
||||||
|
* if (offererData.answer) {
|
||||||
|
* console.log('Received answer:', offererData.answer);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // Answerer polls for offer
|
||||||
|
* const answererData = await client.poll(sessionCode, 'answerer');
|
||||||
|
* console.log('Received offer:', answererData.offer);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
async poll(
|
||||||
|
code: string,
|
||||||
|
side: Side
|
||||||
|
): Promise<PollOffererResponse | PollAnswererResponse> {
|
||||||
|
const request: PollRequest = { code, side };
|
||||||
|
return this.request<PollOffererResponse | PollAnswererResponse>('/poll', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(request),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks server health
|
||||||
|
*
|
||||||
|
* @returns Health status and timestamp
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* const client = new RondevuClient({ baseUrl: 'https://example.com' });
|
||||||
|
* const health = await client.health();
|
||||||
|
* console.log('Server status:', health.status);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
async health(): Promise<HealthResponse> {
|
||||||
|
return this.request<HealthResponse>('/health', {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/index.ts
Normal file
31
src/index.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* @rondevu/client - TypeScript client for Rondevu peer signaling server
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* import { RondevuClient } from '@rondevu/client';
|
||||||
|
*
|
||||||
|
* const client = new RondevuClient({
|
||||||
|
* baseUrl: 'https://rondevu.example.com'
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // Create an offer
|
||||||
|
* const { code } = await client.createOffer('my-room', {
|
||||||
|
* info: 'peer-123',
|
||||||
|
* offer: signalingData
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // Discover peers
|
||||||
|
* const { sessions } = await client.listSessions('my-room');
|
||||||
|
*
|
||||||
|
* // Send answer
|
||||||
|
* await client.sendAnswer({
|
||||||
|
* code: sessions[0].code,
|
||||||
|
* answer: answerData,
|
||||||
|
* side: 'answerer'
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
|
||||||
|
export { RondevuClient } from './client';
|
||||||
|
export * from './types';
|
||||||
162
src/types.ts
Normal file
162
src/types.ts
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
/**
|
||||||
|
* Session side - identifies which peer in a connection
|
||||||
|
*/
|
||||||
|
export type Side = 'offerer' | 'answerer';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session information returned from discovery endpoints
|
||||||
|
*/
|
||||||
|
export interface Session {
|
||||||
|
/** Unique session identifier (UUID) */
|
||||||
|
code: string;
|
||||||
|
/** Peer identifier/metadata */
|
||||||
|
info: string;
|
||||||
|
/** Signaling data for peer connection */
|
||||||
|
offer: string;
|
||||||
|
/** Additional signaling data from offerer */
|
||||||
|
offerCandidates: string[];
|
||||||
|
/** Unix timestamp when session was created */
|
||||||
|
createdAt: number;
|
||||||
|
/** Unix timestamp when session expires */
|
||||||
|
expiresAt: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Topic information with peer count
|
||||||
|
*/
|
||||||
|
export interface TopicInfo {
|
||||||
|
/** Topic identifier */
|
||||||
|
topic: string;
|
||||||
|
/** Number of available peers in this topic */
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pagination information
|
||||||
|
*/
|
||||||
|
export interface Pagination {
|
||||||
|
/** Current page number */
|
||||||
|
page: number;
|
||||||
|
/** Results per page */
|
||||||
|
limit: number;
|
||||||
|
/** Total number of results */
|
||||||
|
total: number;
|
||||||
|
/** Whether there are more results available */
|
||||||
|
hasMore: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from GET / - list all topics
|
||||||
|
*/
|
||||||
|
export interface ListTopicsResponse {
|
||||||
|
topics: TopicInfo[];
|
||||||
|
pagination: Pagination;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from GET /:topic/sessions - list sessions in a topic
|
||||||
|
*/
|
||||||
|
export interface ListSessionsResponse {
|
||||||
|
sessions: Session[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request body for POST /:topic/offer
|
||||||
|
*/
|
||||||
|
export interface CreateOfferRequest {
|
||||||
|
/** Peer identifier/metadata (max 1024 characters) */
|
||||||
|
info: string;
|
||||||
|
/** Signaling data for peer connection */
|
||||||
|
offer: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from POST /:topic/offer
|
||||||
|
*/
|
||||||
|
export interface CreateOfferResponse {
|
||||||
|
/** Unique session identifier (UUID) */
|
||||||
|
code: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request body for POST /answer
|
||||||
|
*/
|
||||||
|
export interface AnswerRequest {
|
||||||
|
/** Session UUID from the offer */
|
||||||
|
code: string;
|
||||||
|
/** Response signaling data (required if candidate not provided) */
|
||||||
|
answer?: string;
|
||||||
|
/** Additional signaling data (required if answer not provided) */
|
||||||
|
candidate?: string;
|
||||||
|
/** Which peer is sending the data */
|
||||||
|
side: Side;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from POST /answer
|
||||||
|
*/
|
||||||
|
export interface AnswerResponse {
|
||||||
|
success: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request body for POST /poll
|
||||||
|
*/
|
||||||
|
export interface PollRequest {
|
||||||
|
/** Session UUID */
|
||||||
|
code: string;
|
||||||
|
/** Which side is polling */
|
||||||
|
side: Side;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from POST /poll when side=offerer
|
||||||
|
*/
|
||||||
|
export interface PollOffererResponse {
|
||||||
|
/** Answer from answerer (null if not yet received) */
|
||||||
|
answer: string | null;
|
||||||
|
/** Additional signaling data from answerer */
|
||||||
|
answerCandidates: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from POST /poll when side=answerer
|
||||||
|
*/
|
||||||
|
export interface PollAnswererResponse {
|
||||||
|
/** Offer from offerer */
|
||||||
|
offer: string;
|
||||||
|
/** Additional signaling data from offerer */
|
||||||
|
offerCandidates: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from POST /poll (union type)
|
||||||
|
*/
|
||||||
|
export type PollResponse = PollOffererResponse | PollAnswererResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from GET /health
|
||||||
|
*/
|
||||||
|
export interface HealthResponse {
|
||||||
|
status: 'ok';
|
||||||
|
timestamp: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error response structure
|
||||||
|
*/
|
||||||
|
export interface ErrorResponse {
|
||||||
|
error: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client configuration options
|
||||||
|
*/
|
||||||
|
export interface RondevuClientOptions {
|
||||||
|
/** Base URL of the Rondevu server (e.g., 'https://example.com') */
|
||||||
|
baseUrl: string;
|
||||||
|
/** Origin header value for session isolation (defaults to baseUrl origin) */
|
||||||
|
origin?: string;
|
||||||
|
/** Optional fetch implementation (for Node.js environments) */
|
||||||
|
fetch?: typeof fetch;
|
||||||
|
}
|
||||||
18
tsconfig.json
Normal file
18
tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"module": "commonjs",
|
||||||
|
"lib": ["ES2020", "DOM"],
|
||||||
|
"declaration": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"rootDir": "./src",
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user