@xtr-dev/rondevu-server 0.0.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/API.md +39 -9
- package/CLAUDE.md +47 -0
- package/README.md +144 -187
- package/build.js +12 -0
- package/dist/index.js +799 -266
- package/dist/index.js.map +4 -4
- package/migrations/0001_add_peer_id.sql +21 -0
- package/migrations/0002_remove_topics.sql +22 -0
- package/migrations/0003_remove_origin.sql +29 -0
- package/migrations/0004_add_secret.sql +4 -0
- package/migrations/schema.sql +18 -0
- package/package.json +4 -3
- package/src/app.ts +421 -127
- package/src/bloom.ts +66 -0
- package/src/config.ts +27 -2
- package/src/crypto.ts +149 -0
- package/src/index.ts +28 -12
- package/src/middleware/auth.ts +51 -0
- package/src/storage/d1.ts +394 -0
- package/src/storage/hash-id.ts +37 -0
- package/src/storage/sqlite.ts +323 -178
- package/src/storage/types.ts +128 -54
- package/src/worker.ts +51 -16
- package/wrangler.toml +45 -0
- package/DEPLOYMENT.md +0 -346
- package/src/storage/kv.ts +0 -241
package/API.md
CHANGED
|
@@ -19,6 +19,33 @@ This allows multiple peers from the same application (origin) to discover each o
|
|
|
19
19
|
|
|
20
20
|
## GET `/`
|
|
21
21
|
|
|
22
|
+
Returns server version information including the git commit hash used to build the server.
|
|
23
|
+
|
|
24
|
+
### Response
|
|
25
|
+
|
|
26
|
+
**Content-Type:** `application/json`
|
|
27
|
+
|
|
28
|
+
**Success (200 OK):**
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"version": "a1b2c3d"
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Notes:**
|
|
36
|
+
- Returns the git commit hash from build time
|
|
37
|
+
- Returns "unknown" if git information is not available
|
|
38
|
+
|
|
39
|
+
### Example
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
curl -X GET http://localhost:3000/
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## GET `/topics`
|
|
48
|
+
|
|
22
49
|
Lists all topics with the count of available peers for each (paginated). Returns only topics that have unanswered sessions.
|
|
23
50
|
|
|
24
51
|
### Request
|
|
@@ -70,13 +97,13 @@ Lists all topics with the count of available peers for each (paginated). Returns
|
|
|
70
97
|
|
|
71
98
|
**Default pagination (page 1, limit 100):**
|
|
72
99
|
```bash
|
|
73
|
-
curl -X GET http://localhost:3000/ \
|
|
100
|
+
curl -X GET http://localhost:3000/topics \
|
|
74
101
|
-H "Origin: https://example.com"
|
|
75
102
|
```
|
|
76
103
|
|
|
77
104
|
**Custom pagination:**
|
|
78
105
|
```bash
|
|
79
|
-
curl -X GET "http://localhost:3000
|
|
106
|
+
curl -X GET "http://localhost:3000/topics?page=2&limit=50" \
|
|
80
107
|
-H "Origin: https://example.com"
|
|
81
108
|
```
|
|
82
109
|
|
|
@@ -403,26 +430,29 @@ All endpoints may return the following error responses:
|
|
|
403
430
|
|
|
404
431
|
### Peer Discovery and Connection
|
|
405
432
|
|
|
406
|
-
1. **
|
|
407
|
-
- GET `/` to see
|
|
433
|
+
1. **Check server version (optional):**
|
|
434
|
+
- GET `/` to see server version information
|
|
435
|
+
|
|
436
|
+
2. **Discover active topics:**
|
|
437
|
+
- GET `/topics` to see all topics and peer counts
|
|
408
438
|
- Optional: paginate through results with `?page=2&limit=100`
|
|
409
439
|
|
|
410
|
-
|
|
440
|
+
3. **Peer A announces availability:**
|
|
411
441
|
- POST `/:topic/offer` with peer identifier and signaling data
|
|
412
442
|
- Receives a unique session code
|
|
413
443
|
|
|
414
|
-
|
|
444
|
+
4. **Peer B discovers peers:**
|
|
415
445
|
- GET `/:topic/sessions` to list available sessions in a topic
|
|
416
446
|
- Filters out sessions with their own info to avoid self-connection
|
|
417
447
|
- Selects a peer to connect to
|
|
418
448
|
|
|
419
|
-
|
|
449
|
+
5. **Peer B initiates connection:**
|
|
420
450
|
- POST `/answer` with the session code and their signaling data
|
|
421
451
|
|
|
422
|
-
|
|
452
|
+
6. **Both peers exchange signaling information:**
|
|
423
453
|
- POST `/answer` with additional signaling data as needed
|
|
424
454
|
- POST `/poll` to retrieve signaling data from the other peer
|
|
425
455
|
|
|
426
|
-
|
|
456
|
+
7. **Peer connection established**
|
|
427
457
|
- Peers use exchanged signaling data to establish direct connection
|
|
428
458
|
- Session automatically expires after configured timeout
|
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Rondevu Server Development Guidelines
|
|
2
|
+
|
|
3
|
+
## WebRTC Signaling Best Practices
|
|
4
|
+
|
|
5
|
+
### ICE Candidate Storage
|
|
6
|
+
|
|
7
|
+
**IMPORTANT: Store ICE candidates as raw JSON without enforcing structure.**
|
|
8
|
+
|
|
9
|
+
When handling ICE candidates in the signaling server:
|
|
10
|
+
|
|
11
|
+
- ✅ **DO** store candidates as `JSON.stringify(candidate)` in the database
|
|
12
|
+
- ✅ **DO** retrieve candidates as `JSON.parse(candidate)` from the database
|
|
13
|
+
- ✅ **DO** use generic types like `any` in TypeScript for candidate data
|
|
14
|
+
- ❌ **DON'T** define strict types for ICE candidate structure
|
|
15
|
+
- ❌ **DON'T** validate or modify candidate properties
|
|
16
|
+
- ❌ **DON'T** assume you know what properties clients will send
|
|
17
|
+
|
|
18
|
+
**Why?** The server is just a relay - it doesn't need to understand the candidate structure. Different browsers and future WebRTC versions may include different properties. By keeping the server agnostic, we maintain maximum compatibility.
|
|
19
|
+
|
|
20
|
+
### Server Role Filtering
|
|
21
|
+
|
|
22
|
+
The server MUST filter ICE candidates by role:
|
|
23
|
+
- Offerers receive only answerer candidates (`WHERE role = 'answerer'`)
|
|
24
|
+
- Answerers receive only offerer candidates (`WHERE role = 'offerer'`)
|
|
25
|
+
|
|
26
|
+
This prevents peers from receiving their own candidates, which would cause connection failures.
|
|
27
|
+
|
|
28
|
+
## Security
|
|
29
|
+
|
|
30
|
+
- Always validate authentication tokens before allowing operations
|
|
31
|
+
- Verify ownership before allowing modifications
|
|
32
|
+
- Rate limit API endpoints to prevent abuse
|
|
33
|
+
- Clean up expired offers regularly
|
|
34
|
+
|
|
35
|
+
## Performance
|
|
36
|
+
|
|
37
|
+
- Use transactions for batch operations (SQLite)
|
|
38
|
+
- Index frequently queried columns (offer_id, role, created_at)
|
|
39
|
+
- Set appropriate TTLs for offers
|
|
40
|
+
- Implement pagination for large result sets
|
|
41
|
+
|
|
42
|
+
## Code Quality
|
|
43
|
+
|
|
44
|
+
- Handle errors gracefully with informative HTTP status codes
|
|
45
|
+
- Log important events for debugging
|
|
46
|
+
- Use TypeScript types for API contracts, but keep data types generic
|
|
47
|
+
- Write tests for critical paths
|
package/README.md
CHANGED
|
@@ -1,242 +1,199 @@
|
|
|
1
|
-
# Rondevu
|
|
1
|
+
# Rondevu Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@xtr-dev/rondevu-server)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- 🚀 **Fast & Lightweight** - Built with [Hono](https://hono.dev/) framework
|
|
8
|
-
- 📂 **Topic-Based Organization** - Group sessions by topic for easy peer discovery
|
|
9
|
-
- 🔒 **Origin Isolation** - Sessions are isolated by HTTP Origin header to group topics by domain
|
|
10
|
-
- 🏷️ **Peer Identification** - Info field prevents duplicate connections to same peer
|
|
11
|
-
- 🔌 **Pluggable Storage** - Storage interface supports SQLite and in-memory adapters
|
|
12
|
-
- 🐳 **Docker Ready** - Minimal Alpine-based Docker image
|
|
13
|
-
- ⏱️ **Session Timeout** - Configurable session expiration from initiation time
|
|
14
|
-
- 🔐 **Type Safe** - Written in TypeScript with full type definitions
|
|
5
|
+
🌐 **Topic-based peer discovery and WebRTC signaling**
|
|
15
6
|
|
|
16
|
-
|
|
7
|
+
Scalable peer-to-peer connection establishment with topic-based discovery, stateless authentication, and complete WebRTC signaling.
|
|
17
8
|
|
|
18
|
-
|
|
9
|
+
**Related repositories:**
|
|
10
|
+
- [@xtr-dev/rondevu-client](https://github.com/xtr-dev/rondevu-client) - TypeScript client library ([npm](https://www.npmjs.com/package/@xtr-dev/rondevu-client))
|
|
11
|
+
- [@xtr-dev/rondevu-server](https://github.com/xtr-dev/rondevu-server) - HTTP signaling server ([npm](https://www.npmjs.com/package/@xtr-dev/rondevu-server), [live](https://api.ronde.vu))
|
|
12
|
+
- [@xtr-dev/rondevu-demo](https://github.com/xtr-dev/rondevu-demo) - Interactive demo ([live](https://ronde.vu))
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
# Install dependencies
|
|
22
|
-
npm install
|
|
14
|
+
---
|
|
23
15
|
|
|
24
|
-
|
|
25
|
-
npm run dev
|
|
16
|
+
## Features
|
|
26
17
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
18
|
+
- **Topic-Based Discovery**: Tag offers with topics (e.g., torrent infohashes) for efficient peer finding
|
|
19
|
+
- **Stateless Authentication**: AES-256-GCM encrypted credentials, no server-side sessions
|
|
20
|
+
- **Protected Offers**: Optional secret field for access-controlled peer connections
|
|
21
|
+
- **Bloom Filters**: Client-side peer exclusion for efficient discovery
|
|
22
|
+
- **Multi-Offer Support**: Create multiple offers per peer simultaneously
|
|
23
|
+
- **Complete WebRTC Signaling**: Offer/answer exchange and ICE candidate relay
|
|
24
|
+
- **Dual Storage**: SQLite (Node.js/Docker) and Cloudflare D1 (Workers) backends
|
|
31
25
|
|
|
32
|
-
|
|
26
|
+
## Quick Start
|
|
33
27
|
|
|
28
|
+
**Node.js:**
|
|
34
29
|
```bash
|
|
35
|
-
|
|
36
|
-
docker build -t rondevu .
|
|
37
|
-
|
|
38
|
-
# Run with default settings (SQLite database)
|
|
39
|
-
docker run -p 3000:3000 rondevu
|
|
40
|
-
|
|
41
|
-
# Run with in-memory storage
|
|
42
|
-
docker run -p 3000:3000 -e STORAGE_TYPE=memory rondevu
|
|
43
|
-
|
|
44
|
-
# Run with custom timeout (10 minutes)
|
|
45
|
-
docker run -p 3000:3000 -e SESSION_TIMEOUT=600000 rondevu
|
|
30
|
+
npm install && npm start
|
|
46
31
|
```
|
|
47
32
|
|
|
48
|
-
|
|
49
|
-
|
|
33
|
+
**Docker:**
|
|
50
34
|
```bash
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
# Login to Cloudflare
|
|
55
|
-
wrangler login
|
|
56
|
-
|
|
57
|
-
# Create KV namespace
|
|
58
|
-
wrangler kv:namespace create SESSIONS
|
|
59
|
-
|
|
60
|
-
# Update wrangler.toml with the KV namespace ID
|
|
35
|
+
docker build -t rondevu . && docker run -p 3000:3000 -e STORAGE_PATH=:memory: rondevu
|
|
36
|
+
```
|
|
61
37
|
|
|
62
|
-
|
|
38
|
+
**Cloudflare Workers:**
|
|
39
|
+
```bash
|
|
63
40
|
npx wrangler deploy
|
|
64
41
|
```
|
|
65
42
|
|
|
66
|
-
|
|
43
|
+
## API Endpoints
|
|
67
44
|
|
|
68
|
-
|
|
45
|
+
### Public Endpoints
|
|
69
46
|
|
|
70
|
-
|
|
47
|
+
#### `GET /`
|
|
48
|
+
Returns server version and info
|
|
71
49
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
| `PORT` | Server port | `3000` |
|
|
75
|
-
| `STORAGE_TYPE` | Storage backend: `sqlite` or `memory` | `sqlite` |
|
|
76
|
-
| `STORAGE_PATH` | Path to SQLite database file | `./data.db` |
|
|
77
|
-
| `SESSION_TIMEOUT` | Session timeout in milliseconds | `300000` |
|
|
78
|
-
| `CORS_ORIGINS` | Comma-separated list of allowed origins | `*` |
|
|
50
|
+
#### `GET /health`
|
|
51
|
+
Health check endpoint with version
|
|
79
52
|
|
|
80
|
-
|
|
53
|
+
#### `POST /register`
|
|
54
|
+
Register a new peer and receive credentials (peerId + secret)
|
|
81
55
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
56
|
+
**Response:**
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"peerId": "f17c195f067255e357232e34cf0735d9",
|
|
60
|
+
"secret": "DdorTR8QgSn9yngn+4qqR8cs1aMijvX..."
|
|
61
|
+
}
|
|
88
62
|
```
|
|
89
63
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
64
|
+
#### `GET /topics?limit=50&offset=0`
|
|
65
|
+
List all topics with active peer counts (paginated)
|
|
66
|
+
|
|
67
|
+
**Query Parameters:**
|
|
68
|
+
- `limit` (optional): Maximum number of topics to return (default: 50, max: 200)
|
|
69
|
+
- `offset` (optional): Number of topics to skip (default: 0)
|
|
70
|
+
|
|
71
|
+
**Response:**
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"topics": [
|
|
75
|
+
{"topic": "movie-xyz", "activePeers": 42},
|
|
76
|
+
{"topic": "torrent-abc", "activePeers": 15}
|
|
77
|
+
],
|
|
78
|
+
"total": 123,
|
|
79
|
+
"limit": 50,
|
|
80
|
+
"offset": 0
|
|
81
|
+
}
|
|
101
82
|
```
|
|
102
83
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
84
|
+
#### `GET /offers/by-topic/:topic?limit=50&bloom=...`
|
|
85
|
+
Find offers by topic with optional bloom filter exclusion
|
|
86
|
+
|
|
87
|
+
**Query Parameters:**
|
|
88
|
+
- `limit` (optional): Maximum offers to return (default: 50, max: 200)
|
|
89
|
+
- `bloom` (optional): Base64-encoded bloom filter to exclude known peers
|
|
90
|
+
|
|
91
|
+
**Response:**
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"topic": "movie-xyz",
|
|
95
|
+
"offers": [
|
|
96
|
+
{
|
|
97
|
+
"id": "offer-id",
|
|
98
|
+
"peerId": "peer-id",
|
|
99
|
+
"sdp": "v=0...",
|
|
100
|
+
"topics": ["movie-xyz", "hd-content"],
|
|
101
|
+
"expiresAt": 1234567890,
|
|
102
|
+
"lastSeen": 1234567890,
|
|
103
|
+
"hasSecret": true // Indicates if secret is required to answer
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
"total": 42,
|
|
107
|
+
"returned": 10
|
|
108
|
+
}
|
|
110
109
|
```
|
|
111
110
|
|
|
112
|
-
**
|
|
113
|
-
|
|
114
|
-
curl -X GET http://localhost:3000/my-room/sessions \
|
|
115
|
-
-H "Origin: https://example.com"
|
|
116
|
-
# Returns: {"sessions":[...]}
|
|
117
|
-
```
|
|
111
|
+
**Notes:**
|
|
112
|
+
- `hasSecret`: Boolean flag indicating whether a secret is required to answer this offer. The actual secret is never exposed in public endpoints.
|
|
118
113
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
curl -X POST http://localhost:3000/answer \
|
|
122
|
-
-H "Content-Type: application/json" \
|
|
123
|
-
-H "Origin: https://example.com" \
|
|
124
|
-
-d '{"code":"550e8400-...","answer":"<SIGNALING_DATA>","side":"answerer"}'
|
|
125
|
-
# Returns: {"success":true}
|
|
126
|
-
```
|
|
114
|
+
#### `GET /peers/:peerId/offers`
|
|
115
|
+
View all offers from a specific peer
|
|
127
116
|
|
|
128
|
-
|
|
117
|
+
### Authenticated Endpoints
|
|
129
118
|
|
|
130
|
-
|
|
119
|
+
All authenticated endpoints require `Authorization: Bearer {peerId}:{secret}` header.
|
|
131
120
|
|
|
132
|
-
|
|
121
|
+
#### `POST /offers`
|
|
122
|
+
Create one or more offers
|
|
133
123
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
124
|
+
**Request:**
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"offers": [
|
|
128
|
+
{
|
|
129
|
+
"sdp": "v=0...",
|
|
130
|
+
"topics": ["movie-xyz", "hd-content"],
|
|
131
|
+
"ttl": 300000,
|
|
132
|
+
"secret": "my-secret-password" // Optional: protect offer (max 128 chars)
|
|
133
|
+
}
|
|
134
|
+
]
|
|
143
135
|
}
|
|
144
136
|
```
|
|
145
137
|
|
|
146
|
-
|
|
138
|
+
**Notes:**
|
|
139
|
+
- `secret` (optional): Protect the offer with a secret. Answerers must provide the correct secret to connect.
|
|
147
140
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
- Persistent file-based or in-memory
|
|
151
|
-
- Automatic session cleanup
|
|
152
|
-
- Simple and reliable
|
|
141
|
+
#### `GET /offers/mine`
|
|
142
|
+
List all offers owned by authenticated peer
|
|
153
143
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
- Global edge storage
|
|
157
|
-
- Automatic TTL-based expiration
|
|
158
|
-
- Distributed and highly available
|
|
144
|
+
#### `PUT /offers/:offerId/heartbeat`
|
|
145
|
+
Update last_seen timestamp for an offer
|
|
159
146
|
|
|
160
|
-
|
|
147
|
+
#### `DELETE /offers/:offerId`
|
|
148
|
+
Delete a specific offer
|
|
161
149
|
|
|
162
|
-
|
|
150
|
+
#### `POST /offers/:offerId/answer`
|
|
151
|
+
Answer an offer (locks it to answerer)
|
|
163
152
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
// Your implementation
|
|
170
|
-
}
|
|
171
|
-
// ... implement other methods
|
|
153
|
+
**Request:**
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"sdp": "v=0...",
|
|
157
|
+
"secret": "my-secret-password" // Required if offer is protected
|
|
172
158
|
}
|
|
173
159
|
```
|
|
174
160
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
### Project Structure
|
|
178
|
-
|
|
179
|
-
```
|
|
180
|
-
rondevu/
|
|
181
|
-
├── src/
|
|
182
|
-
│ ├── index.ts # Node.js server entry point
|
|
183
|
-
│ ├── app.ts # Hono application
|
|
184
|
-
│ ├── config.ts # Configuration
|
|
185
|
-
│ └── storage/
|
|
186
|
-
│ ├── types.ts # Storage interface
|
|
187
|
-
│ ├── sqlite.ts # SQLite adapter
|
|
188
|
-
│ └── codeGenerator.ts # Code generation utility
|
|
189
|
-
├── Dockerfile # Docker build configuration
|
|
190
|
-
├── build.js # Build script
|
|
191
|
-
├── API.md # API documentation
|
|
192
|
-
└── README.md # This file
|
|
193
|
-
```
|
|
161
|
+
**Notes:**
|
|
162
|
+
- `secret` (optional): Required if the offer was created with a secret. Must match the offer's secret.
|
|
194
163
|
|
|
195
|
-
|
|
164
|
+
#### `GET /offers/answers`
|
|
165
|
+
Poll for answers to your offers
|
|
196
166
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
npm run build
|
|
167
|
+
#### `POST /offers/:offerId/ice-candidates`
|
|
168
|
+
Post ICE candidates for an offer
|
|
200
169
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
```bash
|
|
208
|
-
# Build the image
|
|
209
|
-
docker build -t rondevu .
|
|
210
|
-
|
|
211
|
-
# Run with volume for persistent storage
|
|
212
|
-
docker run -p 3000:3000 -v $(pwd)/data:/app/data rondevu
|
|
170
|
+
**Request:**
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"candidates": ["candidate:1 1 UDP..."]
|
|
174
|
+
}
|
|
213
175
|
```
|
|
214
176
|
|
|
215
|
-
|
|
177
|
+
#### `GET /offers/:offerId/ice-candidates?since=1234567890`
|
|
178
|
+
Get ICE candidates from the other peer
|
|
216
179
|
|
|
217
|
-
|
|
218
|
-
2. **Peer A** announces availability by posting to `/:topic/offer` with peer identifier and signaling data
|
|
219
|
-
3. Server generates a unique UUID code and stores the session (bucketed by Origin and topic)
|
|
220
|
-
4. **Peer B** discovers available peers using `GET /:topic/sessions`
|
|
221
|
-
5. **Peer B** filters out their own session using the info field to avoid self-connection
|
|
222
|
-
6. **Peer B** selects a peer and posts their connection data to `POST /answer` with the session code
|
|
223
|
-
7. Both peers exchange signaling data through `POST /answer` endpoint
|
|
224
|
-
8. Both peers poll for updates using `POST /poll` to retrieve connection information
|
|
225
|
-
9. Sessions automatically expire after the configured timeout
|
|
226
|
-
|
|
227
|
-
This allows peers in distributed systems to discover each other without requiring a centralized registry, while maintaining isolation between different applications through Origin headers.
|
|
228
|
-
|
|
229
|
-
### Origin Isolation
|
|
180
|
+
## Configuration
|
|
230
181
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
182
|
+
Environment variables:
|
|
183
|
+
|
|
184
|
+
| Variable | Default | Description |
|
|
185
|
+
|----------|---------|-------------|
|
|
186
|
+
| `PORT` | `3000` | Server port (Node.js/Docker) |
|
|
187
|
+
| `CORS_ORIGINS` | `*` | Comma-separated allowed origins |
|
|
188
|
+
| `STORAGE_PATH` | `./rondevu.db` | SQLite database path (use `:memory:` for in-memory) |
|
|
189
|
+
| `VERSION` | `0.4.0` | Server version (semver) |
|
|
190
|
+
| `AUTH_SECRET` | Random 32-byte hex | Secret key for credential encryption |
|
|
191
|
+
| `OFFER_DEFAULT_TTL` | `300000` | Default offer TTL in ms (5 minutes) |
|
|
192
|
+
| `OFFER_MIN_TTL` | `60000` | Minimum offer TTL in ms (1 minute) |
|
|
193
|
+
| `OFFER_MAX_TTL` | `3600000` | Maximum offer TTL in ms (1 hour) |
|
|
194
|
+
| `MAX_OFFERS_PER_REQUEST` | `10` | Maximum offers per create request |
|
|
195
|
+
| `MAX_TOPICS_PER_OFFER` | `20` | Maximum topics per offer |
|
|
235
196
|
|
|
236
197
|
## License
|
|
237
198
|
|
|
238
199
|
MIT
|
|
239
|
-
|
|
240
|
-
## Contributing
|
|
241
|
-
|
|
242
|
-
Contributions are welcome! Please feel free to submit a Pull Request.
|
package/build.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
// Build script using esbuild
|
|
2
2
|
const esbuild = require('esbuild');
|
|
3
|
+
const { execSync } = require('child_process');
|
|
4
|
+
|
|
5
|
+
// Get git commit hash
|
|
6
|
+
let version = 'unknown';
|
|
7
|
+
try {
|
|
8
|
+
version = execSync('git rev-parse --short HEAD', { encoding: 'utf8' }).trim();
|
|
9
|
+
} catch (err) {
|
|
10
|
+
console.warn('Could not get git commit hash, using "unknown"');
|
|
11
|
+
}
|
|
3
12
|
|
|
4
13
|
esbuild.build({
|
|
5
14
|
entryPoints: ['src/index.ts'],
|
|
@@ -14,4 +23,7 @@ esbuild.build({
|
|
|
14
23
|
'hono'
|
|
15
24
|
],
|
|
16
25
|
sourcemap: true,
|
|
26
|
+
define: {
|
|
27
|
+
'process.env.RONDEVU_VERSION': JSON.stringify(version)
|
|
28
|
+
}
|
|
17
29
|
}).catch(() => process.exit(1));
|