UNPKG

sveltekit-sync

Version:
122 lines (121 loc) 4.73 kB
export type SyncStatus = 'idle' | 'syncing' | 'error' | 'conflict' | 'offline'; export interface SyncOperation<T = any> { id: string; table: string; operation: 'insert' | 'update' | 'delete'; data: T; timestamp: number; clientId: string; version: number; status: 'pending' | 'synced' | 'error'; error?: string; userId?: string; } export interface SyncResult { success: boolean; synced: string[]; conflicts: Conflict[]; errors: Array<{ id: string; error: string; }>; } export interface Conflict<T = any> { operation: SyncOperation<T>; serverData: T; clientData: T; resolution?: 'client-wins' | 'server-wins' | 'merged'; } export interface SyncConfig<TLocalDB = any, TRemoteDB = any> { local: { db: TLocalDB; adapter: LocalAdapter<TLocalDB>; }; remote: { push: (ops: SyncOperation[]) => Promise<SyncResult>; pull: (lastSync: number, clientId: string) => Promise<SyncOperation[]>; resolve?: (conflict: Conflict) => Promise<SyncOperation>; }; syncInterval?: number; batchSize?: number; conflictResolution?: 'client-wins' | 'server-wins' | 'manual' | 'last-write-wins'; retryAttempts?: number; retryDelay?: number; realtime?: RealtimeClientConfig; onSync?: (status: SyncStatus) => void; onConflict?: (conflict: Conflict) => void; onError?: (error: Error) => void; } export interface ClientState { clientId: string; userId: string; lastSync: Date; lastActive: Date; } export interface ServerAdapter<TDB = any> { insert(table: string, data: any): Promise<any>; update(table: string, id: string, data: any, version: number): Promise<any>; delete(table: string, id: string): Promise<void>; findOne(table: string, id: string): Promise<any | null>; find(table: string, filter?: QueryFilter): Promise<any[]>; getChangesSince(table: string, timestamp: number, userId?: string, excludeClientId?: string): Promise<SyncOperation[]>; applyOperation(op: SyncOperation, userId?: string): Promise<void>; batchInsert(table: string, records: any[]): Promise<any[]>; batchUpdate(table: string, updates: Array<{ id: string; data: any; }>): Promise<any[]>; checkConflict(table: string, id: string, expectedVersion: number): Promise<boolean>; logSyncOperation(op: SyncOperation, userId: string): Promise<void>; updateClientState(clientId: string, userId: string): Promise<void>; getClientState(clientId: string): Promise<ClientState | null>; subscribe?(tables: string[], userId: string, callback: (ops: SyncOperation[]) => void): Promise<() => void>; transaction?<T>(fn: (adapter: ServerAdapter<TDB>) => Promise<T>): Promise<T>; } export interface QueryFilter { where?: Record<string, any>; orderBy?: { field: string; direction: 'asc' | 'desc'; }[]; limit?: number; offset?: number; } export interface ClientAdapter<TDB = any> { insert(table: string, data: any): Promise<any>; update(table: string, id: string, data: any): Promise<any>; delete(table: string, id: string): Promise<void>; find(table: string, query?: any): Promise<any[]>; findOne(table: string, id: string): Promise<any | null>; addToQueue(op: SyncOperation): Promise<void>; getQueue(): Promise<SyncOperation[]>; removeFromQueue(ids: string[]): Promise<void>; updateQueueStatus(id: string, status: SyncOperation['status'], error?: string): Promise<void>; getLastSync(): Promise<number>; setLastSync(timestamp: number): Promise<void>; getClientId(): Promise<string>; batchInsert?(table: string, records: any[]): Promise<any[]>; batchDelete?(table: string, ids: string[]): Promise<void>; clear?(): Promise<void>; } export interface LocalAdapter<TDB = any> extends ClientAdapter<TDB> { isInitialized(): Promise<boolean>; setInitialized(value: boolean): Promise<void>; } export type RealtimeStatus = 'connected' | 'connecting' | 'disconnected' | 'fallback'; export interface RealtimeClientConfig { /** Enable realtime sync (default: true) */ enabled?: boolean; /** SSE endpoint URL (default: '/api/sync/realtime') */ endpoint?: string; /** Tables to subscribe to (default: [] = all tables) */ tables?: string[]; /** Reconnect interval in ms (default: 1000) */ reconnectInterval?: number; /** Maximum reconnect interval in ms (default: 30000) */ maxReconnectInterval?: number; /** Max reconnect attempts before fallback to polling (default: 5) */ maxReconnectAttempts?: number; /** Heartbeat timeout in ms (default: 45000) */ heartbeatTimeout?: number; }