import { ILogger } from 'js-logger'; import { SyncStatus, SyncStatusOptions } from '../../../db/crud/SyncStatus.js'; import { BaseListener, BaseObserver, BaseObserverInterface, Disposable } from '../../../utils/BaseObserver.js'; import { BucketStorageAdapter } from '../bucket/BucketStorageAdapter.js'; import { AbstractRemote, FetchStrategy } from './AbstractRemote.js'; import { StreamingSyncRequestParameterType } from './streaming-sync-types.js'; export declare enum LockType { CRUD = "crud", SYNC = "sync" } export declare enum SyncStreamConnectionMethod { HTTP = "http", WEB_SOCKET = "web-socket" } export declare enum SyncClientImplementation { /** * Decodes and handles sync lines received from the sync service in JavaScript. * * This is the default option. * * @deprecated We recommend the {@link RUST} client implementation for all apps. If you have issues with * the Rust client, please file an issue or reach out to us. The JavaScript client will be removed in a future * version of the PowerSync SDK. */ JAVASCRIPT = "js", /** * This implementation offloads the sync line decoding and handling into the PowerSync * core extension. * * This option is more performant than the {@link JAVASCRIPT} client, enabled by default and the * recommended client implementation for all apps. * * ## Compatibility warning * * The Rust sync client stores sync data in a format that is slightly different than the one used * by the old {@link JAVASCRIPT} implementation. When adopting the {@link RUST} client on existing * databases, the PowerSync SDK will migrate the format automatically. * Further, the {@link JAVASCRIPT} client in recent versions of the PowerSync JS SDK (starting from * the version introducing {@link RUST} as an option) also supports the new format, so you can switch * back to {@link JAVASCRIPT} later. * * __However__: Upgrading the SDK version, then adopting {@link RUST} as a sync client and later * downgrading the SDK to an older version (necessarily using the JavaScript-based implementation then) * can lead to sync issues. */ RUST = "rust" } /** * The default {@link SyncClientImplementation} to use, {@link SyncClientImplementation.RUST}. */ export declare const DEFAULT_SYNC_CLIENT_IMPLEMENTATION = SyncClientImplementation.RUST; /** * Abstract Lock to be implemented by various JS environments */ export interface LockOptions { callback: () => Promise; type: LockType; signal?: AbortSignal; } export interface AbstractStreamingSyncImplementationOptions extends RequiredAdditionalConnectionOptions { adapter: BucketStorageAdapter; subscriptions: SubscribedStream[]; uploadCrud: () => Promise; /** * An identifier for which PowerSync DB this sync implementation is * linked to. Most commonly DB name, but not restricted to DB name. */ identifier?: string; logger?: ILogger; remote: AbstractRemote; } export interface StreamingSyncImplementationListener extends BaseListener { /** * Triggered whenever a status update has been attempted to be made or * refreshed. */ statusUpdated?: ((statusUpdate: SyncStatusOptions) => void) | undefined; /** * Triggers whenever the status' members have changed in value */ statusChanged?: ((status: SyncStatus) => void) | undefined; } /** * Configurable options to be used when connecting to the PowerSync * backend instance. */ export type PowerSyncConnectionOptions = Omit; export interface InternalConnectionOptions extends BaseConnectionOptions, AdditionalConnectionOptions { } /** @internal */ export interface BaseConnectionOptions { /** * A set of metadata to be included in service logs. */ appMetadata?: Record; /** * Whether to use a JavaScript implementation to handle received sync lines from the sync * service, or whether this work should be offloaded to the PowerSync core extension. * * This defaults to the JavaScript implementation ({@link SyncClientImplementation.JAVASCRIPT}) * since the ({@link SyncClientImplementation.RUST}) implementation is experimental at the moment. */ clientImplementation?: SyncClientImplementation; /** * The connection method to use when streaming updates from * the PowerSync backend instance. * Defaults to a HTTP streaming connection. */ connectionMethod?: SyncStreamConnectionMethod; /** * The fetch strategy to use when streaming updates from the PowerSync backend instance. */ fetchStrategy?: FetchStrategy; /** * These parameters are passed to the sync rules, and will be available under the`user_parameters` object. */ params?: Record; /** * Whether to include streams that have `auto_subscribe: true` in their definition. * * This defaults to `true`. */ includeDefaultStreams?: boolean; /** * The serialized schema - mainly used to forward information about raw tables to the sync client. */ serializedSchema?: any; } /** @internal */ export interface AdditionalConnectionOptions { /** * Delay for retrying sync streaming operations * from the PowerSync backend after an error occurs. */ retryDelayMs?: number; /** * Backend Connector CRUD operations are throttled * to occur at most every `crudUploadThrottleMs` * milliseconds. */ crudUploadThrottleMs?: number; } /** @internal */ export interface RequiredAdditionalConnectionOptions extends Required { subscriptions: SubscribedStream[]; } export interface StreamingSyncImplementation extends BaseObserverInterface, Disposable { /** * Connects to the sync service */ connect(options?: InternalConnectionOptions): Promise; /** * Disconnects from the sync services. * @throws if not connected or if abort is not controlled internally */ disconnect(): Promise; getWriteCheckpoint: () => Promise; hasCompletedSync: () => Promise; isConnected: boolean; lastSyncedAt?: Date; syncStatus: SyncStatus; triggerCrudUpload: () => void; waitForReady(): Promise; waitForStatus(status: SyncStatusOptions): Promise; waitUntilStatusMatches(predicate: (status: SyncStatus) => boolean): Promise; updateSubscriptions(subscriptions: SubscribedStream[]): void; } export declare const DEFAULT_CRUD_UPLOAD_THROTTLE_MS = 1000; export declare const DEFAULT_RETRY_DELAY_MS = 5000; export declare const DEFAULT_STREAMING_SYNC_OPTIONS: { retryDelayMs: number; crudUploadThrottleMs: number; }; export type RequiredPowerSyncConnectionOptions = Required; export declare const DEFAULT_STREAM_CONNECTION_OPTIONS: RequiredPowerSyncConnectionOptions; export type SubscribedStream = { name: string; params: Record | null; }; export declare abstract class AbstractStreamingSyncImplementation extends BaseObserver implements StreamingSyncImplementation { protected _lastSyncedAt: Date | null; protected options: AbstractStreamingSyncImplementationOptions; protected abortController: AbortController | null; protected uploadAbortController: AbortController | null; protected crudUpdateListener?: () => void; protected streamingSyncPromise?: Promise; protected logger: ILogger; private activeStreams; private isUploadingCrud; private notifyCompletedUploads?; private handleActiveStreamsChange?; syncStatus: SyncStatus; triggerCrudUpload: () => void; constructor(options: AbstractStreamingSyncImplementationOptions); waitForReady(): Promise; waitForStatus(status: SyncStatusOptions): Promise; waitUntilStatusMatches(predicate: (status: SyncStatus) => boolean): Promise; get lastSyncedAt(): Date | undefined; get isConnected(): boolean; dispose(): Promise; abstract obtainLock(lockOptions: LockOptions): Promise; hasCompletedSync(): Promise; getWriteCheckpoint(): Promise; protected _uploadAllCrud(): Promise; connect(options?: PowerSyncConnectionOptions): Promise; disconnect(): Promise; /** * @deprecated use [connect instead] */ streamingSync(signal?: AbortSignal, options?: PowerSyncConnectionOptions): Promise; private collectLocalBucketState; /** * Older versions of the JS SDK used to encode subkeys as JSON in {@link OplogEntry.toJSON}. * Because subkeys are always strings, this leads to quotes being added around them in `ps_oplog`. * While this is not a problem as long as it's done consistently, it causes issues when a database * created by the JS SDK is used with other SDKs, or (more likely) when the new Rust sync client * is enabled. * * So, we add a migration from the old key format (with quotes) to the new one (no quotes). The * migration is only triggered when necessary (for now). The function returns whether the new format * should be used, so that the JS SDK is able to write to updated databases. * * @param requireFixedKeyFormat Whether we require the new format or also support the old one. * The Rust client requires the new subkey format. * @returns Whether the database is now using the new, fixed subkey format. */ private requireKeyFormat; protected streamingSyncIteration(signal: AbortSignal, options?: PowerSyncConnectionOptions): Promise; private receiveSyncLines; private legacyStreamingSyncIteration; private rustSyncIteration; private updateSyncStatusForStartingCheckpoint; private applyCheckpoint; protected updateSyncStatus(options: SyncStatusOptions): void; private delayRetry; updateSubscriptions(subscriptions: SubscribedStream[]): void; } interface RustIterationResult { immediateRestart: boolean; } export {};