@vuer-ai/vuer-rtc 0.0.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 (169) hide show
  1. package/dist/client/EditBuffer.d.ts +43 -0
  2. package/dist/client/EditBuffer.d.ts.map +1 -0
  3. package/dist/client/EditBuffer.js +96 -0
  4. package/dist/client/EditBuffer.js.map +1 -0
  5. package/dist/client/actions.d.ts +66 -0
  6. package/dist/client/actions.d.ts.map +1 -0
  7. package/dist/client/actions.js +345 -0
  8. package/dist/client/actions.js.map +1 -0
  9. package/dist/client/createGraph.d.ts +30 -0
  10. package/dist/client/createGraph.d.ts.map +1 -0
  11. package/dist/client/createGraph.js +91 -0
  12. package/dist/client/createGraph.js.map +1 -0
  13. package/dist/client/hooks.d.ts +81 -0
  14. package/dist/client/hooks.d.ts.map +1 -0
  15. package/dist/client/hooks.js +161 -0
  16. package/dist/client/hooks.js.map +1 -0
  17. package/dist/client/index.d.ts +8 -0
  18. package/dist/client/index.d.ts.map +1 -0
  19. package/dist/client/index.js +10 -0
  20. package/dist/client/index.js.map +1 -0
  21. package/dist/client/types.d.ts +74 -0
  22. package/dist/client/types.d.ts.map +1 -0
  23. package/dist/client/types.js +11 -0
  24. package/dist/client/types.js.map +1 -0
  25. package/dist/hooks.d.ts +8 -0
  26. package/dist/hooks.d.ts.map +1 -0
  27. package/dist/hooks.js +7 -0
  28. package/dist/hooks.js.map +1 -0
  29. package/dist/index.d.ts +9 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +12 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/operations/OperationTypes.d.ts +239 -0
  34. package/dist/operations/OperationTypes.d.ts.map +1 -0
  35. package/dist/operations/OperationTypes.js +10 -0
  36. package/dist/operations/OperationTypes.js.map +1 -0
  37. package/dist/operations/OperationValidator.d.ts +32 -0
  38. package/dist/operations/OperationValidator.d.ts.map +1 -0
  39. package/dist/operations/OperationValidator.js +208 -0
  40. package/dist/operations/OperationValidator.js.map +1 -0
  41. package/dist/operations/apply/array.d.ts +22 -0
  42. package/dist/operations/apply/array.d.ts.map +1 -0
  43. package/dist/operations/apply/array.js +64 -0
  44. package/dist/operations/apply/array.js.map +1 -0
  45. package/dist/operations/apply/boolean.d.ts +18 -0
  46. package/dist/operations/apply/boolean.d.ts.map +1 -0
  47. package/dist/operations/apply/boolean.js +34 -0
  48. package/dist/operations/apply/boolean.js.map +1 -0
  49. package/dist/operations/apply/color.d.ts +14 -0
  50. package/dist/operations/apply/color.d.ts.map +1 -0
  51. package/dist/operations/apply/color.js +46 -0
  52. package/dist/operations/apply/color.js.map +1 -0
  53. package/dist/operations/apply/index.d.ts +18 -0
  54. package/dist/operations/apply/index.d.ts.map +1 -0
  55. package/dist/operations/apply/index.js +26 -0
  56. package/dist/operations/apply/index.js.map +1 -0
  57. package/dist/operations/apply/node.d.ts +24 -0
  58. package/dist/operations/apply/node.d.ts.map +1 -0
  59. package/dist/operations/apply/node.js +77 -0
  60. package/dist/operations/apply/node.js.map +1 -0
  61. package/dist/operations/apply/number.d.ts +26 -0
  62. package/dist/operations/apply/number.d.ts.map +1 -0
  63. package/dist/operations/apply/number.js +54 -0
  64. package/dist/operations/apply/number.js.map +1 -0
  65. package/dist/operations/apply/object.d.ts +14 -0
  66. package/dist/operations/apply/object.d.ts.map +1 -0
  67. package/dist/operations/apply/object.js +47 -0
  68. package/dist/operations/apply/object.js.map +1 -0
  69. package/dist/operations/apply/quaternion.d.ts +15 -0
  70. package/dist/operations/apply/quaternion.d.ts.map +1 -0
  71. package/dist/operations/apply/quaternion.js +33 -0
  72. package/dist/operations/apply/quaternion.js.map +1 -0
  73. package/dist/operations/apply/string.d.ts +14 -0
  74. package/dist/operations/apply/string.d.ts.map +1 -0
  75. package/dist/operations/apply/string.js +26 -0
  76. package/dist/operations/apply/string.js.map +1 -0
  77. package/dist/operations/apply/types.d.ts +34 -0
  78. package/dist/operations/apply/types.d.ts.map +1 -0
  79. package/dist/operations/apply/types.js +32 -0
  80. package/dist/operations/apply/types.js.map +1 -0
  81. package/dist/operations/apply/vector3.d.ts +18 -0
  82. package/dist/operations/apply/vector3.d.ts.map +1 -0
  83. package/dist/operations/apply/vector3.js +44 -0
  84. package/dist/operations/apply/vector3.js.map +1 -0
  85. package/dist/operations/dispatcher.d.ts +35 -0
  86. package/dist/operations/dispatcher.d.ts.map +1 -0
  87. package/dist/operations/dispatcher.js +107 -0
  88. package/dist/operations/dispatcher.js.map +1 -0
  89. package/dist/operations/index.d.ts +10 -0
  90. package/dist/operations/index.d.ts.map +1 -0
  91. package/dist/operations/index.js +17 -0
  92. package/dist/operations/index.js.map +1 -0
  93. package/dist/state/ConflictResolver.d.ts +36 -0
  94. package/dist/state/ConflictResolver.d.ts.map +1 -0
  95. package/dist/state/ConflictResolver.js +167 -0
  96. package/dist/state/ConflictResolver.js.map +1 -0
  97. package/dist/state/DType.d.ts +160 -0
  98. package/dist/state/DType.d.ts.map +1 -0
  99. package/dist/state/DType.js +282 -0
  100. package/dist/state/DType.js.map +1 -0
  101. package/dist/state/Schema.d.ts +32 -0
  102. package/dist/state/Schema.d.ts.map +1 -0
  103. package/dist/state/Schema.js +175 -0
  104. package/dist/state/Schema.js.map +1 -0
  105. package/dist/state/VectorClock.d.ts +42 -0
  106. package/dist/state/VectorClock.d.ts.map +1 -0
  107. package/dist/state/VectorClock.js +84 -0
  108. package/dist/state/VectorClock.js.map +1 -0
  109. package/dist/state/index.d.ts +11 -0
  110. package/dist/state/index.d.ts.map +1 -0
  111. package/dist/state/index.js +13 -0
  112. package/dist/state/index.js.map +1 -0
  113. package/docs/OPERATION_HINTS.md +222 -0
  114. package/docs/SCENE_GRAPH.md +373 -0
  115. package/docs/TYPE_BEHAVIORS.md +348 -0
  116. package/examples/01-basic-usage.ts +139 -0
  117. package/examples/02-concurrent-edits.ts +208 -0
  118. package/examples/03-scene-building.ts +258 -0
  119. package/examples/04-conflict-resolution.ts +339 -0
  120. package/examples/README.md +86 -0
  121. package/jest.config.js +19 -0
  122. package/package.json +57 -0
  123. package/src/client/EditBuffer.ts +105 -0
  124. package/src/client/actions.ts +397 -0
  125. package/src/client/createGraph.ts +132 -0
  126. package/src/client/hooks.tsx +249 -0
  127. package/src/client/index.ts +35 -0
  128. package/src/client/types.ts +94 -0
  129. package/src/hooks.ts +20 -0
  130. package/src/index.ts +14 -0
  131. package/src/operations/OperationTypes.ts +340 -0
  132. package/src/operations/OperationValidator.ts +260 -0
  133. package/src/operations/apply/array.ts +84 -0
  134. package/src/operations/apply/boolean.ts +48 -0
  135. package/src/operations/apply/color.ts +65 -0
  136. package/src/operations/apply/index.ts +37 -0
  137. package/src/operations/apply/node.ts +98 -0
  138. package/src/operations/apply/number.ts +76 -0
  139. package/src/operations/apply/object.ts +63 -0
  140. package/src/operations/apply/quaternion.ts +47 -0
  141. package/src/operations/apply/string.ts +36 -0
  142. package/src/operations/apply/types.ts +66 -0
  143. package/src/operations/apply/vector3.ts +60 -0
  144. package/src/operations/dispatcher.ts +127 -0
  145. package/src/operations/index.ts +80 -0
  146. package/src/state/ConflictResolver.ts +205 -0
  147. package/src/state/DType.ts +333 -0
  148. package/src/state/Schema.ts +236 -0
  149. package/src/state/VectorClock.ts +98 -0
  150. package/src/state/index.ts +14 -0
  151. package/tests/client/actions.test.ts +371 -0
  152. package/tests/client/edit-buffer.test.ts +117 -0
  153. package/tests/fixtures/array-ops.jsonl +6 -0
  154. package/tests/fixtures/boolean-ops.jsonl +6 -0
  155. package/tests/fixtures/color-ops.jsonl +4 -0
  156. package/tests/fixtures/edit-buffer.jsonl +3 -0
  157. package/tests/fixtures/node-ops.jsonl +6 -0
  158. package/tests/fixtures/number-ops.jsonl +7 -0
  159. package/tests/fixtures/object-ops.jsonl +4 -0
  160. package/tests/fixtures/operations.jsonl +7 -0
  161. package/tests/fixtures/string-ops.jsonl +4 -0
  162. package/tests/fixtures/undo-redo.jsonl +3 -0
  163. package/tests/fixtures/vector-ops.jsonl +9 -0
  164. package/tests/operations/collections.test.ts +193 -0
  165. package/tests/operations/nodes.test.ts +228 -0
  166. package/tests/operations/primitives.test.ts +222 -0
  167. package/tests/operations/vectors.test.ts +150 -0
  168. package/tsconfig.json +21 -0
  169. package/tsconfig.test.json +9 -0
