@vuer-ai/vuer-rtc-server 0.2.3 → 0.4.1

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.
Files changed (104) hide show
  1. package/.env +1 -1
  2. package/README.md +56 -0
  3. package/dist/archive/ArchivalService.js +1 -1
  4. package/dist/archive/ArchivalService.js.map +1 -1
  5. package/dist/broker/InMemoryBroker.d.ts +2 -2
  6. package/dist/broker/InMemoryBroker.d.ts.map +1 -1
  7. package/dist/broker/InMemoryBroker.js +4 -4
  8. package/dist/broker/InMemoryBroker.js.map +1 -1
  9. package/dist/broker/types.d.ts +3 -3
  10. package/dist/broker/types.d.ts.map +1 -1
  11. package/dist/journal/CoalescingService.d.ts.map +1 -1
  12. package/dist/journal/CoalescingService.js +18 -208
  13. package/dist/journal/CoalescingService.js.map +1 -1
  14. package/dist/journal/GraphJournalService.d.ts +127 -0
  15. package/dist/journal/GraphJournalService.d.ts.map +1 -0
  16. package/dist/journal/GraphJournalService.js +491 -0
  17. package/dist/journal/GraphJournalService.js.map +1 -0
  18. package/dist/journal/JournalRLE.d.ts +2 -2
  19. package/dist/journal/JournalRLE.js +14 -14
  20. package/dist/journal/JournalRLE.js.map +1 -1
  21. package/dist/journal/JournalRepository.js +7 -7
  22. package/dist/journal/JournalRepository.js.map +1 -1
  23. package/dist/journal/JournalService.d.ts.map +1 -1
  24. package/dist/journal/JournalService.js +6 -40
  25. package/dist/journal/JournalService.js.map +1 -1
  26. package/dist/journal/RLECompression.d.ts +9 -9
  27. package/dist/journal/RLECompression.d.ts.map +1 -1
  28. package/dist/journal/RLECompression.js +22 -22
  29. package/dist/journal/RLECompression.js.map +1 -1
  30. package/dist/journal/TextJournalService.d.ts +98 -0
  31. package/dist/journal/TextJournalService.d.ts.map +1 -0
  32. package/dist/journal/TextJournalService.js +401 -0
  33. package/dist/journal/TextJournalService.js.map +1 -0
  34. package/dist/journal/index.d.ts +3 -1
  35. package/dist/journal/index.d.ts.map +1 -1
  36. package/dist/journal/index.js +4 -1
  37. package/dist/journal/index.js.map +1 -1
  38. package/dist/journal/rle-demo.js +11 -11
  39. package/dist/journal/rle-demo.js.map +1 -1
  40. package/dist/serve.d.ts +29 -11
  41. package/dist/serve.d.ts.map +1 -1
  42. package/dist/serve.js +558 -93
  43. package/dist/serve.js.map +1 -1
  44. package/dist/transport/RTCServer.d.ts +2 -2
  45. package/dist/transport/RTCServer.d.ts.map +1 -1
  46. package/dist/transport/RTCServer.js +22 -22
  47. package/dist/transport/RTCServer.js.map +1 -1
  48. package/docs/API.md +642 -0
  49. package/examples/compression-example.ts +3 -3
  50. package/package.json +2 -2
  51. package/prisma/schema.prisma +124 -6
  52. package/src/archive/ArchivalService.ts +1 -1
  53. package/src/broker/InMemoryBroker.ts +4 -4
  54. package/src/broker/types.ts +3 -3
  55. package/src/journal/CoalescingService.ts +18 -235
  56. package/src/journal/{JournalService.ts → GraphJournalService.ts} +34 -74
  57. package/src/journal/JournalRLE.ts +15 -15
  58. package/src/journal/JournalRepository.ts +7 -7
  59. package/src/journal/RLECompression.ts +24 -24
  60. package/src/journal/TextJournalService.ts +483 -0
  61. package/src/journal/index.ts +10 -2
  62. package/src/journal/rle-demo.ts +11 -11
  63. package/src/serve.ts +598 -94
  64. package/src/transport/RTCServer.ts +23 -23
  65. package/tests/benchmark/journal-optimization-benchmark.test.ts +14 -14
  66. package/tests/compression/compression.test.ts +8 -8
  67. package/tests/demo.ts +88 -88
  68. package/tests/e2e/convergence.test.ts +9 -9
  69. package/tests/e2e/helpers/assertions.ts +22 -0
  70. package/tests/e2e/helpers/createTestServer.ts +4 -4
  71. package/tests/e2e/latency.test.ts +47 -41
  72. package/tests/e2e/packet-loss.test.ts +6 -6
  73. package/tests/e2e/relay.test.ts +9 -9
  74. package/tests/e2e/sync-perf.test.ts +5 -5
  75. package/tests/e2e/sync-reconciliation.test.ts +6 -6
  76. package/tests/e2e/text-sync.test.ts +14 -14
  77. package/tests/e2e/tombstone-convergence.test.ts +22 -22
  78. package/tests/fixtures/array-ops.jsonl +6 -6
  79. package/tests/fixtures/boolean-ops.jsonl +6 -6
  80. package/tests/fixtures/color-ops.jsonl +4 -4
  81. package/tests/fixtures/edit-buffer.jsonl +3 -3
  82. package/tests/fixtures/messages.jsonl +4 -4
  83. package/tests/fixtures/node-ops.jsonl +6 -6
  84. package/tests/fixtures/number-ops.jsonl +7 -7
  85. package/tests/fixtures/object-ops.jsonl +4 -4
  86. package/tests/fixtures/operations.jsonl +7 -7
  87. package/tests/fixtures/string-ops.jsonl +4 -4
  88. package/tests/fixtures/undo-redo.jsonl +3 -3
  89. package/tests/fixtures/vector-ops.jsonl +9 -9
  90. package/tests/integration/repositories.test.ts +8 -9
  91. package/tests/journal/compaction-load-bug.test.ts +31 -31
  92. package/tests/journal/compaction.test.ts +26 -26
  93. package/tests/journal/journal-rle.test.ts +38 -38
  94. package/tests/journal/journal-service.test.ts +13 -13
  95. package/tests/journal/lww-ordering-bug.test.ts +39 -39
  96. package/tests/journal/rle-compression.test.ts +71 -71
  97. package/tests/journal/text-coalescing.test.ts +34 -34
  98. package/tests/test-data/datatypes.ts +85 -85
  99. package/tests/test-data/operations-example.ts +62 -62
  100. package/tests/test-data/scene-example.ts +11 -11
  101. package/tests/unit/operations.test.ts +7 -7
  102. package/tests/unit/s3-compression.test.ts +5 -3
  103. package/tests/unit/vectorClock.test.ts +2 -2
  104. package/tests/journal/multi-session-coalescing.test.ts +0 -871
