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(type: K, entries: SyncResult[K] | SyncResult[K][0]): SyncResultObject; get ok(): boolean; get errors(): KintoError[]; get conflicts(): Conflict[]; get skipped(): any[]; get resolved(): any[]; get created(): any[]; get updated(): import("./types").Update[]; 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 { /** * 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; kinto: KintoBase; events?: Emitter; idSchema: IdSchema; remoteTransformers: RemoteTransformer[]; hooks: Hooks; localFields: string[]; constructor(bucket: string, name: string, kinto: KintoBase, options?: { adapter?: (dbName: string, options?: { dbName?: string; migrateOldData?: boolean; }) => BaseAdapter; adapterOptions?: { dbName?: string; migrateOldData?: boolean; }; events?: Emitter; idSchema?: IdSchema; remoteTransformers?: RemoteTransformer[]; hooks?: Hooks; 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>; /** * 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, options?: { useRecordId?: boolean; synced?: boolean; }): Promise>; /** * 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>; /** * Like {@link CollectionTransaction#upsert}, but wrapped in its own transaction. * * @param {Object} record * @return {Promise} */ upsert(record: B & { id: string; }): Promise, "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>; /** * Like {@link CollectionTransaction#getAny}, but wrapped in its own transaction. * * @param {String} id * @return {Promise} */ getAny(id: string): Promise>; /** * 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>; /** * Same as {@link Collection#deleteAll}, but wrapped in its own transaction, execulding the parameter. * * @return {Promise} */ deleteAll(): Promise>; /** * 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 & { 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>; /** * 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; /** * 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>} 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(doOperations: (proxy: CollectionTransaction) => R, { preloadIds }?: { preloadIds?: string[]; }): Promise; /** * 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; /** * 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; /** * 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} 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; expectedTimestamp?: string | null; retry?: number; }): Promise; 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; retry?: number; }): Promise; /** * 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; /** * 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, resolution: B): Promise>; /** * @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; /** * 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; /** * 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; pullMetadata(client: KintoCollection, options?: { expectedTimestamp?: string | null; headers?: Record; }): Promise<{ [key: string]: unknown; } | null>; metadata(): Promise; } /** * 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 { collection: Collection; adapterTransaction: StorageProxy; private _events; constructor(collection: Collection, adapterTransaction: StorageProxy); 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; /** * 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; /** * 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; /** * Soft delete all records from the local database. * * @param {Array} ids Array of non-deleted Record Ids. * @return {Object} */ deleteAll(ids: string[]): KintoRepresentation; /** * 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 & { 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; /** * 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; /** * 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, "oldRecord">; }