diff --git a/js/src/sync/bootstrap.ts b/js/src/sync/bootstrap.ts new file mode 100644 index 0000000..e69de29 diff --git a/js/src/sync/object-pool.ts b/js/src/sync/object-pool.ts new file mode 100644 index 0000000..4670517 --- /dev/null +++ b/js/src/sync/object-pool.ts @@ -0,0 +1,8 @@ +// Indexdb abstraction that stores (and updates) objects in a pool and allows for live retrieval for the view layer. + + +/* We should have different databases for different entities. + * Then the view layer can use live queries + * The sync layer will keep this pool up to date + */ + diff --git a/js/src/sync/operation.ts b/js/src/sync/operation.ts new file mode 100644 index 0000000..ee3ff79 --- /dev/null +++ b/js/src/sync/operation.ts @@ -0,0 +1,10 @@ +export type OperationType = 'insert' | 'delete' | 'update'; +export type EntityType = 'particle' | 'network' | 'member'; +export type Operation = { + id: string; // Unique identifier for the operation + type: OperationType; + entityId: string; + entityType: EntityType; + data?: Record; // Optional data for the operation (e.g., new values for an update) + timestamp: number; // Unix timestamp in milliseconds +}; diff --git a/js/src/sync/sync-client.ts b/js/src/sync/sync-client.ts new file mode 100644 index 0000000..13db287 --- /dev/null +++ b/js/src/sync/sync-client.ts @@ -0,0 +1,63 @@ +import { Operation } from "./operation"; + +// This is a simple wrapper for managing websocket connection to the sync server +// It allows different parts of the app to listen for incoming operations and send messages +class SyncClient { + private socket: WebSocket | null = null; + private listeners: ((operation: Operation) => void)[] = []; + + connect(url: string) { + if (this.socket) { + this.socket.close(); + } + this.socket = new WebSocket(url); + + this.socket.onopen = () => { + console.log("WebSocket connected"); + }; + + this.socket.onmessage = (event) => { + const message = JSON.parse(event.data); + console.log("Received message:", message); + + if (message.type === "operation") { + const operation: Operation = message.operation; + this.listeners.forEach((listener) => listener(operation)); + } + } + + this.socket.onclose = () => { + console.log("WebSocket disconnected"); + this.socket = null; + }; + + this.socket.onerror = (error) => { + console.error("WebSocket error:", error); + }; + } + + addListener(listener: (operation: Operation) => void) { + this.listeners.push(listener); + } + + removeListener(listener: (operation: Operation) => void) { + this.listeners = this.listeners.filter((l) => l !== listener); + } + + sendMessage(message: any) { + if (this.socket && this.socket.readyState === WebSocket.OPEN) { + this.socket.send(JSON.stringify(message)); + } else { + console.warn("WebSocket is not connected. Cannot send message:", message); + } + } + + disconnect() { + if (this.socket) { + this.socket.close(); + } + this.socket = null; + } +} + +export const syncClient = new SyncClient();