import type { BaseItem, PersistenceAdapter, ReactivityAdapter, Changeset, LoadResponse } from '@signaldb/core'; import { Collection } from '@signaldb/core'; import PromiseQueue from './utils/PromiseQueue'; import type { Change, Snapshot, SyncOperation } from './types'; type SyncOptions> = { name: string; } & T; type CleanupFunction = (() => void | Promise) | void; interface Options, ItemType extends BaseItem = BaseItem, IdType = any> { pull: (collectionOptions: SyncOptions, pullParameters: { lastFinishedSyncStart?: number; lastFinishedSyncEnd?: number; }) => Promise>; push: (collectionOptions: SyncOptions, pushParameters: { rawChanges: Omit[]; changes: Changeset & { modifiedFields: Map; }; }) => Promise; registerRemoteChange?: (collectionOptions: SyncOptions, onChange: (data?: LoadResponse) => Promise) => CleanupFunction | Promise; id?: string; persistenceAdapter?: (id: string, registerErrorHandler: (handler: (error: Error) => void) => void) => PersistenceAdapter; reactivity?: ReactivityAdapter; onError?: (collectionOptions: SyncOptions, error: Error) => void; autostart?: boolean; debounceTime?: number; } /** * Class to manage syncing of collections. * @template CollectionOptions * @template ItemType * @template IdType * @example * const syncManager = new SyncManager({ * pull: async (collectionOptions) => { * const response = await fetch(`/api/collections/${collectionOptions.name}`) * return await response.json() * }, * push: async (collectionOptions, { changes }) => { * await fetch(`/api/collections/${collectionOptions.name}`, { * method: 'POST', * body: JSON.stringify(changes), * }) * }, * }) * * const collection = new Collection() * syncManager.addCollection(collection, { * name: 'todos', * }) * * syncManager.sync('todos') */ export default class SyncManager, ItemType extends BaseItem = BaseItem, IdType = any> { protected options: Options; protected collections: Map; options: SyncOptions; readyPromise: Promise; syncPaused: boolean; cleanupFunction?: CleanupFunction; }>; protected changes: Collection, string>; protected snapshots: Collection, string>; protected syncOperations: Collection; protected scheduledPushes: Set; protected remoteChanges: Omit[]; protected syncQueues: Map; protected persistenceReady: Promise; protected isDisposed: boolean; protected instanceId: string; protected id: string; protected debouncedFlush: () => void; /** * @param options Collection options * @param options.pull Function to pull data from remote source. * @param options.push Function to push data to remote source. * @param [options.registerRemoteChange] Function to register a callback for remote changes. * @param [options.id] Unique identifier for this sync manager. Only nessesary if you have multiple sync managers. * @param [options.persistenceAdapter] Persistence adapter to use for storing changes, snapshots and sync operations. * @param [options.reactivity] Reactivity adapter to use for reactivity. * @param [options.onError] Function to handle errors that occur async during syncing. * @param [options.autostart] Whether to automatically start syncing new collections. * @param [options.debounceTime] The time in milliseconds to debounce push operations. */ constructor(options: Options); protected createPersistenceAdapter(name: string): { adapter: PersistenceAdapter; handler: (error: Error) => void; } | undefined; protected getSyncQueue(name: string): PromiseQueue; /** * Clears all internal data structures */ dispose(): Promise; /** * Gets a collection with it's options by name * @deprecated Use getCollectionProperties instead. * @param name Name of the collection * @throws Will throw an error if the name wasn't found * @returns Tuple of collection and options */ getCollection(name: string): (Collection | SyncOptions)[]; /** * Gets collection options by name * @param name Name of the collection * @throws Will throw an error if the name wasn't found * @returns An object of all properties of the collection */ getCollectionProperties(name: string): { collection: Collection; options: SyncOptions; readyPromise: Promise; syncPaused: boolean; cleanupFunction?: CleanupFunction | undefined; }; /** * Adds a collection to the sync manager. * @param collection Collection to add * @param options Options for the collection. The object needs at least a `name` property. * @param options.name Unique name of the collection */ addCollection(collection: Collection, options: SyncOptions): void; protected flushScheduledPushes(): void; protected schedulePush(name: string): void; /** * Setup all collections to be synced with remote changes * and enable automatic pushing changes to the remote source. */ startAll(): Promise; /** * Setup a collection to be synced with remote changes * and enable automatic pushing changes to the remote source. * @param name Name of the collection */ startSync(name: string): Promise; /** * Pauses the sync process for all collections. * This means that the collections will not be synced with remote changes * and changes will not automatically be pushed to the remote source. */ pauseAll(): Promise; /** * Pauses the sync process for a collection. * This means that the collection will not be synced with remote changes * and changes will not automatically be pushed to the remote source. * @param name Name of the collection */ pauseSync(name: string): Promise; /** * Starts the sync process for all collections */ syncAll(): Promise; /** * Checks if a collection is currently beeing synced * @param [name] Name of the collection. If not provided, it will check if any collection is currently beeing synced. * @returns True if the collection is currently beeing synced, false otherwise. */ isSyncing(name?: string): boolean; /** * Checks if the sync manager is ready to sync. * @returns A promise that resolves when the sync manager is ready to sync. */ isReady(): Promise; /** * Starts the sync process for a collection * @param name Name of the collection * @param options Options for the sync process. * @param options.force If true, the sync process will be started even if there are no changes and onlyWithChanges is true. * @param options.onlyWithChanges If true, the sync process will only be started if there are changes. */ sync(name: string, options?: { force?: boolean; onlyWithChanges?: boolean; }): Promise; /** * Starts the push process for a collection (sync process but only if there are changes) * @param name Name of the collection */ pushChanges(name: string): Promise; protected syncWithData(name: string, data: LoadResponse): Promise; } export {};