Skip to content

Commit b569cb7

Browse files
committed
Merge branch 'main' into sync-progress
2 parents ed11438 + fc90fba commit b569cb7

File tree

26 files changed

+398
-113
lines changed

26 files changed

+398
-113
lines changed

packages/attachments/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"test": "pnpm build && vitest"
3030
},
3131
"peerDependencies": {
32-
"@powersync/common": "workspace:^1.27.0"
32+
"@powersync/common": "workspace:^1.27.1"
3333
},
3434
"devDependencies": {
3535
"@powersync/common": "workspace:*",

packages/common/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# @powersync/common
22

3+
## 1.27.1
4+
5+
### Patch Changes
6+
7+
- 720ad7a: Fix a race condition causing sync changes during uploads not to be applied.
8+
39
## 1.27.0
410

511
### Minor Changes

packages/common/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@powersync/common",
3-
"version": "1.27.0",
3+
"version": "1.27.1",
44
"publishConfig": {
55
"registry": "https://registry.npmjs.org/",
66
"access": "public"

packages/common/src/client/AbstractPowerSyncDatabase.ts

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { Schema } from '../db/schema/Schema.js';
1515
import { BaseObserver } from '../utils/BaseObserver.js';
1616
import { ControlledExecutor } from '../utils/ControlledExecutor.js';
1717
import { mutexRunExclusive } from '../utils/mutex.js';
18-
import { throttleTrailing } from '../utils/throttle.js';
18+
import { throttleTrailing } from '../utils/async.js';
1919
import { SQLOpenFactory, SQLOpenOptions, isDBAdapter, isSQLOpenFactory, isSQLOpenOptions } from './SQLOpenFactory.js';
2020
import { PowerSyncBackendConnector } from './connection/PowerSyncBackendConnector.js';
2121
import { runOnSchemaChange } from './runOnSchemaChange.js';
@@ -263,7 +263,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
263263
/**
264264
* Wait for the first sync operation to complete.
265265
*
266-
* @argument request Either an abort signal (after which the promise will complete regardless of
266+
* @param request Either an abort signal (after which the promise will complete regardless of
267267
* whether a full sync was completed) or an object providing an abort signal and a priority target.
268268
* When a priority target is set, the promise may complete when all buckets with the given (or higher)
269269
* priorities have been synchronized. This can be earlier than a complete sync.
@@ -536,7 +536,7 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
536536
}
537537

538538
/**
539-
* Get a batch of crud data to upload.
539+
* Get a batch of CRUD data to upload.
540540
*
541541
* Returns null if there is no data to upload.
542542
*
@@ -551,6 +551,9 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
551551
* This method does include transaction ids in the result, but does not group
552552
* data by transaction. One batch may contain data from multiple transactions,
553553
* and a single transaction may be split over multiple batches.
554+
*
555+
* @param limit Maximum number of CRUD entries to include in the batch
556+
* @returns A batch of CRUD operations to upload, or null if there are none
554557
*/
555558
async getCrudBatch(limit: number = DEFAULT_CRUD_BATCH_LIMIT): Promise<CrudBatch | null> {
556559
const result = await this.getAll<CrudEntryJSON>(
@@ -587,6 +590,8 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
587590
*
588591
* Unlike {@link getCrudBatch}, this only returns data from a single transaction at a time.
589592
* All data for the transaction is loaded into memory.
593+
*
594+
* @returns A transaction of CRUD operations to upload, or null if there are none
590595
*/
591596
async getNextCrudTransaction(): Promise<CrudTransaction | null> {
592597
return await this.readTransaction(async (tx) => {
@@ -624,6 +629,8 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
624629
* Get an unique client id for this database.
625630
*
626631
* The id is not reset when the database is cleared, only when the database is deleted.
632+
*
633+
* @returns A unique identifier for the database instance
627634
*/
628635
async getClientId(): Promise<string> {
629636
return this.bucketStorageAdapter.getClientId();
@@ -648,14 +655,27 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
648655
}
649656

650657
/**
651-
* Execute a write (INSERT/UPDATE/DELETE) query
658+
* Execute a SQL write (INSERT/UPDATE/DELETE) query
652659
* and optionally return results.
660+
*
661+
* @param sql The SQL query to execute
662+
* @param parameters Optional array of parameters to bind to the query
663+
* @returns The query result as an object with structured key-value pairs
653664
*/
654665
async execute(sql: string, parameters?: any[]) {
655666
await this.waitForReady();
656667
return this.database.execute(sql, parameters);
657668
}
658669

670+
/**
671+
* Execute a SQL write (INSERT/UPDATE/DELETE) query directly on the database without any PowerSync processing.
672+
* This bypasses certain PowerSync abstractions and is useful for accessing the raw database results.
673+
*
674+
* @param sql The SQL query to execute
675+
* @param parameters Optional array of parameters to bind to the query
676+
* @returns The raw query result from the underlying database as a nested array of raw values, where each row is
677+
* represented as an array of column values without field names.
678+
*/
659679
async executeRaw(sql: string, parameters?: any[]) {
660680
await this.waitForReady();
661681
return this.database.executeRaw(sql, parameters);
@@ -665,6 +685,10 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
665685
* Execute a write query (INSERT/UPDATE/DELETE) multiple times with each parameter set
666686
* and optionally return results.
667687
* This is faster than executing separately with each parameter set.
688+
*
689+
* @param sql The SQL query to execute
690+
* @param parameters Optional 2D array of parameter sets, where each inner array is a set of parameters for one execution
691+
* @returns The query result
668692
*/
669693
async executeBatch(sql: string, parameters?: any[][]) {
670694
await this.waitForReady();
@@ -673,6 +697,10 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
673697

674698
/**
675699
* Execute a read-only query and return results.
700+
*
701+
* @param sql The SQL query to execute
702+
* @param parameters Optional array of parameters to bind to the query
703+
* @returns An array of results
676704
*/
677705
async getAll<T>(sql: string, parameters?: any[]): Promise<T[]> {
678706
await this.waitForReady();
@@ -681,6 +709,10 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
681709

682710
/**
683711
* Execute a read-only query and return the first result, or null if the ResultSet is empty.
712+
*
713+
* @param sql The SQL query to execute
714+
* @param parameters Optional array of parameters to bind to the query
715+
* @returns The first result if found, or null if no results are returned
684716
*/
685717
async getOptional<T>(sql: string, parameters?: any[]): Promise<T | null> {
686718
await this.waitForReady();
@@ -689,6 +721,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
689721

690722
/**
691723
* Execute a read-only query and return the first result, error if the ResultSet is empty.
724+
*
725+
* @param sql The SQL query to execute
726+
* @param parameters Optional array of parameters to bind to the query
727+
* @returns The first result matching the query
728+
* @throws Error if no rows are returned
692729
*/
693730
async get<T>(sql: string, parameters?: any[]): Promise<T> {
694731
await this.waitForReady();
@@ -720,6 +757,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
720757
* Open a read-only transaction.
721758
* Read transactions can run concurrently to a write transaction.
722759
* Changes from any write transaction are not visible to read transactions started before it.
760+
*
761+
* @param callback Function to execute within the transaction
762+
* @param lockTimeout Time in milliseconds to wait for a lock before throwing an error
763+
* @returns The result of the callback
764+
* @throws Error if the lock cannot be obtained within the timeout period
723765
*/
724766
async readTransaction<T>(
725767
callback: (tx: Transaction) => Promise<T>,
@@ -740,6 +782,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
740782
* Open a read-write transaction.
741783
* This takes a global lock - only one write transaction can execute against the database at a time.
742784
* Statements within the transaction must be done on the provided {@link Transaction} interface.
785+
*
786+
* @param callback Function to execute within the transaction
787+
* @param lockTimeout Time in milliseconds to wait for a lock before throwing an error
788+
* @returns The result of the callback
789+
* @throws Error if the lock cannot be obtained within the timeout period
743790
*/
744791
async writeTransaction<T>(
745792
callback: (tx: Transaction) => Promise<T>,
@@ -814,6 +861,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
814861
* Source tables are automatically detected using `EXPLAIN QUERY PLAN`.
815862
*
816863
* Note that the `onChange` callback member of the handler is required.
864+
*
865+
* @param sql The SQL query to execute
866+
* @param parameters Optional array of parameters to bind to the query
867+
* @param handler Callbacks for handling results and errors
868+
* @param options Options for configuring watch behavior
817869
*/
818870
watchWithCallback(sql: string, parameters?: any[], handler?: WatchHandler, options?: SQLWatchOptions): void {
819871
const { onResult, onError = (e: Error) => this.options.logger?.error(e) } = handler ?? {};
@@ -859,6 +911,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
859911
* Execute a read query every time the source tables are modified.
860912
* Use {@link SQLWatchOptions.throttleMs} to specify the minimum interval between queries.
861913
* Source tables are automatically detected using `EXPLAIN QUERY PLAN`.
914+
*
915+
* @param sql The SQL query to execute
916+
* @param parameters Optional array of parameters to bind to the query
917+
* @param options Options for configuring watch behavior
918+
* @returns An AsyncIterable that yields QueryResults whenever the data changes
862919
*/
863920
watchWithAsyncGenerator(sql: string, parameters?: any[], options?: SQLWatchOptions): AsyncIterable<QueryResult> {
864921
return new EventIterator<QueryResult>((eventOptions) => {
@@ -879,6 +936,16 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
879936
});
880937
}
881938

939+
/**
940+
* Resolves the list of tables that are used in a SQL query.
941+
* If tables are specified in the options, those are used directly.
942+
* Otherwise, analyzes the query using EXPLAIN to determine which tables are accessed.
943+
*
944+
* @param sql The SQL query to analyze
945+
* @param parameters Optional parameters for the SQL query
946+
* @param options Optional watch options that may contain explicit table list
947+
* @returns Array of table names that the query depends on
948+
*/
882949
async resolveTables(sql: string, parameters?: any[], options?: SQLWatchOptions): Promise<string[]> {
883950
const resolvedTables = options?.tables ? [...options.tables] : [];
884951
if (!options?.tables) {
@@ -951,7 +1018,9 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
9511018
*
9521019
* Note that the `onChange` callback member of the handler is required.
9531020
*
954-
* Returns dispose function to stop watching.
1021+
* @param handler Callbacks for handling change events and errors
1022+
* @param options Options for configuring watch behavior
1023+
* @returns A dispose function to stop watching for changes
9551024
*/
9561025
onChangeWithCallback(handler?: WatchOnChangeHandler, options?: SQLWatchOptions): () => void {
9571026
const { onChange, onError = (e: Error) => this.options.logger?.error(e) } = handler ?? {};
@@ -1004,8 +1073,11 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
10041073
*
10051074
* This is preferred over {@link watchWithAsyncGenerator} when multiple queries need to be performed
10061075
* together when data is changed.
1076+
*
1077+
* Note: do not declare this as `async *onChange` as it will not work in React Native.
10071078
*
1008-
* Note, do not declare this as `async *onChange` as it will not work in React Native
1079+
* @param options Options for configuring watch behavior
1080+
* @returns An AsyncIterable that yields change events whenever the specified tables change
10091081
*/
10101082
onChangeWithAsyncGenerator(options?: SQLWatchOptions): AsyncIterable<WatchOnChangeEvent> {
10111083
const resolvedOptions = options ?? {};

0 commit comments

Comments
 (0)