import BaseAdapter, { StorageProxy } from "./adapters/base";
import KintoBase from "./KintoBase";
import { Collection as KintoCollection } from "./http";
import { KintoRepresentation, IdSchema, RemoteTransformer, AvailableHook, Hooks, UndefiendKintoRepresentation, UpdateRepresentation, WithOptional, RecordStatus, SyncResult, KintoError, Conflict, Emitter, CollectionSyncOptions } from "./types";
/**
 * Compare two records omitting local fields and synchronization
 * attributes (like _status and last_modified)
 * @param {Object} a    A record to compare.
 * @param {Object} b    A record to compare.
 * @param {Array} localFields Additional fields to ignore during the comparison
 * @return {boolean}
 */
export declare function recordsEqual(a: {
    [key: string]: unknown;
}, b: {
    [key: string]: unknown;
}, localFields?: readonly string[]): boolean;
/**
 * Synchronization result object.
 */
export declare class SyncResultObject {
    /**
     * Public constructor.
     */
    lastModified?: number | null;
    private _lists;
    private _cached;
    constructor();
    /**
     * Adds entries for a given result type.
     *
     * @param {String} type    The result type.
     * @param {Array}  entries The result entries.
     * @return {SyncResultObject}
     */
    add<K extends keyof SyncResult>(type: K, entries: SyncResult[K] | SyncResult[K][0]): SyncResultObject;
    get ok(): boolean;
    get errors(): KintoError[];
    get conflicts(): Conflict<any>[];
    get skipped(): any[];
    get resolved(): any[];
    get created(): any[];
    get updated(): import("./types").Update<any>[];
    get deleted(): any[];
    get published(): any[];
    private _deduplicate;
    /**
     * Reinitializes result entries for a given result type.
     *
     * @param  {String} type The result type.
     * @return {SyncResultObject}
     */
    reset(type: keyof SyncResult): SyncResultObject;
    private toObject;
}
export declare class ServerWasFlushedError extends Error {
    clientTimestamp: number;
    serverTimestamp?: number;
    message: string;
    constructor(clientTimestamp: number, serverTimestamp: number | undefined, message: string);
}
/**
 * IDSchema for when using kinto.js as a key-value store.
 * Using this IDSchema requires you to set a property as the id.
 * This will be the property used to retrieve this record.
 *
 * @example
 * const exampleCollection = db.collection("example", { idSchema: createKeyValueStoreIdSchema() })
 * await exampleCollection.create({ title: "How to tie a tie", favoriteColor: "blue", id: "user123" }, { useRecordId: true })
 * await exampleCollection.getAny("user123")
 */
export declare function createKeyValueStoreIdSchema(): IdSchema;
/**
 * Abstracts a collection of records stored in the local database, providing
 * CRUD operations and synchronization helpers.
 */