@@ -0,0 +1,249 @@
1
+ /**
2
+ * React Hooks for vuer-rtc
3
+ *
4
+ * Usage:
5
+ * ```tsx
6
+ * function App() {
7
+ * return (
8
+ * <GraphProvider sessionId="my-session" onSend={sendToServer}>
9
+ * <Scene />
10
+ * </GraphProvider>
11
+ * );
12
+ * }
13
+ *
14
+ * function Scene() {
15
+ * const graph = useGraph();
16
+ * const { edit, commit, undo, redo } = useGraphActions();
17
+ * // ...
18
+ * }
19
+ * ```
20
+ */
21
+
22
+ import React, {
23
+ createContext,
24
+ useContext,
25
+ useState,
26
+ useCallback,
27
+ useSyncExternalStore,
28
+ useMemo,
29
+ type ReactNode,
30
+ } from 'react';
31
+ import type { CRDTMessage, Operation, SceneGraph, SceneNode } from '../operations/OperationTypes.js';
32
+ import { createGraph, type GraphStore, type Snapshot } from './createGraph.js';
33
+
34
+ // ===========================================
35
+ // Context
36
+ // ===========================================
37
+
38
+ const GraphContext = createContext<GraphStore | null>(null);
39
+
40
+ // ===========================================
41
+ // Provider
42
+ // ===========================================
43
+
44
+ export interface GraphProviderProps {
45
+ sessionId: string;
46
+ initialSnapshot?: Snapshot;
47
+ onSend?: (msg: CRDTMessage) => void;
48
+ children: ReactNode;
49
+ }
50
+
51
+ export function GraphProvider({
52
+ sessionId,
53
+ initialSnapshot,
54
+ onSend,
55
+ children,
56
+ }: GraphProviderProps): React.ReactElement {
57
+ const [store] = useState(() =>
58
+ createGraph({
59
+ sessionId,
60
+ initialSnapshot,
61
+ onSend,
62
+ })
63
+ );
64
+
65
+ return (
66
+ <GraphContext.Provider value={store}>
67
+ {children}
68
+ </GraphContext.Provider>
69
+ );
70
+ }
71
+
72
+ // ===========================================
73
+ // Hooks
74
+ // ===========================================
75
+
76
+ /**
77
+ * Get the graph store
78
+ */
79
+ export function useGraphStore(): GraphStore {
80
+ const store = useContext(GraphContext);
81
+ if (!store) {
82
+ throw new Error('useGraphStore must be used within a GraphProvider');
83
+ }
84
+ return store;
85
+ }
86
+
87
+ /**
88
+ * Get the current graph (reactive)
89
+ */
90
+ export function useGraph(): SceneGraph {
91
+ const store = useGraphStore();
92
+ return useSyncExternalStore(
93
+ store.subscribe,
94
+ () => store.getState().graph,
95
+ () => store.getState().graph
96
+ );
97
+ }
98
+
99
+ /**
100
+ * Get a specific node (reactive)
101
+ */
102
+ export function useNode(key: string): SceneNode | undefined {
103
+ const store = useGraphStore();
104
+ return useSyncExternalStore(
105
+ store.subscribe,
106
+ () => store.getState().graph.nodes[key],
107
+ () => store.getState().graph.nodes[key]
108
+ );
109
+ }
110
+
111
+ /**
112
+ * Get node property (reactive)
113
+ */
114
+ export function useNodeProperty<T>(key: string, path: string): T | undefined {
115
+ const store = useGraphStore();
116
+ return useSyncExternalStore(
117
+ store.subscribe,
118
+ () => {
119
+ const node = store.getState().graph.nodes[key];
120
+ return node ? (node[path] as T) : undefined;
121
+ },
122
+ () => {
123
+ const node = store.getState().graph.nodes[key];
124
+ return node ? (node[path] as T) : undefined;
125
+ }
126
+ );
127
+ }
128
+
129
+ /**
130
+ * Get graph actions
131
+ */
132
+ export function useGraphActions() {
133
+ const store = useGraphStore();
134
+
135
+ const edit = useCallback(
136
+ (op: Operation) => {
137
+ store.edit(op);
138
+ },
139
+ [store]
140
+ );
141
+
142
+ const commit = useCallback(
143
+ (description?: string) => {
144
+ return store.commit(description);
145
+ },
146
+ [store]
147
+ );
148
+
149
+ const undoAction = useCallback(() => {
150
+ return store.undo();
151
+ }, [store]);
152
+
153
+ const redoAction = useCallback(() => {
154
+ return store.redo();
155
+ }, [store]);
156
+
157
+ const receive = useCallback(
158
+ (msg: CRDTMessage) => {
159
+ store.receive(msg);
160
+ },
161
+ [store]
162
+ );
163
+
164
+ const ack = useCallback(
165
+ (msgId: string) => {
166
+ store.ack(msgId);
167
+ },
168
+ [store]
169
+ );
170
+
171
+ const compact = useCallback(() => {
172
+ store.compact();
173
+ }, [store]);
174
+
175
+ return useMemo(
176
+ () => ({
177
+ edit,
178
+ commit,
179
+ undo: undoAction,
180
+ redo: redoAction,
181
+ receive,
182
+ ack,
183
+ compact,
184
+ }),
185
+ [edit, commit, undoAction, redoAction, receive, ack, compact]
186
+ );
187
+ }
188
+
189
+ /**
190
+ * Hook for drag operations
191
+ *
192
+ * Usage:
193
+ * ```tsx
194
+ * const { onDragStart, onDrag, onDragEnd, isDragging } = useDrag('cube', 'position');
195
+ * ```
196
+ */
197
+ export function useDrag(nodeKey: string, path: string) {
198
+ const { edit, commit } = useGraphActions();
199
+ const [isDragging, setIsDragging] = useState(false);
200
+
201
+ const onDragStart = useCallback(() => {
202
+ setIsDragging(true);
203
+ }, []);
204
+
205
+ const onDrag = useCallback(
206
+ (delta: [number, number, number]) => {
207
+ edit({
208
+ otype: 'vector3.add',
209
+ key: nodeKey,
210
+ path,
211
+ value: delta,
212
+ });
213
+ },
214
+ [edit, nodeKey, path]
215
+ );
216
+
217
+ const onDragEnd = useCallback(() => {
218
+ setIsDragging(false);
219
+ commit(`Move ${nodeKey}`);
220
+ }, [commit, nodeKey]);
221
+
222
+ return useMemo(
223
+ () => ({ isDragging, onDragStart, onDrag, onDragEnd }),
224
+ [isDragging, onDragStart, onDrag, onDragEnd]
225
+ );
226
+ }
227
+
228
+ /**
229
+ * Hook for undo/redo keyboard shortcuts
230
+ */
231
+ export function useUndoRedoShortcuts() {
232
+ const { undo, redo } = useGraphActions();
233
+
234
+ React.useEffect(() => {
235
+ const handleKeyDown = (e: KeyboardEvent) => {
236
+ if ((e.metaKey || e.ctrlKey) && e.key === 'z') {
237
+ e.preventDefault();
238
+ if (e.shiftKey) {
239
+ redo();
240
+ } else {
241
+ undo();
242
+ }
243
+ }
244
+ };
245
+
246
+ window.addEventListener('keydown', handleKeyDown);
247
+ return () => window.removeEventListener('keydown', handleKeyDown);
248
+ }, [undo, redo]);
249
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Client module exports
3
+ */
4
+
5
+ // Types
6
+ export type {
7
+ ClientState,
8
+ JournalEntry,
9
+ EditBuffer,
10
+ Snapshot,
11
+ CreateGraphOptions,
12
+ GraphStore,
13
+ } from './types.js';
14
+
15
+ // Factory
16
+ export { createGraph, createGraphFromServer } from './createGraph.js';
17
+
18
+ // Actions (for advanced usage)
19
+ export {
20
+ createInitialState,
21
+ rebuildGraph,
22
+ onEdit,
23
+ commitEdits,
24
+ cancelEdits,
25
+ onServerAck,
26
+ onRemoteMessage,
27
+ undo,
28
+ redo,
29
+ compact,
30
+ initFromServer,
31
+ generateUUID,
32
+ } from './actions.js';
33
+
34
+ // Edit buffer utilities
35
+ export { isAdditiveOp, mergeValues, EditBufferImpl } from './EditBuffer.js';
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Client State Types
3
+ *
4
+ * Defines the state model for CRDT clients with:
5
+ * - graph: current computed state
6
+ * - journal: committed messages with ack and deletedAt
7
+ * - edits: uncommitted operations (edit buffer)
8
+ * - snapshot: checkpoint for fast replay
9
+ */
10
+
11
+ import type { CRDTMessage, Operation, SceneGraph } from '../operations/OperationTypes.js';
12
+ import type { VectorClock } from '../state/VectorClock.js';
13
+
14
+ /**
15
+ * Journal entry - a committed message with metadata
16
+ */
17
+ export interface JournalEntry {
18
+ msg: CRDTMessage;
19
+ ack: boolean; // Has server acknowledged?
20
+ deletedAt?: number; // If set, message is "undone"
21
+ }
22
+
23
+ /**
24
+ * Edit buffer - uncommitted operations
25
+ */
26
+ export interface EditBuffer {
27
+ ops: Operation[]; // Pending operations (merged)
28
+ startGraph: SceneGraph | null; // Graph state when edits started
29
+ }
30
+
31
+ /**
32
+ * Snapshot - checkpoint for fast replay
33
+ */
34
+ export interface Snapshot {
35
+ graph: SceneGraph;
36
+ vectorClock: VectorClock;
37
+ journalIndex: number; // How many entries are baked in
38
+ }
39
+
40
+ /**
41
+ * Client state - complete client-side state
42
+ */
43
+ export interface ClientState {
44
+ // Current computed value (derived from snapshot + journal + edits)
45
+ graph: SceneGraph;
46
+
47
+ // Committed edits (sent or pending acknowledgement)
48
+ journal: JournalEntry[];
49
+
50
+ // Uncommitted operations (in-progress edits)
51
+ edits: EditBuffer;
52
+
53
+ // Checkpoint for fast replay
54
+ snapshot: Snapshot;
55
+
56
+ // Clocks
57
+ lamportTime: number;
58
+ vectorClock: VectorClock;
59
+ sessionId: string;
60
+ }
61
+
62
+ /**
63
+ * Options for creating a graph store
64
+ */
65
+ export interface CreateGraphOptions {
66
+ sessionId: string;
67
+ initialSnapshot?: Snapshot;
68
+ onSend?: (msg: CRDTMessage) => void;
69
+ onStateChange?: (state: ClientState) => void;
70
+ }
71
+
72
+ /**
73
+ * Graph store - the public API
74
+ */
75
+ export interface GraphStore {
76
+ // State access
77
+ getState: () => ClientState;
78
+ subscribe: (listener: () => void) => () => void;
79
+
80
+ // Edit operations
81
+ edit: (op: Operation) => void;
82
+ commit: (description?: string) => CRDTMessage | null;
83
+
84
+ // Server communication
85
+ receive: (msg: CRDTMessage) => void;
86
+ ack: (msgId: string) => void;
87
+
88
+ // Undo/redo
89
+ undo: () => { msg: CRDTMessage | null };
90
+ redo: () => { msg: CRDTMessage | null };
91
+
92
+ // Maintenance
93
+ compact: () => void;
94
+ }
package/src/hooks.ts ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * React hooks for @vuer-ai/vuer-rtc
3
+ *
4
+ * Import from '@vuer-ai/vuer-rtc/hooks'
5
+ */
6
+
7
+ export {
8
+ GraphProvider,
9
+ useGraphStore,
10
+ useGraph,
11
+ useNode,
12
+ useNodeProperty,
13
+ useGraphActions,
14
+ useDrag,
15
+ useUndoRedoShortcuts,
16
+ type GraphProviderProps,
17
+ } from './client/hooks.js';
18
+
19
+ // Re-export types
20
+ export type { GraphStore, ClientState, Snapshot } from './client/types.js';
package/src/index.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @vuer-ai/vuer-rtc
3
+ *
4
+ * CRDT-based real-time collaborative data structures
5
+ */
6
+
7
+ // Operations
8
+ export * from './operations/index.js';
9
+
10
+ // State utilities
11
+ export * from './state/index.js';
12
+
13
+ // Client (state management, createGraph, etc.)
14
+ export * from './client/index.js';