type MaybePromise<T> = T | Promise<T>;
type ExportOptions = {
    from?: VersionVector;
    hooks?: ExportHooks;
    pruneTombstonesBefore?: number;
    peerId?: string;
};
type ImportOptions = {
    bundle: ExportBundle;
    hooks?: ImportHooks;
};
export type VersionVectorEntry = {
    physicalTime: number;
    logicalCounter: number;
};
export interface VersionVector {
    [peer: string]: VersionVectorEntry | undefined;
}
export declare function encodeVersionVector(vector: VersionVector): Uint8Array;
export declare function decodeVersionVector(bytes: Uint8Array): VersionVector;
export type Value = string | number | boolean | null | Array<Value> | {
    [key: string]: Value;
};
export type KeyPart = Value;
export type MetadataMap = Record<string, unknown>;
export type ExportRecord = {
    c: string;
    d?: Value;
    m?: MetadataMap;
};
export type ExportBundle = {
    version: number;
    entries: Record<string, ExportRecord>;
};
export type EntryClock = {
    physicalTime: number;
    logicalCounter: number;
    peerId: string;
};
export type EntryInfo = {
    data?: Value;
    metadata: MetadataMap;
    clock: EntryClock;
};
export type ExportPayload = {
    data?: Value;
    metadata?: MetadataMap;
};
export type ExportHookContext = {
    key: KeyPart[];
    clock: EntryClock;
    raw: ExportRecord;
};
export type ExportHooks = {
    transform?: (context: ExportHookContext, payload: ExportPayload) => MaybePromise<ExportPayload | void>;
};
export type ImportPayload = ExportPayload;
export type ImportHookContext = ExportHookContext;
export type ImportAccept = {
    accept: true;
};
export type ImportSkip = {
    accept: false;
    reason: string;
};
export type ImportDecision = ImportAccept | ImportSkip | ImportPayload | void;
export type ImportHooks = {
    preprocess?: (context: ImportHookContext, payload: ImportPayload) => MaybePromise<ImportDecision>;
};
export type ImportReport = {
    accepted: number;
    skipped: Array<{
        key: KeyPart[];
        reason: string;
    }>;
};
export type PutPayload = ExportPayload;
export type PutHookContext = {
    key: KeyPart[];
    now?: number;
};
export type PutHooks = {
    transform?: (context: PutHookContext, payload: PutPayload) => MaybePromise<PutPayload | void>;
};
export type PutWithMetaOptions = {
    metadata?: MetadataMap;
    now?: number;
    hooks?: PutHooks;
};
export type ScanBound = {
    kind: "inclusive";
    key: KeyPart[];
} | {
    kind: "exclusive";
    key: KeyPart[];
} | {
    kind: "unbounded";
};
export type ScanOptions = {
    start?: ScanBound;
    end?: ScanBound;
    prefix?: KeyPart[];
};
export type ScanRow = {
    key: KeyPart[];
    raw: ExportRecord;
    value?: Value;
};
export type EventPayload = ExportPayload;
export type Event = {
    key: KeyPart[];
    value?: Value;
    metadata?: MetadataMap;
    payload: EventPayload;
};
export type EventBatch = {
    source: string;
    events: Event[];
};
export declare class Flock {
    private inner;
    private listeners;
    private nativeSubscriberId;
    private eventBatcher;
    constructor(peerId?: string);
    private static fromInner;
    static fromJson(bundle: ExportBundle, peerId: string): Flock;
    static fromFile(bytes: Uint8Array, peerId?: string): Flock;
    checkInvariants(): void;
    setPeerId(peerId: string): void;
    private putWithMetaInternal;
    private putWithMetaWithHooks;
    /**
     * Put a value into the flock. If the given entry already exists, this insert will be skipped.
     * @param key
     * @param value
     * @param now
     */
    put(key: KeyPart[], value: Value, now?: number): void;
    putWithMeta(key: KeyPart[], value: Value, options?: PutWithMetaOptions): void | Promise<void>;
    set(key: KeyPart[], value: Value, now?: number): void;
    /**
     * Delete a value from the flock. If the given entry does not exist, this delete will be skipped.
     * @param key
     * @param now
     */
    delete(key: KeyPart[], now?: number): void;
    get(key: KeyPart[]): Value | undefined;
    /**
     * Returns the full entry payload (data, metadata, and clock) for a key.
     *
     * Unlike `get`, this distinguishes between a missing key (`undefined`) and a
     * tombstone (returns the clock and metadata with `data` omitted). Metadata is
     * cloned and defaults to `{}` when absent.
     */
    getEntry(key: KeyPart[]): EntryInfo | undefined;
    merge(other: Flock): void;
    /**
     * Returns the exclusive version vector, which only includes peers that have
     * at least one entry in the current state. This is consistent with the state
     * after export and re-import.
     *
     * Use this version when sending to other peers for incremental sync.
     */
    version(): VersionVector;
    /**
     * Returns the inclusive version vector, which includes all peers ever seen,
     * even if their entries have been overridden by other peers.
     *
     * Use this version when checking if you have received all data from another peer.
     */
    inclusiveVersion(): VersionVector;
    private exportJsonInternal;
    private exportJsonWithHooks;
    exportJson(): ExportBundle;
    exportJson(from: VersionVector): ExportBundle;
    exportJson(from: VersionVector, pruneTombstonesBefore: number): ExportBundle;
    exportJson(options: ExportOptions): Promise<ExportBundle>;
    private importJsonInternal;
    private importJsonWithHooks;
    importJson(bundle: ExportBundle): ImportReport;
    importJson(options: ImportOptions): Promise<ImportReport>;
    importJsonStr(bundle: string): ImportReport;
    getMaxPhysicalTime(): number;
    peerId(): string;
    kvToJson(): ExportBundle;
    putMvr(key: KeyPart[], value: Value, now?: number): void;
    getMvr(key: KeyPart[]): Value[];
    exportFile(): Uint8Array;
    scan(options?: ScanOptions): ScanRow[];
    private ensureNativeSubscription;
    private handleBatch;
    private deliverBatch;
    subscribe(listener: (batch: EventBatch) => void): () => void;
    /**
     * Enable auto-debounce mode. Events will be accumulated and emitted after
     * the specified timeout of inactivity. Each new operation resets the timer.
     *
     * Use `commit()` to force immediate emission of pending events.
     * Use `disableAutoDebounceCommit()` to disable and emit pending events.
     *
     * @param timeout - Debounce timeout in milliseconds
     * @param options - Optional configuration object with maxDebounceTime (default: 10000ms)
     * @throws Error if called while a transaction is active
     * @throws Error if autoDebounceCommit is already active
     *
     * @example
     * ```ts
     * flock.autoDebounceCommit(100);
     * flock.put(["a"], 1);
     * flock.put(["b"], 2);
     * // No events emitted yet...
     * // After 100ms of inactivity, subscribers receive single EventBatch
     * // If operations keep coming, commit happens after maxDebounceTime (10s default)
     * ```
     */
    autoDebounceCommit(timeout: number, options?: {
        maxDebounceTime?: number;
    }): void;
    /**
     * Disable auto-debounce mode and emit any pending events immediately.
     * No-op if autoDebounceCommit is not active.
     */
    disableAutoDebounceCommit(): void;
    /**
     * Force immediate emission of any pending debounced events.
     * Does not disable auto-debounce mode - new operations will continue to be debounced.
     * No-op if autoDebounceCommit is not active or no events are pending.
     */
    commit(): void;
    /**
     * Check if auto-debounce mode is currently active.
     */
    isAutoDebounceActive(): boolean;
    /**
     * Execute operations within a transaction. All put/delete operations inside
     * the callback will be batched and emitted as a single EventBatch when the
     * transaction commits successfully.
     *
     * If the callback throws an error, the transaction is rolled back and no
     * events are emitted. Note: Data changes are NOT rolled back - only event
     * emission is affected.
     *
     * The callback must be synchronous. For async operations, use FlockSQLite.
     *
     * @param callback - Synchronous function containing put/delete operations
     * @returns The return value of the callback
     * @throws Error if nested transaction attempted
     * @throws Error if import is called during the transaction (auto-commits first)
     * @throws Error if called while autoDebounceCommit is active
     *
     * @example
     * ```ts
     * flock.txn(() => {
     *   flock.put(["a"], 1);
     *   flock.put(["b"], 2);
     *   flock.put(["c"], 3);
     * });
     * // Subscribers receive a single EventBatch with 3 events
     * ```
     */
    txn<T>(callback: () => T): T;
    /**
     * Check if a transaction is currently active.
     */
    isInTxn(): boolean;
}
export {};
