···22import "./index.css";
33import App from "./App.tsx";
44import { Helmet } from "react-helmet";
55-import { DBAsync } from "@vlcn.io/xplat-api";
55+import { DBAsync, UPDATE_TYPE, UpdateType } from "@vlcn.io/xplat-api";
66import initWasm from "@vlcn.io/crsqlite-wasm";
77import wasmUrl from "@vlcn.io/crsqlite-wasm/crsqlite.wasm?url";
88import tblrx from "@vlcn.io/rx-tbl";
99import { SelectionProvider } from "@/contexts/selection-context";
1010import { useCustomSync } from "@/hooks/use-sync";
1111import { SyncStatus } from "@/components/ui/sync-status";
1212+1313+// Create a module-scoped registry for database instances
1414+const dbRegistry = new Map<string, { rx: any, db: any }>();
1515+1616+// Function to notify database listeners for a specific database
1717+export function notifyDbListeners(dbname: string) {
1818+ const ctx = dbRegistry.get(dbname);
1919+ if (ctx) {
2020+ console.log(`Notifying listeners for database: ${dbname}`);
2121+2222+ // Get all tables in the database
2323+ // For simplicity, we'll just use the todos table since we know it exists
2424+ const tables = ["todos"];
2525+2626+ // Create synthetic changes for each table
2727+ // This tells the system that each table has been updated
2828+ const changes: [number, string, bigint][] = tables.map(table => [
2929+ UPDATE_TYPE.UPDATE, // We use UPDATE as a general change type
3030+ table, // Table name
3131+ 0n // Using 0n as a generic rowid
3232+ ]);
3333+3434+ // Call the internal notify function
3535+ // First try with changes parameter
3636+ try {
3737+ console.log(`Calling __internalNotifyListeners with ${changes.length} changes`);
3838+ ctx.rx.__internalNotifyListeners(changes);
3939+ } catch (error) {
4040+ console.error('Error with changes parameter:', error);
4141+4242+ // Fallback to no parameters
4343+ try {
4444+ console.log('Calling __internalNotifyListeners with no parameters');
4545+ ctx.rx.__internalNotifyListeners();
4646+ } catch (error) {
4747+ console.error('Error with no parameters:', error);
4848+ }
4949+ }
5050+ return true;
5151+ }
5252+ console.warn(`No database context found for ${dbname}`);
5353+ return false;
5454+}
12551356// Create a worker instance only once
1457import SyncWorker from './worker/sync-worker.ts?worker';
···263306 WHERE completed = 0;
264307 `);
265308 const rx = tblrx(db);
309309+310310+ // Register the database context
311311+ dbRegistry.set(dbname, { db, rx });
312312+ console.log(`Registered database ${dbname} in registry`);
313313+314314+ // Add cleanup when the component unmounts
315315+ window.addEventListener('beforeunload', () => {
316316+ const ctx = dbRegistry.get(dbname);
317317+ if (ctx) {
318318+ // Proper cleanup
319319+ ctx.db.close();
320320+ dbRegistry.delete(dbname);
321321+ }
322322+ });
323323+266324 return { db, rx, roomId, dbname };
267325};
268326···372430373431// Handle worker messages
374432syncWorker.addEventListener('message', async (event) => {
375375- const { type, dbname, payload, room } = event.data;
433433+ const { type, dbname, payload, room, count } = event.data;
376434377435 if (type === 'REQUEST_SIGNATURE') {
378436 console.log('Received request for signature', { dbname, room });
···405463 message: authMessage
406464 });
407465 }, 0);
466466+ } else if (type === 'DB_UPDATED') {
467467+ console.log(`🔄 SYNC: Received DB_UPDATED for ${dbname}`);
468468+ const result = notifyDbListeners(dbname);
469469+ console.log(`🔄 SYNC: Notification result: ${result ? 'success' : 'failed'}`);
408470 }
409471});
410472473473+// Export the function so it can be used elsewhere if needed
474474+(window as any).notifyDbListeners = notifyDbListeners;
475475+411476const init = async () => {
412477 const ctx = await initDb();
413478414414- // Make the worker available globally for debugging
479479+ // Make useful objects available globally for debugging
415480 (window as any).syncWorker = syncWorker;
481481+ (window as any).notifyDbListeners = notifyDbListeners;
482482+ (window as any).dbRegistry = dbRegistry;
416483417484 createRoot(document.getElementById("root") as HTMLElement).render(
418485 <>
+13-12
mast-react-vite/src/worker/sync-worker.ts
···363363 // Notify main thread that changes were sent
364364 self.postMessage({ type: 'CHANGES_SENT', dbname, count: changes.length });
365365366366+ // Notify main thread that database was updated
367367+ logDebug(`🔄 DATABASE UPDATED: Notifying main thread for ${dbname} after sending ${changes.length} changes`);
368368+ self.postMessage({
369369+ type: 'DB_UPDATED',
370370+ dbname
371371+ });
372372+366373 } catch (error) {
367374 logError(`Error sending changes:`, error);
368375 self.postMessage({ type: 'SYNC_ERROR', dbname, error: 'Failed to send changes' });
···447454 logDebug(`Updated lastSyncVersion to ${maxVersion}`);
448455 }
449456450450- // Notify main thread that changes were applied and force a query refresh
451451- try {
452452- // This will trigger a database update event that @vlcn.io/rx-tbl will detect
453453- // Force a dummy statement that touches the database to trigger update subscriptions
454454- // Creating a temporary table will cause SQLite to touch the database file
455455- await connection.db.exec('SELECT 1;');
456456- } catch (error) {
457457- logError('Error triggering database refresh:', error);
458458- }
459459-460460- // Notify main thread that changes were applied
461461- self.postMessage({ type: 'CHANGES_APPLIED', dbname, count: changes.length });
457457+ // Notify main thread that database was updated
458458+ logDebug(`🔄 DATABASE UPDATED: Notifying main thread for ${dbname} with ${changes.length} changes`);
459459+ self.postMessage({
460460+ type: 'DB_UPDATED',
461461+ dbname
462462+ });
462463463464 } catch (error) {
464465 logError(`Error applying changes:`, error);