package/docs/API.md ADDED
@@ -0,0 +1,642 @@
1
+ # Vuer RTC Server API Documentation
2
+
3
+ ## Overview
4
+
5
+ The Vuer RTC Server provides two types of collaborative documents:
6
+
7
+ 1. **Graph Documents** - Collaborative 3D scene graphs with nodes, transforms, and properties
8
+ 2. **Text Documents** - Collaborative text documents using CRDT (TextRope)
9
+
10
+ Each type has dedicated REST and WebSocket APIs.
11
+
12
+ ---
13
+
14
+ ## WebSocket API
15
+
16
+ ### Graph Documents
17
+
18
+ **URL**: `ws://server/ws/graph/{roomId}?sessionId={sessionId}`
19
+
20
+ **Lifecycle**:
21
+ ```
22
+ 1. Client connects → Server sends initial state
23
+ ← { type: 'init', snapshot: {...}, journal: [...] }
24
+
25
+ 2. Client sends operations
26
+ → { ops: [{ otype: 'node.insert', ... }], clock: {...}, lamportTime: 1 }
27
+
28
+ 3. Server broadcasts to all clients
29
+ ← { ops: [...], clock: {...}, lamportTime: 1 }
30
+
31
+ 4. Server sends acknowledgment
32
+ ← { type: 'ack', clock: {...}, lamportTime: 1 }
33
+
34
+ 5. Client disconnects → Server removes from room
35
+ ```
36
+
37
+ **Message Types**:
38
+ - `init` - Initial state snapshot + journal
39
+ - `message` - CRDT operations broadcast
40
+ - `ack` - Server acknowledgment of client messages
41
+ - `error` - Error notification
42
+
43
+ ### Text Documents
44
+
45
+ **URL**: `ws://server/ws/text/{docId}?sessionId={sessionId}`
46
+
47
+ **Lifecycle**:
48
+ ```
49
+ 1. Client connects → Server sends initial text state
50
+ ← { type: 'init', snapshot: { text: "..." }, journal: [...] }
51
+
52
+ 2. Client sends text operations
53
+ → { ops: [{ otype: 'text.insert', position: 0, value: 'Hello' }], clock: {...}, lamportTime: 1 }
54
+
55
+ 3. Server broadcasts to all clients
56
+ ← { ops: [...], clock: {...}, lamportTime: 1 }
57
+
58
+ 4. Server sends acknowledgment
59
+ ← { type: 'ack', clock: {...}, lamportTime: 1 }
60
+
61
+ 5. Client disconnects → Server removes from document
62
+ ```
63
+
64
+ **Text Operation Types**:
65
+ - `text.insert` - Insert text at position
66
+ - `text.delete` - Delete text at position
67
+ - `text.replace` - Replace text (atomic delete + insert)
68
+
69
+ ---
70
+
71
+ ## REST API
72
+
73
+ ### Statistics
74
+
75
+ #### `GET /api/stats`
76
+ Get database statistics
77
+
78
+ **Response**:
79
+ ```json
80
+ {
81
+ "documents": 10,
82
+ "textDocuments": 5,
83
+ "journalBatches": 150,
84
+ "operations": 2500,
85
+ "sessions": 8
86
+ }
87
+ ```
88
+
89
+ #### `GET /api/stats/sizes`
90
+ Get detailed size breakdown
91
+
92
+ **Response**:
93
+ ```json
94
+ {
95
+ "totalDocStateSize": 524288,
96
+ "totalJournalSize": 1048576,
97
+ "avgDocStateSize": 52428,
98
+ "avgJournalSize": 6990,
99
+ "documents": [...]
100
+ }
101
+ ```
102
+
103
+ ---
104
+
105
+ ## Graph Documents API
106
+
107
+ ### List Graph Documents
108
+
109
+ #### `GET /api/graph`
110
+ Get all graph documents
111
+
112
+ **Query Parameters**:
113
+ - `limit` (optional) - Number of documents to return
114
+ - `offset` (optional) - Pagination offset
115
+
116
+ **Response**:
117
+ ```json
118
+ {
119
+ "documents": [
120
+ {
121
+ "id": "507f1f77bcf86cd799439011",
122
+ "name": "my-scene",
123
+ "ownerId": "user-123",
124
+ "version": 5,
125
+ "createdAt": "2024-01-01T00:00:00Z",
126
+ "updatedAt": "2024-01-01T12:00:00Z"
127
+ }
128
+ ],
129
+ "total": 10
130
+ }
131
+ ```
132
+
133
+ ### Get Graph Document
134
+
135
+ #### `GET /api/graph/:id`
136
+ Get graph document state
137
+
138
+ **Response**:
139
+ ```json
140
+ {
141
+ "id": "507f1f77bcf86cd799439011",
142
+ "name": "my-scene",
143
+ "currentState": {
144
+ "graph": {
145
+ "nodes": {...},
146
+ "rootKey": "scene-root",
147
+ "lww": {},
148
+ "tombstones": {}
149
+ },
150
+ "vectorClock": {...},
151
+ "lamportTime": 100
152
+ },
153
+ "version": 5
154
+ }
155
+ ```
156
+
157
+ ### Get Graph Journal
158
+
159
+ #### `GET /api/graph/:id/journal`
160
+ Get operation journal (write-ahead log)
161
+
162
+ **Query Parameters**:
163
+ - `limit` (optional) - Number of batches to return
164
+ - `offset` (optional) - Pagination offset
165
+
166
+ **Response**:
167
+ ```json
168
+ {
169
+ "batches": [
170
+ {
171
+ "id": "507f...",
172
+ "batchId": "batch-uuid",
173
+ "operations": [...],
174
+ "vectorClock": {...},
175
+ "lamportTime": 100,
176
+ "persistedAt": "2024-01-01T00:00:00Z"
177
+ }
178
+ ],
179
+ "total": 50
180
+ }
181
+ ```
182
+
183
+ ### Get Graph Operations
184
+
185
+ #### `GET /api/graph/:id/operations`
186
+ Get all operations (expanded from journal batches)
187
+
188
+ **Query Parameters**:
189
+ - `limit` (optional) - Number of operations to return
190
+ - `offset` (optional) - Pagination offset
191
+
192
+ **Response**:
193
+ ```json
194
+ {
195
+ "operations": [
196
+ {
197
+ "id": "507f...",
198
+ "opId": "op-uuid",
199
+ "type": "node.insert",
200
+ "data": {...},
201
+ "vectorClock": {...},
202
+ "lamportTime": 100,
203
+ "createdAt": "2024-01-01T00:00:00Z"
204
+ }
205
+ ],
206
+ "total": 500
207
+ }
208
+ ```
209
+
210
+ ### Get Graph Sessions
211
+
212
+ #### `GET /api/graph/:id/sessions`
213
+ Get active and recent sessions
214
+
215
+ **Response**:
216
+ ```json
217
+ {
218
+ "sessions": [
219
+ {
220
+ "id": "507f...",
221
+ "userId": "user-123",
222
+ "clientId": "client-abc",
223
+ "connected": true,
224
+ "connectedAt": "2024-01-01T00:00:00Z",
225
+ "lastSeenAt": "2024-01-01T12:00:00Z"
226
+ }
227
+ ]
228
+ }
229
+ ```
230
+
231
+ ### Compact Graph Journal
232
+
233
+ #### `POST /api/graph/:id/compact`
234
+ Trigger journal compaction
235
+
236
+ Folds acknowledged journal entries into snapshot and removes them from the journal.
237
+
238
+ **Response**:
239
+ ```json
240
+ {
241
+ "message": "Compaction triggered",
242
+ "before": { "journal": 150, "snapshot": 50 },
243
+ "after": { "journal": 0, "snapshot": 200 }
244
+ }
245
+ ```
246
+
247
+ ### Coalesce Graph Operations
248
+
249
+ #### `POST /api/graph/:id/coalesce`
250
+ Trigger operation coalescing
251
+
252
+ Combines redundant operations (e.g., multiple updates to the same property).
253
+
254
+ **Response**:
255
+ ```json
256
+ {
257
+ "message": "Coalescing triggered",
258
+ "coalescedOps": 50,
259
+ "resultingOps": 25
260
+ }
261
+ ```
262
+
263
+ ### Delete Graph Document
264
+
265
+ #### `DELETE /api/graph/:id`
266
+ Permanently delete a graph document
267
+
268
+ **Response**:
269
+ ```json
270
+ {
271
+ "message": "Document deleted",
272
+ "id": "507f1f77bcf86cd799439011"
273
+ }
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Text Documents API
279
+
280
+ ### List Text Documents
281
+
282
+ #### `GET /api/text`
283
+ Get all text documents
284
+
285
+ **Query Parameters**:
286
+ - `limit` (optional) - Number of documents to return
287
+ - `offset` (optional) - Pagination offset
288
+
289
+ **Response**:
290
+ ```json
291
+ {
292
+ "documents": [
293
+ {
294
+ "id": "507f1f77bcf86cd799439011",
295
+ "name": "my-doc",
296
+ "ownerId": "user-123",
297
+ "version": 3,
298
+ "createdAt": "2024-01-01T00:00:00Z",
299
+ "updatedAt": "2024-01-01T12:00:00Z"
300
+ }
301
+ ],
302
+ "total": 5
303
+ }
304
+ ```
305
+
306
+ ### Get Text Document
307
+
308
+ #### `GET /api/text/:id`
309
+ Get text document content
310
+
311
+ **Response**:
312
+ ```json
313
+ {
314
+ "id": "507f1f77bcf86cd799439011",
315
+ "name": "my-doc",
316
+ "currentText": "Hello, world!",
317
+ "version": 3
318
+ }
319
+ ```
320
+
321
+ ### Get Text Journal
322
+
323
+ #### `GET /api/text/:id/journal`
324
+ Get operation journal for text document
325
+
326
+ **Query Parameters**:
327
+ - `limit` (optional) - Number of batches to return
328
+ - `offset` (optional) - Pagination offset
329
+
330
+ **Response**:
331
+ ```json
332
+ {
333
+ "batches": [
334
+ {
335
+ "id": "507f...",
336
+ "batchId": "batch-uuid",
337
+ "operations": [
338
+ {
339
+ "otype": "text.insert",
340
+ "position": 0,
341
+ "value": "Hello",
342
+ "id": "session-1-5",
343
+ "content": "Hello",
344
+ "seq": 1
345
+ }
346
+ ],
347
+ "vectorClock": { "session-1": 5 },
348
+ "lamportTime": 5,
349
+ "persistedAt": "2024-01-01T00:00:00Z"
350
+ }
351
+ ],
352
+ "total": 20
353
+ }
354
+ ```
355
+
356
+ ### Get Text Operations
357
+
358
+ #### `GET /api/text/:id/operations`
359
+ Get all text operations
360
+
361
+ **Query Parameters**:
362
+ - `limit` (optional) - Number of operations to return
363
+ - `offset` (optional) - Pagination offset
364
+
365
+ **Response**:
366
+ ```json
367
+ {
368
+ "operations": [
369
+ {
370
+ "id": "507f...",
371
+ "opId": "op-uuid",
372
+ "type": "text.insert",
373
+ "data": {
374
+ "position": 0,
375
+ "value": "Hello",
376
+ "id": "session-1-5",
377
+ "content": "Hello",
378
+ "seq": 1
379
+ },
380
+ "vectorClock": { "session-1": 5 },
381
+ "lamportTime": 5,
382
+ "createdAt": "2024-01-01T00:00:00Z"
383
+ }
384
+ ],
385
+ "total": 100
386
+ }
387
+ ```
388
+
389
+ ### Get Text Sessions
390
+
391
+ #### `GET /api/text/:id/sessions`
392
+ Get active and recent sessions for text document
393
+
394
+ **Response**:
395
+ ```json
396
+ {
397
+ "sessions": [
398
+ {
399
+ "id": "507f...",
400
+ "userId": "user-123",
401
+ "clientId": "client-abc",
402
+ "connected": true,
403
+ "connectedAt": "2024-01-01T00:00:00Z",
404
+ "lastSeenAt": "2024-01-01T12:00:00Z",
405
+ "presence": {
406
+ "cursor": { "position": 10 },
407
+ "selection": { "start": 5, "end": 15 }
408
+ }
409
+ }
410
+ ]
411
+ }
412
+ ```
413
+
414
+ ### Compact Text Journal
415
+
416
+ #### `POST /api/text/:id/compact`
417
+ Trigger journal compaction for text document
418
+
419
+ **Response**:
420
+ ```json
421
+ {
422
+ "message": "Compaction triggered",
423
+ "before": { "journal": 50, "text": "..." },
424
+ "after": { "journal": 0, "text": "..." }
425
+ }
426
+ ```
427
+
428
+ ### Coalesce Text Operations
429
+
430
+ #### `POST /api/text/:id/coalesce`
431
+ Trigger operation coalescing for text document
432
+
433
+ **Response**:
434
+ ```json
435
+ {
436
+ "message": "Coalescing triggered",
437
+ "coalescedOps": 20,
438
+ "resultingOps": 10
439
+ }
440
+ ```
441
+
442
+ ### Delete Text Document
443
+
444
+ #### `DELETE /api/text/:id`
445
+ Permanently delete a text document
446
+
447
+ **Response**:
448
+ ```json
449
+ {
450
+ "message": "Text document deleted",
451
+ "id": "507f1f77bcf86cd799439011"
452
+ }
453
+ ```
454
+
455
+ ---
456
+
457
+ ## Legacy Endpoints (Deprecated)
458
+
459
+ For backwards compatibility, the following endpoints redirect to `/api/graph/`:
460
+
461
+ - `GET /api/documents` → `GET /api/graph`
462
+ - `GET /api/documents/:id` → `GET /api/graph/:id`
463
+ - `GET /api/rooms/:roomId/state` → `GET /api/graph/:id/state`
464
+ - `DELETE /api/rooms/:roomId` → `DELETE /api/graph/:id`
465
+
466
+ **Note**: These will be removed in a future version. Please migrate to the new endpoints.
467
+
468
+ ---
469
+
470
+ ## Error Responses
471
+
472
+ All endpoints return errors in the following format:
473
+
474
+ ```json
475
+ {
476
+ "error": "Error message",
477
+ "code": "ERROR_CODE",
478
+ "details": {...}
479
+ }
480
+ ```
481
+
482
+ **Common Error Codes**:
483
+ - `404` - Document not found
484
+ - `400` - Invalid request
485
+ - `500` - Internal server error
486
+ - `403` - Forbidden (authorization failed)
487
+
488
+ ---
489
+
490
+ ## CRDT Concepts
491
+
492
+ ### Vector Clock
493
+ Causal ordering mechanism - tracks the logical time for each session.
494
+
495
+ ```json
496
+ {
497
+ "session-1": 5,
498
+ "session-2": 3,
499
+ "session-3": 7
500
+ }
501
+ ```
502
+
503
+ ### Lamport Time
504
+ Global logical clock for deterministic tie-breaking.
505
+
506
+ ### Journal
507
+ Write-ahead log of all operations. Provides:
508
+ - Reliability (operations persisted before acknowledgment)
509
+ - Undo/redo support
510
+ - Audit trail
511
+ - Efficient sync (send only new operations)
512
+
513
+ ### Compaction
514
+ Folding acknowledged operations into snapshot to reduce journal size.
515
+
516
+ ---
517
+
518
+ ## Rate Limiting
519
+
520
+ - WebSocket connections: 100 per IP
521
+ - REST API: 1000 requests/minute per IP
522
+ - Journal compaction: Max 1 per document per minute
523
+
524
+ ---
525
+
526
+ ## Examples
527
+
528
+ ### Connecting to a Graph Document
529
+
530
+ ```javascript
531
+ const ws = new WebSocket('ws://localhost:8080/ws/graph/my-room?sessionId=client-123');
532
+
533
+ ws.onmessage = (event) => {
534
+ const msg = JSON.parse(event.data);
535
+
536
+ if (msg.type === 'init') {
537
+ console.log('Initial state:', msg.snapshot);
538
+ console.log('Journal:', msg.journal);
539
+ } else if (msg.type === 'message') {
540
+ console.log('Operations:', msg.ops);
541
+ }
542
+ };
543
+
544
+ // Send an operation
545
+ ws.send(JSON.stringify({
546
+ ops: [{
547
+ otype: 'node.insert',
548
+ key: 'root',
549
+ path: 'children',
550
+ value: { key: 'cube-1', tag: 'Box' }
551
+ }],
552
+ clock: { 'client-123': 1 },
553
+ lamportTime: 1
554
+ }));
555
+ ```
556
+
557
+ ### Connecting to a Text Document
558
+
559
+ ```javascript
560
+ const ws = new WebSocket('ws://localhost:8080/ws/text/my-doc?sessionId=client-456');
561
+
562
+ ws.onmessage = (event) => {
563
+ const msg = JSON.parse(event.data);
564
+
565
+ if (msg.type === 'init') {
566
+ console.log('Initial text:', msg.snapshot.text);
567
+ } else if (msg.type === 'message') {
568
+ console.log('Text operations:', msg.ops);
569
+ }
570
+ };
571
+
572
+ // Send a text insert
573
+ ws.send(JSON.stringify({
574
+ ops: [{
575
+ otype: 'text.insert',
576
+ position: 0,
577
+ value: 'Hello, world!'
578
+ }],
579
+ clock: { 'client-456': 1 },
580
+ lamportTime: 1
581
+ }));
582
+ ```
583
+
584
+ ---
585
+
586
+ ## Client Libraries
587
+
588
+ ### JavaScript/TypeScript
589
+
590
+ ```bash
591
+ npm install @vuer-ai/vuer-rtc
592
+ ```
593
+
594
+ **Graph Documents**:
595
+ ```typescript
596
+ import { createGraph } from '@vuer-ai/vuer-rtc/client';
597
+
598
+ const graph = createGraph({
599
+ sessionId: 'my-session',
600
+ onSend: (msg) => websocket.send(msg)
601
+ });
602
+
603
+ graph.onEdit({
604
+ key: 'root',
605
+ otype: 'node.insert',
606
+ path: 'children',
607
+ value: { key: 'cube-1', tag: 'Box' }
608
+ });
609
+
610
+ graph.commit();
611
+ ```
612
+
613
+ **Text Documents**:
614
+ ```typescript
615
+ import { createTextDocument } from '@vuer-ai/vuer-rtc/client';
616
+
617
+ const doc = createTextDocument({
618
+ sessionId: 'my-session',
619
+ onSend: (msg) => websocket.send(msg)
620
+ });
621
+
622
+ doc.insert(0, 'Hello, world!');
623
+ doc.commit();
624
+ ```
625
+
626
+ ### Python
627
+
628
+ ```bash
629
+ pip install vuer-rtc
630
+ ```
631
+
632
+ ```python
633
+ from vuer_rtc import GraphClient, TextClient
634
+
635
+ # Graph document
636
+ graph = GraphClient(url='ws://localhost:8080/ws/graph/my-room', session_id='py-client')
637
+ graph.insert_node('root', 'children', {'key': 'cube-1', 'tag': 'Box'})
638
+
639
+ # Text document
640
+ text = TextClient(url='ws://localhost:8080/ws/text/my-doc', session_id='py-client')
641
+ text.insert(0, 'Hello, world!')
642
+ ```
@@ -55,7 +55,7 @@ async function exampleBasicCompression() {
55
55
  rootKey: 'root',
56
56
  },
57
57
  vectorClock: { session1: 100, session2: 50 },
58
- lamportTime: 100,
58
+ lt: 100,
59
59
  journalIndex: 100,
60
60
  };
61
61
 
@@ -94,7 +94,7 @@ async function exampleVerifyIntegrity() {
94
94
  rootKey: 'root',
95
95
  },
96
96
  vectorClock: { session1: 42 },
97
- lamportTime: 42,
97
+ lt: 42,
98
98
  journalIndex: 42,
99
99
  };
100
100
 
@@ -142,7 +142,7 @@ async function exampleCompressionStats() {
142
142
  vectorClock: Object.fromEntries(
143
143
  Array.from({ length: 10 }, (_, i) => [`session${i}`, i * 10])
144
144
  ),
145
- lamportTime: 100,
145
+ lt: 100,
146
146
  journalIndex: 100,
147
147
  };
148
148
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vuer-ai/vuer-rtc-server",
3
- "version": "0.2.3",
3
+ "version": "0.4.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Vuer RTC Server — RoomBroker, WebSocket transport, MongoDB persistence",
@@ -41,7 +41,7 @@
41
41
  "@prisma/client": "^5.22.0",
42
42
  "prisma": "^5.22.0",
43
43
  "ws": "^8.19.0",
44
- "@vuer-ai/vuer-rtc": "^0.3.2"
44
+ "@vuer-ai/vuer-rtc": "^0.8.6"
45
45
  },
46
46
  "scripts": {
47
47
  "build": "prisma generate && tsc",