diff --git a/dist/client/triplit-client.d.ts b/dist/client/triplit-client.d.ts index 85dc8f6d97ded0e0e4e7bfdfedb1d02ea33405d7..dd9e6e78114f174e97f28cc9e6ac95e3d3037d44 100644 --- a/dist/client/triplit-client.d.ts +++ b/dist/client/triplit-client.d.ts @@ -15,6 +15,7 @@ export declare class TriplitClient = Models> { * The sync engine is responsible for managing the connection to the server and syncing data */ syncEngine: SyncEngine; + private hasPendingWrites; private _token; private claimsPath; private _serverUrl; @@ -36,6 +37,11 @@ export declare class TriplitClient = Models> { */ constructor(options?: ClientOptions); get ready(): Promise; + /** + * Flushes updates to the database and syncs with the server. This function may be a no-op if no + * writes have been made since the last flush. + */ + flush(syncWrites?: boolean): Promise; /** * Gets the schema of the database * @@ -99,7 +105,7 @@ export declare class TriplitClient = Models> { * * @param collectionName - The name of the collection to insert into * @param object - The entity to insert - * @returns The transaction ID and the inserted entity, if successful + * @returns - The inserted entity, if successful */ insert>(collectionName: CN, object: WriteModel): Promise>>; /** @@ -108,7 +114,6 @@ export declare class TriplitClient = Models> { * @param collectionName - The name of the collection to update * @param entityId - The id of the entity to update * @param updater - A function that provides the current entity and allows you to modify it - * @returns The transaction ID */ update>(collectionName: CN, entityId: string, data: UpdatePayload): Promise; /** @@ -116,7 +121,6 @@ export declare class TriplitClient = Models> { * * @param collectionName - The name of the collection to delete from * @param entityId - The id of the entity to delete - * @returns The transaction ID */ delete>(collectionName: CN, entityId: string): Promise; entityIsInCache(collection: string, entityId: string): Promise; diff --git a/dist/client/triplit-client.js b/dist/client/triplit-client.js index c1f54b5b9abb11c4c983cf368d66c8d22379172a..4b9b19f7cf65a603e228b9aec68c1a1218b91eb2 100644 --- a/dist/client/triplit-client.js +++ b/dist/client/triplit-client.js @@ -23,6 +23,7 @@ export class TriplitClient { * The sync engine is responsible for managing the connection to the server and syncing data */ syncEngine; + hasPendingWrites = false; _token = undefined; claimsPath = undefined; _serverUrl = undefined; @@ -69,13 +70,21 @@ export class TriplitClient { this.db = decoded ? this.db.withSessionVars(decoded) : this.db; } }); - this.db.onCommit( - // @ts-expect-error - throttle(async (tx) => { - await this.db.updateQueryViews(); - this.db.broadcastToQuerySubscribers(); - await this.syncEngine.syncWrites(); - }, 20, { leading: false, trailing: true })); + let writeTimeout = undefined; + this.db.onCommit(async () => { + this.hasPendingWrites = true; + if (writeTimeout) { + clearTimeout(writeTimeout); + } + else { + // on the very first write in a batch, flush without writing to the server + await this.flush(false); + } + writeTimeout = setTimeout(() => { + this.flush(); + writeTimeout = undefined; + }, 20); + }); this.db.onSchemaChange((change) => { if (change.successful) { this.http.updateOptions({ @@ -155,6 +164,20 @@ export class TriplitClient { return this.awaitReady; return Promise.resolve(); } + /** + * Flushes updates to the database and syncs with the server. This function may be a no-op if no + * writes have been made since the last flush. + */ + async flush(syncWrites = true) { + if (!this.hasPendingWrites) + return; + await this.db.updateQueryViews(); + this.db.broadcastToQuerySubscribers(); + if (syncWrites) { + await this.syncEngine.syncWrites(); + this.hasPendingWrites = false; + } + } /** * Gets the schema of the database * @@ -314,7 +337,7 @@ export class TriplitClient { * * @param collectionName - The name of the collection to insert into * @param object - The entity to insert - * @returns The transaction ID and the inserted entity, if successful + * @returns - The inserted entity, if successful */ async insert(collectionName, object) { if (this.awaitReady) @@ -332,7 +355,6 @@ export class TriplitClient { * @param collectionName - The name of the collection to update * @param entityId - The id of the entity to update * @param updater - A function that provides the current entity and allows you to modify it - * @returns The transaction ID */ async update(collectionName, entityId, data) { if (this.awaitReady) @@ -349,7 +371,6 @@ export class TriplitClient { * * @param collectionName - The name of the collection to delete from * @param entityId - The id of the entity to delete - * @returns The transaction ID */ async delete(collectionName, entityId) { if (this.awaitReady) @@ -976,32 +997,6 @@ function flipOrder(order) { return undefined; return order.map((o) => [o[0], o[1] === 'ASC' ? 'DESC' : 'ASC']); } -function throttle(func, limit, options) { - let inThrottle; - let lastArgs = null; - return function () { - const args = arguments; - if (!inThrottle) { - if (options?.leading !== false) { - func(args); - } - else { - lastArgs = args; - } - inThrottle = true; - setTimeout(() => { - if (options?.trailing && lastArgs) { - func(lastArgs); - lastArgs = null; - } - inThrottle = false; - }, limit); - } - else { - lastArgs = args; - } - }; -} function validateServerUrl(serverUrl) { if (serverUrl && !serverUrl.startsWith('http://') &&