mirror of
https://github.com/xtr-dev/rondevu-client.git
synced 2025-12-13 04:13:25 +00:00
Simplify API: Remove explicit claiming, add Rondevu.connect(), simplify publishService
Breaking changes:
- Remove claimUsername() method - username claiming now fully implicit
- Remove initialize() method - replaced with static Rondevu.connect()
- Change publishService() parameter from serviceFqn to service (username auto-appended)
- Make constructor private - must use Rondevu.connect()
- Remove nullable types from keypair/api - always initialized after connect()
New pattern:
const rondevu = await Rondevu.connect({ apiUrl, username })
await rondevu.publishService({ service: 'chat:2.0.0', offers })
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
120
README.md
120
README.md
@@ -38,18 +38,13 @@ npm install @xtr-dev/rondevu-client
|
||||
```typescript
|
||||
import { Rondevu } from '@xtr-dev/rondevu-client'
|
||||
|
||||
// 1. Initialize (with username or anonymous)
|
||||
const rondevu = new Rondevu({
|
||||
// 1. Connect to Rondevu (generates keypair, username auto-claimed on first request)
|
||||
const rondevu = await Rondevu.connect({
|
||||
apiUrl: 'https://api.ronde.vu',
|
||||
username: 'alice' // Or omit for anonymous username
|
||||
})
|
||||
|
||||
await rondevu.initialize() // Generates keypair automatically
|
||||
|
||||
// 2. Claim username (optional - anonymous users auto-claim)
|
||||
await rondevu.claimUsername()
|
||||
|
||||
// 3. Create WebRTC offer
|
||||
// 2. Create WebRTC offer
|
||||
const pc = new RTCPeerConnection({
|
||||
iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
|
||||
})
|
||||
@@ -61,7 +56,7 @@ await pc.setLocalDescription(offer)
|
||||
|
||||
// 4. Publish service
|
||||
const service = await rondevu.publishService({
|
||||
serviceFqn: 'chat:1.0.0@alice',
|
||||
service: 'chat:1.0.0',
|
||||
offers: [{ sdp: offer.sdp }],
|
||||
ttl: 300000
|
||||
})
|
||||
@@ -120,15 +115,12 @@ dc.onopen = () => {
|
||||
```typescript
|
||||
import { Rondevu } from '@xtr-dev/rondevu-client'
|
||||
|
||||
// 1. Initialize
|
||||
const rondevu = new Rondevu({
|
||||
// 1. Connect to Rondevu
|
||||
const rondevu = await Rondevu.connect({
|
||||
apiUrl: 'https://api.ronde.vu',
|
||||
username: 'bob'
|
||||
})
|
||||
|
||||
await rondevu.initialize()
|
||||
await rondevu.claimUsername()
|
||||
|
||||
// 2. Get service offer
|
||||
const serviceData = await rondevu.getService('chat:1.0.0@alice')
|
||||
|
||||
@@ -201,11 +193,13 @@ Main class for all Rondevu operations.
|
||||
```typescript
|
||||
import { Rondevu } from '@xtr-dev/rondevu-client'
|
||||
|
||||
const rondevu = new Rondevu({
|
||||
// Create and connect to Rondevu
|
||||
const rondevu = await Rondevu.connect({
|
||||
apiUrl: string, // Signaling server URL
|
||||
username?: string, // Optional: your username (auto-generates anonymous if omitted)
|
||||
keypair?: Keypair, // Optional: reuse existing keypair
|
||||
cryptoAdapter?: CryptoAdapter // Optional: platform-specific crypto (defaults to WebCryptoAdapter)
|
||||
batching?: BatcherOptions | false // Optional: RPC batching configuration
|
||||
})
|
||||
```
|
||||
|
||||
@@ -218,7 +212,7 @@ The client supports both browser and Node.js environments using crypto adapters:
|
||||
import { Rondevu } from '@xtr-dev/rondevu-client'
|
||||
|
||||
// WebCryptoAdapter is used by default - no configuration needed
|
||||
const rondevu = new Rondevu({
|
||||
const rondevu = await Rondevu.connect({
|
||||
apiUrl: 'https://api.ronde.vu',
|
||||
username: 'alice'
|
||||
})
|
||||
@@ -228,13 +222,11 @@ const rondevu = new Rondevu({
|
||||
```typescript
|
||||
import { Rondevu, NodeCryptoAdapter } from '@xtr-dev/rondevu-client'
|
||||
|
||||
const rondevu = new Rondevu({
|
||||
const rondevu = await Rondevu.connect({
|
||||
apiUrl: 'https://api.ronde.vu',
|
||||
username: 'alice',
|
||||
cryptoAdapter: new NodeCryptoAdapter()
|
||||
})
|
||||
|
||||
await rondevu.initialize()
|
||||
```
|
||||
|
||||
**Note:** Node.js support requires:
|
||||
@@ -255,25 +247,17 @@ class CustomCryptoAdapter implements CryptoAdapter {
|
||||
randomBytes(length: number): Uint8Array { /* ... */ }
|
||||
}
|
||||
|
||||
const rondevu = new Rondevu({
|
||||
const rondevu = await Rondevu.connect({
|
||||
apiUrl: 'https://api.ronde.vu',
|
||||
cryptoAdapter: new CustomCryptoAdapter()
|
||||
})
|
||||
```
|
||||
|
||||
#### Initialization
|
||||
|
||||
```typescript
|
||||
// Initialize (generates keypair if not provided, auto-claims anonymous usernames)
|
||||
await rondevu.initialize(): Promise<void>
|
||||
```
|
||||
|
||||
#### Username Management
|
||||
|
||||
```typescript
|
||||
// Claim username with Ed25519 signature
|
||||
await rondevu.claimUsername(): Promise<void>
|
||||
Usernames are **automatically claimed** on the first authenticated request (like `publishService()`).
|
||||
|
||||
```typescript
|
||||
// Check if username is claimed (checks server)
|
||||
await rondevu.isUsernameClaimed(): Promise<boolean>
|
||||
|
||||
@@ -281,10 +265,10 @@ await rondevu.isUsernameClaimed(): Promise<boolean>
|
||||
rondevu.getUsername(): string
|
||||
|
||||
// Get public key
|
||||
rondevu.getPublicKey(): string | null
|
||||
rondevu.getPublicKey(): string
|
||||
|
||||
// Get keypair (for backup/storage)
|
||||
rondevu.getKeypair(): Keypair | null
|
||||
rondevu.getKeypair(): Keypair
|
||||
```
|
||||
|
||||
#### Service Publishing
|
||||
@@ -292,9 +276,9 @@ rondevu.getKeypair(): Keypair | null
|
||||
```typescript
|
||||
// Publish service with offers
|
||||
await rondevu.publishService({
|
||||
serviceFqn: string, // e.g., 'chat:1.0.0@alice'
|
||||
service: string, // e.g., 'chat:1.0.0' (username auto-appended)
|
||||
offers: Array<{ sdp: string }>,
|
||||
ttl?: number // Optional: milliseconds (default: 300000)
|
||||
ttl?: number // Optional: milliseconds (default: 300000)
|
||||
}): Promise<Service>
|
||||
```
|
||||
|
||||
@@ -452,13 +436,8 @@ await api.checkUsername(username: string): Promise<{
|
||||
expiresAt?: number
|
||||
}>
|
||||
|
||||
// Claim username
|
||||
await api.claimUsername(
|
||||
username: string,
|
||||
publicKey: string,
|
||||
signature: string,
|
||||
message: string
|
||||
): Promise<{ success: boolean, username: string }>
|
||||
// Note: Username claiming is now implicit - usernames are auto-claimed
|
||||
// on first authenticated request to the server
|
||||
|
||||
// ... (all other HTTP endpoints)
|
||||
```
|
||||
@@ -527,18 +506,16 @@ interface PollingConfig {
|
||||
|
||||
```typescript
|
||||
// Auto-generate anonymous username (format: anon-{timestamp}-{random})
|
||||
const rondevu = new Rondevu({
|
||||
const rondevu = await Rondevu.connect({
|
||||
apiUrl: 'https://api.ronde.vu'
|
||||
// No username provided - will generate anonymous username
|
||||
})
|
||||
|
||||
await rondevu.initialize() // Auto-claims anonymous username
|
||||
|
||||
console.log(rondevu.getUsername()) // e.g., "anon-lx2w34-a3f501"
|
||||
|
||||
// Anonymous users behave exactly like regular users
|
||||
await rondevu.publishService({
|
||||
serviceFqn: `chat:1.0.0@${rondevu.getUsername()}`,
|
||||
service: 'chat:1.0.0',
|
||||
offers: [{ sdp: offerSdp }]
|
||||
})
|
||||
```
|
||||
@@ -547,15 +524,12 @@ await rondevu.publishService({
|
||||
|
||||
```typescript
|
||||
// Save keypair and username to localStorage
|
||||
const rondevu = new Rondevu({
|
||||
const rondevu = await Rondevu.connect({
|
||||
apiUrl: 'https://api.ronde.vu',
|
||||
username: 'alice'
|
||||
})
|
||||
|
||||
await rondevu.initialize()
|
||||
await rondevu.claimUsername()
|
||||
|
||||
// Save for later
|
||||
// Save for later (username will be auto-claimed on first authenticated request)
|
||||
localStorage.setItem('rondevu-username', rondevu.getUsername())
|
||||
localStorage.setItem('rondevu-keypair', JSON.stringify(rondevu.getKeypair()))
|
||||
|
||||
@@ -563,13 +537,11 @@ localStorage.setItem('rondevu-keypair', JSON.stringify(rondevu.getKeypair()))
|
||||
const savedUsername = localStorage.getItem('rondevu-username')
|
||||
const savedKeypair = JSON.parse(localStorage.getItem('rondevu-keypair'))
|
||||
|
||||
const rondevu2 = new Rondevu({
|
||||
const rondevu2 = await Rondevu.connect({
|
||||
apiUrl: 'https://api.ronde.vu',
|
||||
username: savedUsername,
|
||||
keypair: savedKeypair
|
||||
})
|
||||
|
||||
await rondevu2.initialize() // Reuses keypair
|
||||
```
|
||||
|
||||
### Service Discovery
|
||||
@@ -603,7 +575,7 @@ for (let i = 0; i < 5; i++) {
|
||||
}
|
||||
|
||||
const service = await rondevu.publishService({
|
||||
serviceFqn: 'chat:1.0.0@alice',
|
||||
service: 'chat:1.0.0',
|
||||
offers,
|
||||
ttl: 300000
|
||||
})
|
||||
@@ -666,7 +638,45 @@ const pc = new RTCPeerConnection()
|
||||
|
||||
## Examples
|
||||
|
||||
See the [demo](https://github.com/xtr-dev/rondevu-demo) for a complete working example with React UI.
|
||||
### Node.js Service Host Example
|
||||
|
||||
You can host WebRTC services in Node.js that browser clients can connect to. See the [Node.js Host Guide](../demo/NODE_HOST_GUIDE.md) for a complete guide.
|
||||
|
||||
**Quick example:**
|
||||
|
||||
```typescript
|
||||
import { Rondevu, NodeCryptoAdapter } from '@xtr-dev/rondevu-client'
|
||||
import wrtc from 'wrtc'
|
||||
|
||||
const { RTCPeerConnection } = wrtc
|
||||
|
||||
// Initialize with Node crypto adapter
|
||||
const rondevu = await Rondevu.connect({
|
||||
apiUrl: 'https://api.ronde.vu',
|
||||
username: 'mybot',
|
||||
cryptoAdapter: new NodeCryptoAdapter()
|
||||
})
|
||||
|
||||
// Create peer connection (offerer creates data channel)
|
||||
const pc = new RTCPeerConnection(rtcConfig)
|
||||
const dc = pc.createDataChannel('chat')
|
||||
|
||||
// Publish service (username auto-claimed on first publish)
|
||||
const offer = await pc.createOffer()
|
||||
await pc.setLocalDescription(offer)
|
||||
|
||||
await rondevu.publishService({
|
||||
service: 'chat:1.0.0',
|
||||
offers: [{ sdp: offer.sdp }]
|
||||
})
|
||||
|
||||
// Browser clients can now discover and connect to chat:1.0.0@mybot
|
||||
```
|
||||
|
||||
See complete examples:
|
||||
- [Node.js Host Guide](../demo/NODE_HOST_GUIDE.md) - Full guide with complete examples
|
||||
- [test-connect.js](../demo/test-connect.js) - Working Node.js client example
|
||||
- [React Demo](https://github.com/xtr-dev/rondevu-demo) - Complete browser UI ([live](https://ronde.vu))
|
||||
|
||||
## Migration from v0.3.x
|
||||
|
||||
|
||||
28
src/api.ts
28
src/api.ts
@@ -157,7 +157,21 @@ export class RondevuAPI {
|
||||
|
||||
const results: RpcResponse[] = await response.json()
|
||||
|
||||
// Validate response is an array
|
||||
if (!Array.isArray(results)) {
|
||||
console.error('Invalid RPC batch response:', results)
|
||||
throw new Error('Server returned invalid batch response (not an array)')
|
||||
}
|
||||
|
||||
// Check response length matches request length
|
||||
if (results.length !== requests.length) {
|
||||
console.error(`Response length mismatch: expected ${requests.length}, got ${results.length}`)
|
||||
}
|
||||
|
||||
return results.map((result, i) => {
|
||||
if (!result || typeof result !== 'object') {
|
||||
throw new Error(`Invalid response at index ${i}`)
|
||||
}
|
||||
if (!result.success) {
|
||||
throw new Error(result.error || `RPC call ${i} failed`)
|
||||
}
|
||||
@@ -223,20 +237,6 @@ export class RondevuAPI {
|
||||
return result.available
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim a username
|
||||
*/
|
||||
async claimUsername(username: string, publicKey: string): Promise<void> {
|
||||
const auth = await this.generateAuth('claim', username)
|
||||
await this.rpc({
|
||||
method: 'claimUsername',
|
||||
message: auth.message,
|
||||
signature: auth.signature,
|
||||
publicKey: this.keypair.publicKey,
|
||||
params: { username, publicKey },
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current username is claimed
|
||||
*/
|
||||
|
||||
202
src/rondevu.ts
202
src/rondevu.ts
@@ -10,7 +10,7 @@ export interface RondevuOptions {
|
||||
}
|
||||
|
||||
export interface PublishServiceOptions {
|
||||
serviceFqn: string // Must include @username (e.g., "chat:1.0.0@alice")
|
||||
service: string // Service name and version (e.g., "chat:2.0.0") - username will be auto-appended
|
||||
offers: Array<{ sdp: string }>
|
||||
ttl?: number
|
||||
}
|
||||
@@ -19,7 +19,7 @@ export interface PublishServiceOptions {
|
||||
* Rondevu - Complete WebRTC signaling client
|
||||
*
|
||||
* Provides a unified API for:
|
||||
* - Username claiming with Ed25519 signatures
|
||||
* - Implicit username claiming (auto-claimed on first authenticated request)
|
||||
* - Service publishing with automatic signature generation
|
||||
* - Service discovery (direct, random, paginated)
|
||||
* - WebRTC signaling (offer/answer exchange, ICE relay)
|
||||
@@ -27,17 +27,15 @@ export interface PublishServiceOptions {
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Create Rondevu instance with username
|
||||
* const rondevu = new Rondevu({
|
||||
* // Create and initialize Rondevu instance
|
||||
* const rondevu = await Rondevu.connect({
|
||||
* apiUrl: 'https://signal.example.com',
|
||||
* username: 'alice',
|
||||
* })
|
||||
* await rondevu.initialize()
|
||||
* await rondevu.claimUsername() // Claim username before publishing
|
||||
*
|
||||
* // Publish a service
|
||||
* // Publish a service (username auto-claimed on first publish)
|
||||
* const publishedService = await rondevu.publishService({
|
||||
* serviceFqn: 'chat:1.0.0@alice',
|
||||
* service: 'chat:1.0.0',
|
||||
* offers: [{ sdp: offerSdp }],
|
||||
* ttl: 300000,
|
||||
* })
|
||||
@@ -50,120 +48,106 @@ export interface PublishServiceOptions {
|
||||
* ```
|
||||
*/
|
||||
export class Rondevu {
|
||||
private api: RondevuAPI | null = null
|
||||
private api: RondevuAPI
|
||||
private readonly apiUrl: string
|
||||
private username: string
|
||||
private keypair: Keypair | null = null
|
||||
private keypair: Keypair
|
||||
private usernameClaimed = false
|
||||
private cryptoAdapter?: CryptoAdapter
|
||||
private batchingOptions?: BatcherOptions | false
|
||||
|
||||
constructor(options: RondevuOptions) {
|
||||
this.apiUrl = options.apiUrl
|
||||
this.username = options.username || this.generateAnonymousUsername()
|
||||
this.keypair = options.keypair || null
|
||||
this.cryptoAdapter = options.cryptoAdapter
|
||||
this.batchingOptions = options.batching
|
||||
private constructor(
|
||||
apiUrl: string,
|
||||
username: string,
|
||||
keypair: Keypair,
|
||||
api: RondevuAPI,
|
||||
cryptoAdapter?: CryptoAdapter,
|
||||
batchingOptions?: BatcherOptions | false
|
||||
) {
|
||||
this.apiUrl = apiUrl
|
||||
this.username = username
|
||||
this.keypair = keypair
|
||||
this.api = api
|
||||
this.cryptoAdapter = cryptoAdapter
|
||||
this.batchingOptions = batchingOptions
|
||||
|
||||
console.log('[Rondevu] Constructor called:', {
|
||||
console.log('[Rondevu] Instance created:', {
|
||||
username: this.username,
|
||||
hasKeypair: !!this.keypair,
|
||||
publicKey: this.keypair?.publicKey,
|
||||
publicKey: this.keypair.publicKey,
|
||||
batchingEnabled: batchingOptions !== false
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and initialize a Rondevu client
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const rondevu = await Rondevu.connect({
|
||||
* apiUrl: 'https://api.ronde.vu',
|
||||
* username: 'alice'
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
static async connect(options: RondevuOptions): Promise<Rondevu> {
|
||||
const username = options.username || Rondevu.generateAnonymousUsername()
|
||||
|
||||
console.log('[Rondevu] Connecting:', {
|
||||
username,
|
||||
hasKeypair: !!options.keypair,
|
||||
batchingEnabled: options.batching !== false
|
||||
})
|
||||
|
||||
// Generate keypair if not provided
|
||||
let keypair = options.keypair
|
||||
if (!keypair) {
|
||||
console.log('[Rondevu] Generating new keypair...')
|
||||
keypair = await RondevuAPI.generateKeypair(options.cryptoAdapter)
|
||||
console.log('[Rondevu] Generated keypair, publicKey:', keypair.publicKey)
|
||||
} else {
|
||||
console.log('[Rondevu] Using existing keypair, publicKey:', keypair.publicKey)
|
||||
}
|
||||
|
||||
// Create API instance
|
||||
const api = new RondevuAPI(
|
||||
options.apiUrl,
|
||||
username,
|
||||
keypair,
|
||||
options.cryptoAdapter,
|
||||
options.batching
|
||||
)
|
||||
console.log('[Rondevu] Created API instance')
|
||||
|
||||
return new Rondevu(
|
||||
options.apiUrl,
|
||||
username,
|
||||
keypair,
|
||||
api,
|
||||
options.cryptoAdapter,
|
||||
options.batching
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an anonymous username with timestamp and random component
|
||||
*/
|
||||
private generateAnonymousUsername(): string {
|
||||
private static generateAnonymousUsername(): string {
|
||||
const timestamp = Date.now().toString(36)
|
||||
const random = Array.from(crypto.getRandomValues(new Uint8Array(3)))
|
||||
.map(b => b.toString(16).padStart(2, '0')).join('')
|
||||
return `anon-${timestamp}-${random}`
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Initialization
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Initialize the service - generates keypair if not provided and creates API instance
|
||||
* Call this before using other methods
|
||||
*/
|
||||
async initialize(): Promise<void> {
|
||||
console.log('[Rondevu] Initialize called, hasKeypair:', !!this.keypair)
|
||||
|
||||
// Generate keypair if not provided
|
||||
if (!this.keypair) {
|
||||
console.log('[Rondevu] Generating new keypair...')
|
||||
this.keypair = await RondevuAPI.generateKeypair(this.cryptoAdapter)
|
||||
console.log('[Rondevu] Generated keypair, publicKey:', this.keypair.publicKey)
|
||||
} else {
|
||||
console.log('[Rondevu] Using existing keypair, publicKey:', this.keypair.publicKey)
|
||||
}
|
||||
|
||||
// Create API instance with username, keypair, crypto adapter, and batching options
|
||||
this.api = new RondevuAPI(
|
||||
this.apiUrl,
|
||||
this.username,
|
||||
this.keypair,
|
||||
this.cryptoAdapter,
|
||||
this.batchingOptions
|
||||
)
|
||||
console.log('[Rondevu] Created API instance with username:', this.username)
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Username Management
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Claim the username with Ed25519 signature
|
||||
* Should be called once before publishing services
|
||||
*/
|
||||
async claimUsername(): Promise<void> {
|
||||
if (!this.keypair) {
|
||||
throw new Error('Not initialized. Call initialize() first.')
|
||||
}
|
||||
|
||||
// Check if username is already claimed
|
||||
const available = await this.getAPI().isUsernameAvailable(this.username)
|
||||
if (!available) {
|
||||
// Check if it's claimed by us
|
||||
const claimed = await this.getAPI().isUsernameClaimed()
|
||||
if (claimed) {
|
||||
this.usernameClaimed = true
|
||||
return
|
||||
}
|
||||
throw new Error(`Username "${this.username}" is already claimed by another user`)
|
||||
}
|
||||
|
||||
// Claim the username
|
||||
await this.getAPI().claimUsername(this.username, this.keypair.publicKey)
|
||||
this.usernameClaimed = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Get API instance (creates lazily if needed)
|
||||
*/
|
||||
private getAPI(): RondevuAPI {
|
||||
if (!this.api) {
|
||||
throw new Error('Not initialized. Call initialize() first.')
|
||||
}
|
||||
return this.api
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if username has been claimed (checks with server)
|
||||
*/
|
||||
async isUsernameClaimed(): Promise<boolean> {
|
||||
if (!this.keypair) {
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
const claimed = await this.getAPI().isUsernameClaimed()
|
||||
const claimed = await this.api.isUsernameClaimed()
|
||||
|
||||
// Update internal flag to match server state
|
||||
this.usernameClaimed = claimed
|
||||
@@ -184,15 +168,14 @@ export class Rondevu {
|
||||
* Username will be automatically claimed on first publish if not already claimed
|
||||
*/
|
||||
async publishService(options: PublishServiceOptions): Promise<Service> {
|
||||
if (!this.keypair) {
|
||||
throw new Error('Not initialized. Call initialize() first.')
|
||||
}
|
||||
const { service, offers, ttl } = options
|
||||
|
||||
const { serviceFqn, offers, ttl } = options
|
||||
// Auto-append username to service
|
||||
const serviceFqn = `${service}@${this.username}`
|
||||
|
||||
// Publish to server (server will auto-claim username if needed)
|
||||
// Note: signature and message are generated by the API layer
|
||||
const result = await this.getAPI().publishService({
|
||||
const result = await this.api.publishService({
|
||||
serviceFqn,
|
||||
offers,
|
||||
ttl,
|
||||
@@ -223,7 +206,7 @@ export class Rondevu {
|
||||
createdAt: number
|
||||
expiresAt: number
|
||||
}> {
|
||||
return await this.getAPI().getService(serviceFqn)
|
||||
return await this.api.getService(serviceFqn)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,7 +222,7 @@ export class Rondevu {
|
||||
createdAt: number
|
||||
expiresAt: number
|
||||
}> {
|
||||
return await this.getAPI().getService(serviceVersion)
|
||||
return await this.api.getService(serviceVersion)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,7 +243,7 @@ export class Rondevu {
|
||||
limit: number
|
||||
offset: number
|
||||
}> {
|
||||
return await this.getAPI().getService(serviceVersion, { limit, offset })
|
||||
return await this.api.getService(serviceVersion, { limit, offset })
|
||||
}
|
||||
|
||||
// ============================================
|
||||
@@ -274,7 +257,7 @@ export class Rondevu {
|
||||
success: boolean
|
||||
offerId: string
|
||||
}> {
|
||||
await this.getAPI().answerOffer(serviceFqn, offerId, sdp)
|
||||
await this.api.answerOffer(serviceFqn, offerId, sdp)
|
||||
return { success: true, offerId }
|
||||
}
|
||||
|
||||
@@ -287,7 +270,7 @@ export class Rondevu {
|
||||
answererId: string
|
||||
answeredAt: number
|
||||
} | null> {
|
||||
return await this.getAPI().getOfferAnswer(serviceFqn, offerId)
|
||||
return await this.api.getOfferAnswer(serviceFqn, offerId)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,7 +292,7 @@ export class Rondevu {
|
||||
createdAt: number
|
||||
}>>
|
||||
}> {
|
||||
return await this.getAPI().poll(since)
|
||||
return await this.api.poll(since)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -319,7 +302,7 @@ export class Rondevu {
|
||||
count: number
|
||||
offerId: string
|
||||
}> {
|
||||
return await this.getAPI().addOfferIceCandidates(serviceFqn, offerId, candidates)
|
||||
return await this.api.addOfferIceCandidates(serviceFqn, offerId, candidates)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,7 +312,7 @@ export class Rondevu {
|
||||
candidates: IceCandidate[]
|
||||
offerId: string
|
||||
}> {
|
||||
return await this.getAPI().getOfferIceCandidates(serviceFqn, offerId, since)
|
||||
return await this.api.getOfferIceCandidates(serviceFqn, offerId, since)
|
||||
}
|
||||
|
||||
// ============================================
|
||||
@@ -339,7 +322,7 @@ export class Rondevu {
|
||||
/**
|
||||
* Get the current keypair (for backup/storage)
|
||||
*/
|
||||
getKeypair(): Keypair | null {
|
||||
getKeypair(): Keypair {
|
||||
return this.keypair
|
||||
}
|
||||
|
||||
@@ -353,8 +336,8 @@ export class Rondevu {
|
||||
/**
|
||||
* Get the public key
|
||||
*/
|
||||
getPublicKey(): string | null {
|
||||
return this.keypair?.publicKey || null
|
||||
getPublicKey(): string {
|
||||
return this.keypair.publicKey
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -362,9 +345,6 @@ export class Rondevu {
|
||||
* @deprecated Use direct methods on Rondevu instance instead
|
||||
*/
|
||||
getAPIPublic(): RondevuAPI {
|
||||
if (!this.api) {
|
||||
throw new Error('Not initialized. Call initialize() first.')
|
||||
}
|
||||
return this.api
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user