import { OPSqliteOpenFactory } from '@powersync/op-sqlite'; import { PowerSyncContext, PowerSyncDatabase } from '@powersync/react-native'; import { type ReactNode, useEffect, useState } from 'react'; import { AppSchema } from './config'; import { SyncConnector } from './connector'; let powerSyncInstance: PowerSyncDatabase | null = null; let connectingPromise: Promise | null = null; let initPromise: Promise | null = null; function ensureDatabase(): PowerSyncDatabase { if (!powerSyncInstance) { const factory = new OPSqliteOpenFactory({ dbFilename: 'palace-powersync.sqlite' }); powerSyncInstance = new PowerSyncDatabase({ database: factory, schema: AppSchema }); } return powerSyncInstance; } async function ensureInitialized(): Promise { const db = ensureDatabase(); if (!initPromise) { initPromise = db.init(); } await initPromise; return db; } export function getDatabase(): PowerSyncDatabase { return ensureDatabase(); } export function isSyncConnected(): boolean { return powerSyncInstance?.connected ?? false; } export async function connectSync(): Promise { if (connectingPromise) return connectingPromise; const db = await ensureInitialized(); if (db.connected) return; connectingPromise = (async () => { try { const connector = new SyncConnector(); await connector.fetchCredentials(); await db.connect(connector); const timeout = new Promise((_, reject) => setTimeout(() => reject(new Error('Sync timeout after 30s')), 30000) ); await Promise.race([db.waitForFirstSync(), timeout]); } finally { connectingPromise = null; } })(); return connectingPromise; } export async function disconnectSync(): Promise { const db = getDatabase(); if (db.connected) { await db.disconnect(); } } export async function disconnectAndClear(): Promise { const db = getDatabase(); await db.disconnectAndClear(); } export function DatabaseProvider({ children }: { children: ReactNode }) { const [ready, setReady] = useState(false); useEffect(() => { ensureInitialized().then(() => setReady(true)); }, []); if (!ready) return null; return {children}; }