export default class Collection<B extends {
    id: string;
    last_modified?: number;
    _status?: RecordStatus;
} = any> {
    /**
     * Constructor.
     *
     * Options:
     * - `{BaseAdapter} adapter` The DB adapter (default: `IDB`)
     *
     * @param  {String}    bucket  The bucket identifier.
     * @param  {String}    name    The collection name.
     * @param  {KintoBase} kinto   The Kinto instance.
     * @param  {Object}    options The options object.
     */
    private _bucket;
    private _name;
    private _lastModified;
    db: BaseAdapter<B>;
    kinto: KintoBase<B>;
    events?: Emitter;
    idSchema: IdSchema;
    remoteTransformers: RemoteTransformer[];
    hooks: Hooks<B>;
    localFields: string[];
    constructor(bucket: string, name: string, kinto: KintoBase<B>, options?: {
        adapter?: (dbName: string, options?: {
            dbName?: string;
            migrateOldData?: boolean;
        }) => BaseAdapter<B>;
        adapterOptions?: {
            dbName?: string;
            migrateOldData?: boolean;
        };
        events?: Emitter;
        idSchema?: IdSchema;
        remoteTransformers?: RemoteTransformer[];
        hooks?: Hooks<B>;
        localFields?: string[];
    });
    /**
     * The HTTP client.
     * @type {KintoClient}
     */
    get api(): import("./http").default;
    /**
     * The collection name.
     * @type {String}
     */
    get name(): string;
    /**
     * The bucket name.
     * @type {String}
     */
    get bucket(): string;
    /**
     * The last modified timestamp.
     * @type {Number}
     */
    get lastModified(): number | null;
    /**
     * Synchronization strategies. Available strategies are:
     *
     * - `MANUAL`: Conflicts will be reported in a dedicated array.
     * - `SERVER_WINS`: Conflicts are resolved using remote data.
     * - `CLIENT_WINS`: Conflicts are resolved using local data.
     *
     * @type {Object}
     */
    static get strategy(): {
        CLIENT_WINS: string;
        SERVER_WINS: string;
        PULL_ONLY: string;
        MANUAL: string;
    };
    /**
     * Validates an idSchema.
     *
     * @param  {Object|undefined} idSchema
     * @return {Object}
     */
    private _validateIdSchema;
    /**
     * Validates a list of remote transformers.
     *
     * @param  {Array|undefined} remoteTransformers
     * @return {Array}
     */
    private _validateRemoteTransformers;
    /**
     * Validate the passed hook is correct.
     *
     * @param {Array|undefined} hook.
     * @return {Array}
     **/
    private _validateHook;
    /**
     * Validates a list of hooks.
     *
     * @param  {Object|undefined} hooks
     * @return {Object}
     */
    private _validateHooks;
    /**
     * Deletes every records in the current collection and marks the collection as
     * never synced.
     *
     * @return {Promise}
     */
    clear(): Promise<KintoRepresentation<{}[]>>;
    /**
     * Encodes a record.
     *
     * @param  {String} type   Either "remote" or "local".
     * @param  {Object} record The record object to encode.
     * @return {Promise}
     */
    private _encodeRecord;
    /**
     * Decodes a record.
     *
     * @param  {String} type   Either "remote" or "local".
     * @param  {Object} record The record object to decode.
     * @return {Promise}
     */
    private _decodeRecord;
    /**
     * Adds a record to the local database, asserting that none
     * already exist with this ID.
     *
     * Note: If either the `useRecordId` or `synced` options are true, then the
     * record object must contain the id field to be validated. If none of these
     * options are true, an id is generated using the current IdSchema; in this
     * case, the record passed must not have an id.
     *
     * Options:
     * - {Boolean} synced       Sets record status to "synced" (default: `false`).
     * - {Boolean} useRecordId  Forces the `id` field from the record to be used,
     *                          instead of one that is generated automatically
     *                          (default: `false`).
     *
     * @param  {Object} record
     * @param  {Object} options
     * @return {Promise}
     */
    create(record: WithOptional<B, "id">, options?: {
        useRecordId?: boolean;
        synced?: boolean;
    }): Promise<KintoRepresentation<B>>;
    /**
     * Like {@link CollectionTransaction#update}, but wrapped in its own transaction.
     *
     * Options:
     * - {Boolean} synced: Sets record status to "synced" (default: false)
     * - {Boolean} patch:  Extends the existing record instead of overwriting it
     *   (default: false)
     *
     * @param  {Object} record
     * @param  {Object} options
     * @return {Promise}
     */
    update(record: B & {
        id: string;
    }, options?: {
        synced?: boolean;
        patch?: boolean;
    }): Promise<UpdateRepresentation<B>>;
    /**
     * Like {@link CollectionTransaction#upsert}, but wrapped in its own transaction.
     *
     * @param  {Object} record
     * @return {Promise}
     */
    upsert(record: B & {
        id: string;
    }): Promise<WithOptional<UpdateRepresentation<B>, "oldRecord">>;
    /**
     * Like {@link CollectionTransaction#get}, but wrapped in its own transaction.
     *
     * Options:
     * - {Boolean} includeDeleted: Include virtually deleted records.
     *
     * @param  {String} id
     * @param  {Object} options
     * @return {Promise}
     */
    get(id: string, options?: {
        includeDeleted: boolean;
    }): Promise<KintoRepresentation<B>>;
    /**
     * Like {@link CollectionTransaction#getAny}, but wrapped in its own transaction.
     *
     * @param  {String} id
     * @return {Promise}
     */
    getAny(id: string): Promise<UndefiendKintoRepresentation<B>>;
    /**
     * Same as {@link Collection#delete}, but wrapped in its own transaction.
     *
     * Options:
     * - {Boolean} virtual: When set to `true`, doesn't actually delete the record,
     *   update its `_status` attribute to `deleted` instead (default: true)
     *
     * @param  {String} id       The record's Id.
     * @param  {Object} options  The options object.
     * @return {Promise}
     */
    delete(id: string, options?: {
        virtual: boolean;
    }): Promise<KintoRepresentation<B>>;
    /**
     * Same as {@link Collection#deleteAll}, but wrapped in its own transaction, execulding the parameter.
     *
     * @return {Promise}
     */
    deleteAll(): Promise<KintoRepresentation<B[]>>;
    /**
     * The same as {@link CollectionTransaction#deleteAny}, but wrapped
     * in its own transaction.
     *
     * @param  {String} id       The record's Id.
     * @return {Promise}
     */
    deleteAny(id: string): Promise<KintoRepresentation<B> & {
        deleted: boolean;
    }>;
    /**
     * Lists records from the local database.
     *
     * Params:
     * - {Object} filters Filter the results (default: `{}`).
     * - {String} order   The order to apply   (default: `-last_modified`).
     *
     * Options:
     * - {Boolean} includeDeleted: Include virtually deleted records.
     *
     * @param  {Object} params  The filters and order to apply to the results.
     * @param  {Object} options The options object.
     * @return {Promise}
     */
    list(params?: {
        filters?: {
            [key: string]: any;
        };
        order?: string;
    }, options?: {
        includeDeleted: boolean;
    }): Promise<KintoRepresentation<B[]>>;
    /**
     * Imports remote changes into the local database.
     * This method is in charge of detecting the conflicts, and resolve them
     * according to the specified strategy.
     * @param  {SyncResultObject} syncResultObject The sync result object.
     * @param  {Array}            decodedChanges   The list of changes to import in the local database.
     * @param  {String}           strategy         The {@link Collection.strategy} (default: MANUAL)
     * @return {Promise}
     */
    importChanges(syncResultObject: SyncResultObject, decodedChanges: any[], strategy?: string): Promise<SyncResultObject>;
    /**
     * Imports the responses of pushed changes into the local database.
     * Basically it stores the timestamp assigned by the server into the local
     * database.
     * @param  {SyncResultObject} syncResultObject The sync result object.
     * @param  {Array}            toApplyLocally   The list of changes to import in the local database.
     * @param  {Array}            conflicts        The list of conflicts that have to be resolved.
     * @param  {String}           strategy         The {@link Collection.strategy}.
     * @return {Promise}
     */
    private _applyPushedResults;
    /**
     * Handles synchronization conflicts according to specified strategy.
     *
     * @param  {SyncResultObject} result    The sync result object.
     * @param  {String}           strategy  The {@link Collection.strategy}.
     * @return {Promise<Array<Object>>} The resolved conflicts, as an
     *    array of {accepted, rejected} objects
     */
    private _handleConflicts;
    /**
     * Execute a bunch of operations in a transaction.
     *
     * This transaction should be atomic -- either all of its operations
     * will succeed, or none will.
     *
     * The argument to this function is itself a function which will be
     * called with a {@link CollectionTransaction}. Collection methods
     * are available on this transaction, but instead of returning
     * promises, they are synchronous. execute() returns a Promise whose
     * value will be the return value of the provided function.
     *
     * Most operations will require access to the record itself, which
     * must be preloaded by passing its ID in the preloadIds option.
     *
     * Options:
     * - {Array} preloadIds: list of IDs to fetch at the beginning of
     *   the transaction
     *
     * @return {Promise} Resolves with the result of the given function
     *    when the transaction commits.
     */
    execute<R>(doOperations: (proxy: CollectionTransaction<B>) => R, { preloadIds }?: {
        preloadIds?: string[];
    }): Promise<R>;
    /**
     * Resets the local records as if they were never synced; existing records are
     * marked as newly created, deleted records are dropped.
     *
     * A next call to {@link Collection.sync} will thus republish the whole
     * content of the local collection to the server.
     *
     * @return {Promise} Resolves with the number of processed records.
     */
    resetSyncStatus(): Promise<number>;
    /**
     * Returns an object containing two lists:
     *
     * - `toDelete`: unsynced deleted records we can safely delete;
     * - `toSync`: local updates to send to the server.
     *
     * @return {Promise}
     */
    gatherLocalChanges(): Promise<unknown[]>;
    /**
     * Fetch remote changes, import them to the local database, and handle
     * conflicts according to `options.strategy`. Then, updates the passed
     * {@link SyncResultObject} with import results.
     *
     * Options:
     * - {String} strategy: The selected sync strategy.
     * - {String} expectedTimestamp: A timestamp to use as a "cache busting" query parameter.
     * - {Array<String>} exclude: A list of record ids to exclude from pull.
     * - {Object} headers: The HTTP headers to use in the request.
     * - {int} retry: The number of retries to do if the HTTP request fails.
     * - {int} lastModified: The timestamp to use in `?_since` query.
     *
     * @param  {KintoClient.Collection} client           Kinto client Collection instance.
     * @param  {SyncResultObject}       syncResultObject The sync result object.
     * @param  {Object}                 options          The options object.
     * @return {Promise}
     */
    pullChanges(client: KintoCollection, syncResultObject: SyncResultObject, options?: {
        exclude?: any[];
        strategy?: string;
        lastModified?: number | null;
        headers?: Record<string, string>;
        expectedTimestamp?: string | null;
        retry?: number;
    }): Promise<SyncResultObject>;
    applyHook(hookName: AvailableHook, payload: any): Promise<{
        changes: B[];
    }>;
    /**
     * Publish local changes to the remote server and updates the passed
     * {@link SyncResultObject} with publication results.
     *
     * Options:
     * - {String} strategy: The selected sync strategy.
     * - {Object} headers: The HTTP headers to use in the request.
     * - {int} retry: The number of retries to do if the HTTP request fails.
     *
     * @param  {KintoClient.Collection} client           Kinto client Collection instance.
     * @param  {SyncResultObject}       syncResultObject The sync result object.
     * @param  {Object}                 changes          The change object.
     * @param  {Array}                  changes.toDelete The list of records to delete.
     * @param  {Array}                  changes.toSync   The list of records to create/update.
     * @param  {Object}                 options          The options object.
     * @return {Promise}
     */
    pushChanges(client: KintoCollection, changes: any, syncResultObject: SyncResultObject, options?: {
        strategy?: string;
        headers?: Record<string, string>;
        retry?: number;
    }): Promise<SyncResultObject>;
    /**
     * Return a copy of the specified record without the local fields.
     *
     * @param  {Object} record  A record with potential local fields.
     * @return {Object}
     */
    cleanLocalFields(record: B): Omit<B, string>;
    /**
     * Resolves a conflict, updating local record according to proposed
     * resolution — keeping remote record `last_modified` value as a reference for
     * further batch sending.
     *
     * @param  {Object} conflict   The conflict object.
     * @param  {Object} resolution The proposed record.
     * @return {Promise}
     */
    resolve(conflict: Conflict<B>, resolution: B): Promise<KintoRepresentation<B>>;
    /**
     * @private
     */
    private _resolveRaw;
    /**
     * Synchronize remote and local data. The promise will resolve with a
     * {@link SyncResultObject}, though will reject:
     *
     * - if the server is currently backed off;
     * - if the server has been detected flushed.
     *
     * Options:
     * - {Object} headers: HTTP headers to attach to outgoing requests.
     * - {String} expectedTimestamp: A timestamp to use as a "cache busting" query parameter.
     * - {Number} retry: Number of retries when server fails to process the request (default: 1).
     * - {Collection.strategy} strategy: See {@link Collection.strategy}.
     * - {Boolean} ignoreBackoff: Force synchronization even if server is currently
     *   backed off.
     * - {String} bucket: The remove bucket id to use (default: null)
     * - {String} collection: The remove collection id to use (default: null)
     * - {String} remote The remote Kinto server endpoint to use (default: null).
     *
     * @param  {Object} options Options.
     * @return {Promise}
     * @throws {Error} If an invalid remote option is passed.
     */
    sync(options?: CollectionSyncOptions): Promise<SyncResultObject>;
    /**
     * Load a list of records already synced with the remote server.
     *
     * The local records which are unsynced or whose timestamp is either missing
     * or superior to those being loaded will be ignored.
     *
     * @deprecated Use {@link importBulk} instead.
     * @param  {Array} records The previously exported list of records to load.
     * @return {Promise} with the effectively imported records.
     */
    loadDump(records: (B & {
        last_modified: number;
    })[]): Promise<B[]>;
    /**
     * Load a list of records already synced with the remote server.
     *
     * The local records which are unsynced or whose timestamp is either missing
     * or superior to those being loaded will be ignored.
     *
     * @param  {Array} records The previously exported list of records to load.
     * @return {Promise} with the effectively imported records.
     */
    importBulk(records: (B & {
        last_modified: number;
    })[]): Promise<B[]>;
    pullMetadata(client: KintoCollection, options?: {
        expectedTimestamp?: string | null;
        headers?: Record<string, string>;
    }): Promise<{
        [key: string]: unknown;
    } | null>;
    metadata(): Promise<unknown>;
}
/**
 * A Collection-oriented wrapper for an adapter's transaction.
 *
 * This defines the high-level functions available on a collection.
 * The collection itself offers functions of the same name. These will
 * perform just one operation in its own transaction.
 */
