@powersync/common 1.20.2 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.mjs +3 -3
- package/lib/client/AbstractPowerSyncDatabase.d.ts +1 -0
- package/lib/client/AbstractPowerSyncDatabase.js +20 -13
- package/lib/client/compilableQueryWatch.d.ts +7 -0
- package/lib/client/compilableQueryWatch.js +37 -0
- package/lib/client/runOnSchemaChange.d.ts +2 -0
- package/lib/client/runOnSchemaChange.js +23 -0
- package/lib/db/DBAdapter.d.ts +4 -0
- package/lib/db/schema/Schema.d.ts +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/package.json +1 -1
|
@@ -14,6 +14,7 @@ import { CrudBatch } from './sync/bucket/CrudBatch.js';
|
|
|
14
14
|
import { CrudEntry } from './sync/bucket/CrudEntry.js';
|
|
15
15
|
import { CrudTransaction } from './sync/bucket/CrudTransaction.js';
|
|
16
16
|
import { DEFAULT_CRUD_UPLOAD_THROTTLE_MS } from './sync/stream/AbstractStreamingSyncImplementation.js';
|
|
17
|
+
import { runOnSchemaChange } from './runOnSchemaChange.js';
|
|
17
18
|
const POWERSYNC_TABLE_MATCH = /(^ps_data__|^ps_data_local__)/;
|
|
18
19
|
const DEFAULT_DISCONNECT_CLEAR_OPTIONS = {
|
|
19
20
|
clearLocal: true
|
|
@@ -211,6 +212,8 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
211
212
|
}
|
|
212
213
|
this._schema = schema;
|
|
213
214
|
await this.database.execute('SELECT powersync_replace_schema(?)', [JSON.stringify(this.schema.toJSON())]);
|
|
215
|
+
await this.database.refreshSchema();
|
|
216
|
+
this.iterateListeners(async (cb) => cb.schemaChanged?.(schema));
|
|
214
217
|
}
|
|
215
218
|
/**
|
|
216
219
|
* Wait for initialization to complete.
|
|
@@ -503,7 +506,7 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
503
506
|
if (!onResult) {
|
|
504
507
|
throw new Error('onResult is required');
|
|
505
508
|
}
|
|
506
|
-
|
|
509
|
+
const watchQuery = async (abortSignal) => {
|
|
507
510
|
try {
|
|
508
511
|
const resolvedTables = await this.resolveTables(sql, parameters, options);
|
|
509
512
|
// Fetch initial data
|
|
@@ -522,13 +525,16 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
522
525
|
onError
|
|
523
526
|
}, {
|
|
524
527
|
...(options ?? {}),
|
|
525
|
-
tables: resolvedTables
|
|
528
|
+
tables: resolvedTables,
|
|
529
|
+
// Override the abort signal since we intercept it
|
|
530
|
+
signal: abortSignal
|
|
526
531
|
});
|
|
527
532
|
}
|
|
528
533
|
catch (error) {
|
|
529
534
|
onError?.(error);
|
|
530
535
|
}
|
|
531
|
-
}
|
|
536
|
+
};
|
|
537
|
+
runOnSchemaChange(watchQuery, this, options);
|
|
532
538
|
}
|
|
533
539
|
/**
|
|
534
540
|
* Execute a read query every time the source tables are modified.
|
|
@@ -537,17 +543,18 @@ export class AbstractPowerSyncDatabase extends BaseObserver {
|
|
|
537
543
|
*/
|
|
538
544
|
watchWithAsyncGenerator(sql, parameters, options) {
|
|
539
545
|
return new EventIterator((eventOptions) => {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
tables: resolvedTables
|
|
547
|
-
})) {
|
|
548
|
-
eventOptions.push(await this.executeReadOnly(sql, parameters));
|
|
546
|
+
const handler = {
|
|
547
|
+
onResult: (result) => {
|
|
548
|
+
eventOptions.push(result);
|
|
549
|
+
},
|
|
550
|
+
onError: (error) => {
|
|
551
|
+
eventOptions.fail(error);
|
|
549
552
|
}
|
|
550
|
-
}
|
|
553
|
+
};
|
|
554
|
+
this.watchWithCallback(sql, parameters, handler, options);
|
|
555
|
+
options?.signal?.addEventListener('abort', () => {
|
|
556
|
+
eventOptions.stop();
|
|
557
|
+
});
|
|
551
558
|
});
|
|
552
559
|
}
|
|
553
560
|
async resolveTables(sql, parameters, options) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CompilableQuery } from './../types/types.js';
|
|
2
|
+
import { AbstractPowerSyncDatabase, SQLWatchOptions } from './AbstractPowerSyncDatabase.js';
|
|
3
|
+
export interface CompilableQueryWatchHandler<T> {
|
|
4
|
+
onResult: (results: T[]) => void;
|
|
5
|
+
onError?: (error: Error) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function compilableQueryWatch<T>(db: AbstractPowerSyncDatabase, query: CompilableQuery<T>, handler: CompilableQueryWatchHandler<T>, options?: SQLWatchOptions): void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { runOnSchemaChange } from './runOnSchemaChange.js';
|
|
2
|
+
export function compilableQueryWatch(db, query, handler, options) {
|
|
3
|
+
const { onResult, onError = (e) => { } } = handler ?? {};
|
|
4
|
+
if (!onResult) {
|
|
5
|
+
throw new Error('onResult is required');
|
|
6
|
+
}
|
|
7
|
+
const watchQuery = async (abortSignal) => {
|
|
8
|
+
try {
|
|
9
|
+
const toSql = query.compile();
|
|
10
|
+
const resolvedTables = await db.resolveTables(toSql.sql, toSql.parameters, options);
|
|
11
|
+
// Fetch initial data
|
|
12
|
+
const result = await query.execute();
|
|
13
|
+
onResult(result);
|
|
14
|
+
db.onChangeWithCallback({
|
|
15
|
+
onChange: async () => {
|
|
16
|
+
try {
|
|
17
|
+
const result = await query.execute();
|
|
18
|
+
onResult(result);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
onError(error);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
onError
|
|
25
|
+
}, {
|
|
26
|
+
...(options ?? {}),
|
|
27
|
+
tables: resolvedTables,
|
|
28
|
+
// Override the abort signal since we intercept it
|
|
29
|
+
signal: abortSignal
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
onError(error);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
runOnSchemaChange(watchQuery, db, options);
|
|
37
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function runOnSchemaChange(callback, db, options) {
|
|
2
|
+
const triggerWatchedQuery = () => {
|
|
3
|
+
const abortController = new AbortController();
|
|
4
|
+
let disposeSchemaListener = null;
|
|
5
|
+
const stopWatching = () => {
|
|
6
|
+
abortController.abort('Abort triggered');
|
|
7
|
+
disposeSchemaListener?.();
|
|
8
|
+
disposeSchemaListener = null;
|
|
9
|
+
// Stop listening to upstream abort for this watch
|
|
10
|
+
options?.signal?.removeEventListener('abort', stopWatching);
|
|
11
|
+
};
|
|
12
|
+
options?.signal?.addEventListener('abort', stopWatching);
|
|
13
|
+
disposeSchemaListener = db.registerListener({
|
|
14
|
+
schemaChanged: async () => {
|
|
15
|
+
stopWatching();
|
|
16
|
+
// Re trigger the watched query (recursively), setTimeout ensures that we don't modify the list of listeners while iterating through them
|
|
17
|
+
setTimeout(() => triggerWatchedQuery(), 0);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
callback(abortController.signal);
|
|
21
|
+
};
|
|
22
|
+
triggerWatchedQuery();
|
|
23
|
+
}
|
package/lib/db/DBAdapter.d.ts
CHANGED
|
@@ -90,6 +90,10 @@ export interface DBAdapter extends BaseObserverInterface<DBAdapterListener>, DBG
|
|
|
90
90
|
readTransaction: <T>(fn: (tx: Transaction) => Promise<T>, options?: DBLockOptions) => Promise<T>;
|
|
91
91
|
writeLock: <T>(fn: (tx: LockContext) => Promise<T>, options?: DBLockOptions) => Promise<T>;
|
|
92
92
|
writeTransaction: <T>(fn: (tx: Transaction) => Promise<T>, options?: DBLockOptions) => Promise<T>;
|
|
93
|
+
/**
|
|
94
|
+
* This method refreshes the schema information across all connections. This is for advanced use cases, and should generally not be needed.
|
|
95
|
+
*/
|
|
96
|
+
refreshSchema: () => Promise<void>;
|
|
93
97
|
}
|
|
94
98
|
export declare function isBatchedUpdateNotification(update: BatchedUpdateNotification | UpdateNotification): update is BatchedUpdateNotification;
|
|
95
99
|
export declare function extractTableUpdates(update: BatchedUpdateNotification | UpdateNotification): string[];
|
package/lib/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export * from './client/SQLOpenFactory.js';
|
|
|
4
4
|
export * from './client/connection/PowerSyncBackendConnector.js';
|
|
5
5
|
export * from './client/connection/PowerSyncCredentials.js';
|
|
6
6
|
export * from './client/sync/bucket/BucketStorageAdapter.js';
|
|
7
|
+
export { runOnSchemaChange } from './client/runOnSchemaChange.js';
|
|
8
|
+
export { CompilableQueryWatchHandler, compilableQueryWatch } from './client/compilableQueryWatch.js';
|
|
7
9
|
export { UpdateType, CrudEntry, OpId } from './client/sync/bucket/CrudEntry.js';
|
|
8
10
|
export * from './client/sync/bucket/SqliteBucketStorage.js';
|
|
9
11
|
export * from './client/sync/bucket/CrudBatch.js';
|
package/lib/index.js
CHANGED
|
@@ -4,6 +4,8 @@ export * from './client/SQLOpenFactory.js';
|
|
|
4
4
|
export * from './client/connection/PowerSyncBackendConnector.js';
|
|
5
5
|
export * from './client/connection/PowerSyncCredentials.js';
|
|
6
6
|
export * from './client/sync/bucket/BucketStorageAdapter.js';
|
|
7
|
+
export { runOnSchemaChange } from './client/runOnSchemaChange.js';
|
|
8
|
+
export { compilableQueryWatch } from './client/compilableQueryWatch.js';
|
|
7
9
|
export { UpdateType, CrudEntry } from './client/sync/bucket/CrudEntry.js';
|
|
8
10
|
export * from './client/sync/bucket/SqliteBucketStorage.js';
|
|
9
11
|
export * from './client/sync/bucket/CrudBatch.js';
|