mirror of
https://github.com/xtr-dev/rondevu-client.git
synced 2025-12-09 18:33:25 +00:00
Update README with secret field documentation
- Document secret parameter in offer creation examples - Add Protected Offers section with detailed usage - Update API reference for create() and answer() methods - Show hasSecret flag in discovery responses 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
60
README.md
60
README.md
@@ -16,6 +16,7 @@ TypeScript/JavaScript client for Rondevu, providing topic-based peer discovery,
|
||||
|
||||
- **Topic-Based Discovery**: Find peers by topics (e.g., torrent infohashes)
|
||||
- **Stateless Authentication**: No server-side sessions, portable credentials
|
||||
- **Protected Connections**: Optional secret-protected offers for access control
|
||||
- **Bloom Filters**: Efficient peer exclusion for repeated discoveries
|
||||
- **Multi-Offer Management**: Create and manage multiple offers per peer
|
||||
- **Complete WebRTC Signaling**: Full offer/answer and ICE candidate exchange
|
||||
@@ -68,7 +69,8 @@ peer.on('datachannel', (channel) => {
|
||||
// Create offer and advertise on topics
|
||||
const offerId = await peer.createOffer({
|
||||
topics: ['my-app', 'room-123'],
|
||||
ttl: 300000 // 5 minutes
|
||||
ttl: 300000, // 5 minutes
|
||||
secret: 'my-secret-password' // Optional: protect offer (max 128 chars)
|
||||
});
|
||||
|
||||
console.log('Offer created:', offerId);
|
||||
@@ -121,11 +123,50 @@ if (offers.length > 0) {
|
||||
|
||||
// Answer the offer
|
||||
await peer.answer(offer.id, offer.sdp, {
|
||||
topics: offer.topics
|
||||
topics: offer.topics,
|
||||
secret: 'my-secret-password' // Required if offer.hasSecret is true
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Protected Offers
|
||||
|
||||
You can protect offers with a secret to control who can answer them. This is useful for private rooms or invite-only connections.
|
||||
|
||||
### Creating a Protected Offer
|
||||
|
||||
```typescript
|
||||
const offerId = await peer.createOffer({
|
||||
topics: ['private-room'],
|
||||
secret: 'my-secret-password' // Max 128 characters
|
||||
});
|
||||
|
||||
// Share the secret with authorized peers through a secure channel
|
||||
```
|
||||
|
||||
### Answering a Protected Offer
|
||||
|
||||
```typescript
|
||||
const offers = await client.offers.findByTopic('private-room');
|
||||
|
||||
// Check if offer requires a secret
|
||||
if (offers[0].hasSecret) {
|
||||
console.log('This offer requires a secret');
|
||||
}
|
||||
|
||||
// Provide the secret when answering
|
||||
await peer.answer(offers[0].id, offers[0].sdp, {
|
||||
topics: offers[0].topics,
|
||||
secret: 'my-secret-password' // Must match the offer's secret
|
||||
});
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- The actual secret is never exposed in public API responses - only a `hasSecret` boolean flag
|
||||
- Answerers must provide the correct secret, or the answer will be rejected
|
||||
- Secrets are limited to 128 characters
|
||||
- Use this for access control, not for cryptographic security (use end-to-end encryption for that)
|
||||
|
||||
## Connection Lifecycle
|
||||
|
||||
The `RondevuPeer` uses a state machine for connection management:
|
||||
@@ -368,7 +409,8 @@ localStorage.setItem('rondevu-creds', JSON.stringify(creds));
|
||||
const offers = await client.offers.create([{
|
||||
sdp: 'v=0...', // Your WebRTC offer SDP
|
||||
topics: ['movie-xyz', 'hd-content'],
|
||||
ttl: 300000 // 5 minutes
|
||||
ttl: 300000, // 5 minutes
|
||||
secret: 'my-secret-password' // Optional: protect offer (max 128 chars)
|
||||
}]);
|
||||
|
||||
// Discover peers by topic
|
||||
@@ -433,7 +475,8 @@ const offers = await client.offers.create([
|
||||
{
|
||||
sdp: 'v=0...',
|
||||
topics: ['topic-1', 'topic-2'],
|
||||
ttl: 300000 // optional, default 5 minutes
|
||||
ttl: 300000, // optional, default 5 minutes
|
||||
secret: 'my-secret-password' // optional, max 128 chars
|
||||
}
|
||||
]);
|
||||
```
|
||||
@@ -462,13 +505,18 @@ Delete a specific offer.
|
||||
await client.offers.delete(offerId);
|
||||
```
|
||||
|
||||
#### `client.offers.answer(offerId, sdp)`
|
||||
#### `client.offers.answer(offerId, sdp, secret?)`
|
||||
Answer an offer (locks it to answerer).
|
||||
|
||||
```typescript
|
||||
await client.offers.answer(offerId, answerSdp);
|
||||
await client.offers.answer(offerId, answerSdp, 'my-secret-password');
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `offerId`: The offer ID to answer
|
||||
- `sdp`: The WebRTC answer SDP
|
||||
- `secret` (optional): Required if the offer has `hasSecret: true`
|
||||
|
||||
#### `client.offers.getAnswers()`
|
||||
Poll for answers to your offers.
|
||||
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@xtr-dev/rondevu-client",
|
||||
"version": "0.7.3",
|
||||
"version": "0.7.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@xtr-dev/rondevu-client",
|
||||
"version": "0.7.3",
|
||||
"version": "0.7.6",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@xtr-dev/rondevu-client": "^0.5.1"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@xtr-dev/rondevu-client",
|
||||
"version": "0.7.5",
|
||||
"version": "0.7.6",
|
||||
"description": "TypeScript client for Rondevu topic-based peer discovery and signaling server",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface CreateOfferRequest {
|
||||
sdp: string;
|
||||
topics: string[];
|
||||
ttl?: number;
|
||||
secret?: string;
|
||||
}
|
||||
|
||||
export interface Offer {
|
||||
@@ -18,6 +19,8 @@ export interface Offer {
|
||||
createdAt?: number;
|
||||
expiresAt: number;
|
||||
lastSeen: number;
|
||||
secret?: string;
|
||||
hasSecret?: boolean;
|
||||
answererPeerId?: string;
|
||||
answerSdp?: string;
|
||||
answeredAt?: number;
|
||||
@@ -221,14 +224,14 @@ export class RondevuOffers {
|
||||
/**
|
||||
* Answer an offer
|
||||
*/
|
||||
async answer(offerId: string, sdp: string): Promise<void> {
|
||||
async answer(offerId: string, sdp: string, secret?: string): Promise<void> {
|
||||
const response = await this.fetchFn(`${this.baseUrl}/offers/${encodeURIComponent(offerId)}/answer`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: RondevuAuth.createAuthHeader(this.credentials),
|
||||
},
|
||||
body: JSON.stringify({ sdp }),
|
||||
body: JSON.stringify({ sdp, secret }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
|
||||
Reference in New Issue
Block a user