export declare class CollectionTransaction<B extends {
    id: string;
    last_modified?: number;
    _status?: RecordStatus;
}> {
    collection: Collection<B>;
    adapterTransaction: StorageProxy<B>;
    private _events;
    constructor(collection: Collection<B>, adapterTransaction: StorageProxy<B>);
    private _queueEvent;
    /**
     * Emit queued events, to be called once every transaction operations have
     * been executed successfully.
     */
    emitEvents(): void;
    /**
     * Retrieve a record by its id from the local database, or
     * undefined if none exists.
     *
     * This will also return virtually deleted records.
     *
     * @param  {String} id
     * @return {Object}
     */
    getAny(id: string): UndefiendKintoRepresentation<B>;
    /**
     * Retrieve a record by its id from the local database.
     *
     * Options:
     * - {Boolean} includeDeleted: Include virtually deleted records.
     *
     * @param  {String} id
     * @param  {Object} options
     * @return {Object}
     */
    get(id: string, options?: {
        includeDeleted: boolean;
    }): KintoRepresentation<B>;
    /**
     * Deletes a record from the local database.
     *
     * Options:
     * - {Boolean} virtual: When set to `true`, doesn't actually delete the record,
     *   update its `_status` attribute to `deleted` instead (default: true)
     *
     * @param  {String} id       The record's Id.
     * @param  {Object} options  The options object.
     * @return {Object}
     */
    delete(id: string, options?: {
        virtual: boolean;
    }): KintoRepresentation<B>;
    /**
     * Soft delete all records from the local database.
     *
     * @param  {Array} ids        Array of non-deleted Record Ids.
     * @return {Object}
     */
    deleteAll(ids: string[]): KintoRepresentation<B[]>;
    /**
     * Deletes a record from the local database, if any exists.
     * Otherwise, do nothing.
     *
     * @param  {String} id       The record's Id.
     * @return {Object}
     */
    deleteAny(id: string): KintoRepresentation<B> & {
        deleted: boolean;
    };
    /**
     * Adds a record to the local database, asserting that none
     * already exist with this ID.
     *
     * @param  {Object} record, which must contain an ID
     * @return {Object}
     */
    create(record: B): KintoRepresentation<B>;
    /**
     * Updates a record from the local database.
     *
     * Options:
     * - {Boolean} synced: Sets record status to "synced" (default: false)
     * - {Boolean} patch:  Extends the existing record instead of overwriting it
     *   (default: false)
     *
     * @param  {Object} record
     * @param  {Object} options
     * @return {Object}
     */
    update(record: B & {
        id: string;
    }, options?: {
        synced: boolean;
        patch: boolean;
    }): UpdateRepresentation<B>;
    /**
     * Lower-level primitive for updating a record while respecting
     * _status and last_modified.
     *
     * @param  {Object} oldRecord: the record retrieved from the DB
     * @param  {Object} newRecord: the record to replace it with
     * @return {Object}
     */
    private _updateRaw;
    /**
     * Upsert a record into the local database.
     *
     * This record must have an ID.
     *
     * If a record with this ID already exists, it will be replaced.
     * Otherwise, this record will be inserted.
     *
     * @param  {Object} record
     * @return {Object}
     */
    upsert(record: B & {
        id: string;
    }): WithOptional<UpdateRepresentation<B>, "oldRecord">;
}
