sveltekit-sync
Version:
Local-first sync engine for SvelteKit
127 lines (126 loc) • 4.38 kB
TypeScript
import type { Conflict, SyncConfig, SyncOperation, SyncStatus } from '../types.js';
import { RealtimeClient } from '../realtime/client.js';
import { type RealtimeStatus as RTStatus } from '../realtime/types.js';
import { QueryBuilder } from './query/builder.js';
import { type FieldsProxy } from './query/field-proxy.js';
import { PresenceStore, type User } from './presence.svelte.js';
import { SyncChannel, type ChannelOptions } from './channel.svelte.js';
export declare class SyncEngine<TLocalDB = any, TRemoteDB = any> {
private config;
private syncTimer;
private isSyncing;
private syncStatus;
private pendingOps;
private conflicts;
private lastSync;
private clientId;
private isInitialized;
private multiTab;
private collections;
private realtimeClient;
private realtimeStatus;
constructor(config: SyncConfig<TLocalDB, TRemoteDB>);
private setupMultiTabSync;
private handleRealtimeStatusChange;
private handleRealtimeOperations;
init(): Promise<void>;
private pullInitialData;
private ensureInitialized;
create(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>;
sync(force?: boolean): Promise<void>;
private push;
private pull;
private resolveConflicts;
private startAutoSync;
private stopAutoSync;
get state(): {
isSyncing: boolean;
status: SyncStatus;
pendingOps: SyncOperation<any>[];
conflicts: Conflict<any>[];
lastSync: number;
hasPendingChanges: boolean;
realtimeStatus: RTStatus;
isRealtimeConnected: boolean;
};
collection<T extends Record<string, any>>(tableName: string): CollectionStore<T>;
forcePush(): Promise<void>;
forcePull(): Promise<void>;
get realtime(): RealtimeClient | null;
enableRealtime(): void;
disableRealtime(): void;
/** Force realtime reconnection */
reconnectRealtime(): void;
/**
* Create a channel for scoped real-time communication
*/
channel(name: string, options?: ChannelOptions, user?: User): SyncChannel;
destroy(): void;
}
export declare class CollectionStore<T extends Record<string, any>> {
private engine;
private tableName;
data: T[];
isLoading: boolean;
error: Error | null;
private _initialized;
private _fields;
private presenceStore;
constructor(engine: SyncEngine, tableName: string);
/**
* Get typed field references for building queries
* Usage: todosStore.$.completed.eq(false)
*/
get $(): FieldsProxy<T>;
/**
* Alias for $ - get typed field references
* Usage: todosStore.fields.completed.eq(false)
*/
get fields(): FieldsProxy<T>;
/**
* Create a new query builder for this collection
* Supports multiple query syntaxes
* 1. Callback (full type inference):
* .where(todo => todo.completed === false)
* 2. Object syntax (simple equality):
* .where({ completed: false })
* 3. Object with operators:
* .where({ priority: gte(5) })
* 4. Proxy callback:
* .where(f => f.completed.eq(false))
* 5. Field condition:
* .where(fields.completed.eq(false))
* @returns A new QueryBuilder instance
*/
query(): QueryBuilder<T>;
/**
* Enable presence/awareness for this collection
*/
presence(config: {
user: User;
custom?: any;
}): PresenceStore<any>;
get count(): number;
get isEmpty(): boolean;
create(data: Omit<T, 'id'>): Promise<T>;
update(id: string, data: Partial<T>): Promise<T>;
delete(id: string): Promise<void>;
findOne(id: string): Promise<T | null>;
load(query?: any): Promise<void>;
reload(): Promise<void>;
find(predicate: (item: T) => boolean): T | undefined;
filter(predicate: (item: T) => boolean): T[];
map<U>(mapper: (item: T) => U): U[];
sort(compareFn: (a: T, b: T) => number): T[];
createMany(items: Omit<T, 'id'>[]): Promise<T[]>;
deleteMany(ids: string[]): Promise<void>;
updateMany(updates: {
id: string;
data: Partial<T>;
}[]): Promise<T[]>;
clear(): void;
}