@powersync/op-sqlite 0.1.3 → 0.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@powersync/op-sqlite",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "PowerSync - sync Postgres or MongoDB with SQLite in your React Native app for offline-first and real-time data",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./lib/commonjs/index.js",
@@ -59,13 +59,13 @@
59
59
  },
60
60
  "peerDependencies": {
61
61
  "@op-engineering/op-sqlite": "^10.1.0",
62
- "@powersync/common": "^1.22.0",
62
+ "@powersync/common": "^1.22.1",
63
63
  "react": "*",
64
64
  "react-native": "*"
65
65
  },
66
66
  "dependencies": {
67
67
  "async-lock": "^1.4.0",
68
- "@powersync/common": "1.22.0"
68
+ "@powersync/common": "1.22.1"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@op-engineering/op-sqlite": "^10.1.0",
@@ -1,40 +1,85 @@
1
- import { DB, SQLBatchTuple } from '@op-engineering/op-sqlite';
2
- import { BaseObserver, DBAdapterListener, QueryResult, RowUpdateType } from '@powersync/common';
1
+ import { DB, SQLBatchTuple, UpdateHookOperation } from '@op-engineering/op-sqlite';
2
+ import {
3
+ BaseObserver,
4
+ BatchedUpdateNotification,
5
+ DBAdapterListener,
6
+ QueryResult,
7
+ RowUpdateType,
8
+ UpdateNotification
9
+ } from '@powersync/common';
3
10
 
4
11
  export type OPSQLiteConnectionOptions = {
5
12
  baseDB: DB;
6
13
  };
7
14
 
15
+ export type OPSQLiteUpdateNotification = {
16
+ table: string;
17
+ operation: UpdateHookOperation;
18
+ row?: any;
19
+ rowId: number;
20
+ };
21
+
8
22
  export class OPSQLiteConnection extends BaseObserver<DBAdapterListener> {
9
23
  protected DB: DB;
24
+ private updateBuffer: UpdateNotification[];
25
+
10
26
  constructor(protected options: OPSQLiteConnectionOptions) {
11
27
  super();
12
28
  this.DB = options.baseDB;
29
+ this.updateBuffer = [];
30
+
31
+ this.DB.rollbackHook(() => {
32
+ this.updateBuffer = [];
33
+ });
13
34
 
14
- // link table update commands
15
35
  this.DB.updateHook((update) => {
16
- this.iterateListeners((cb) => {
17
- let opType: RowUpdateType;
18
- switch (update.operation) {
19
- case 'INSERT':
20
- opType = RowUpdateType.SQLITE_INSERT;
21
- break;
22
- case 'DELETE':
23
- opType = RowUpdateType.SQLITE_DELETE;
24
- break;
25
- case 'UPDATE':
26
- opType = RowUpdateType.SQLITE_UPDATE;
27
- break;
28
- }
29
- cb.tablesUpdated?.({
30
- table: update.table,
31
- opType,
32
- rowId: update.rowId
33
- });
34
- });
36
+ this.addTableUpdate(update);
35
37
  });
36
38
  }
37
39
 
40
+ addTableUpdate(update: OPSQLiteUpdateNotification) {
41
+ let opType: RowUpdateType;
42
+ switch (update.operation) {
43
+ case 'INSERT':
44
+ opType = RowUpdateType.SQLITE_INSERT;
45
+ break;
46
+ case 'DELETE':
47
+ opType = RowUpdateType.SQLITE_DELETE;
48
+ break;
49
+ case 'UPDATE':
50
+ opType = RowUpdateType.SQLITE_UPDATE;
51
+ break;
52
+ }
53
+
54
+ this.updateBuffer.push({
55
+ table: update.table,
56
+ opType,
57
+ rowId: update.rowId
58
+ });
59
+ }
60
+
61
+ flushUpdates() {
62
+ if (!this.updateBuffer.length) {
63
+ return;
64
+ }
65
+
66
+ const groupedUpdates = this.updateBuffer.reduce((grouping: Record<string, UpdateNotification[]>, update) => {
67
+ const { table } = update;
68
+ const updateGroup = grouping[table] || (grouping[table] = []);
69
+ updateGroup.push(update);
70
+ return grouping;
71
+ }, {});
72
+
73
+ const batchedUpdate: BatchedUpdateNotification = {
74
+ groupedUpdates,
75
+ rawUpdates: this.updateBuffer,
76
+ tables: Object.keys(groupedUpdates)
77
+ };
78
+
79
+ this.updateBuffer = [];
80
+ this.iterateListeners((l) => l.tablesUpdated?.(batchedUpdate));
81
+ }
82
+
38
83
  close() {
39
84
  return this.DB.close();
40
85
  }
@@ -1,12 +1,4 @@
1
- import {
2
- BaseObserver,
3
- DBAdapter,
4
- DBAdapterListener,
5
- DBLockOptions,
6
- QueryResult,
7
- SQLOpenOptions,
8
- Transaction
9
- } from '@powersync/common';
1
+ import { BaseObserver, DBAdapter, DBAdapterListener, DBLockOptions, QueryResult, Transaction } from '@powersync/common';
10
2
  import { ANDROID_DATABASE_PATH, IOS_LIBRARY_PATH, open, type DB } from '@op-engineering/op-sqlite';
11
3
  import Lock from 'async-lock';
12
4
  import { OPSQLiteConnection } from './OPSQLiteConnection';
@@ -194,13 +186,18 @@ export class OPSQLiteDBAdapter extends BaseObserver<DBAdapterListener> implement
194
186
 
195
187
  return new Promise(async (resolve, reject) => {
196
188
  try {
197
- await this.locks.acquire(
198
- LockType.WRITE,
199
- async () => {
200
- resolve(await fn(this.writeConnection!));
201
- },
202
- { timeout: options?.timeoutMs }
203
- );
189
+ await this.locks
190
+ .acquire(
191
+ LockType.WRITE,
192
+ async () => {
193
+ resolve(await fn(this.writeConnection!));
194
+ },
195
+ { timeout: options?.timeoutMs }
196
+ )
197
+ .then(() => {
198
+ // flush updates once a write lock has been released
199
+ this.writeConnection!.flushUpdates();
200
+ });
204
201
  } catch (ex) {
205
202
  reject(ex);
206
203
  }