@powersync/web 0.0.0-dev-20251119142638 → 0.0.0-dev-20251120085122

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.
Files changed (27) hide show
  1. package/dist/index.umd.js +21 -6
  2. package/dist/index.umd.js.map +1 -1
  3. package/dist/worker/SharedSyncImplementation.umd.js +14 -6
  4. package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
  5. package/dist/worker/WASQLiteDB.umd.js +28 -34
  6. package/dist/worker/WASQLiteDB.umd.js.map +1 -1
  7. package/lib/src/db/adapters/AsyncDatabaseConnection.d.ts +13 -0
  8. package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.d.ts +1 -0
  9. package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.js +7 -2
  10. package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.d.ts +5 -0
  11. package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.js +7 -0
  12. package/lib/src/worker/db/SharedWASQLiteConnection.d.ts +4 -3
  13. package/lib/src/worker/db/SharedWASQLiteConnection.js +17 -17
  14. package/lib/src/worker/db/WASQLiteDB.worker.js +2 -2
  15. package/lib/src/worker/db/WorkerWASQLiteConnection.d.ts +3 -3
  16. package/lib/src/worker/db/WorkerWASQLiteConnection.js +2 -14
  17. package/lib/src/worker/sync/SharedSyncImplementation.d.ts +2 -2
  18. package/lib/src/worker/sync/SharedSyncImplementation.js +7 -4
  19. package/lib/tsconfig.tsbuildinfo +1 -1
  20. package/package.json +1 -1
  21. package/src/db/adapters/AsyncDatabaseConnection.ts +13 -0
  22. package/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts +8 -2
  23. package/src/db/adapters/wa-sqlite/WASQLiteConnection.ts +8 -0
  24. package/src/worker/db/SharedWASQLiteConnection.ts +23 -20
  25. package/src/worker/db/WASQLiteDB.worker.ts +2 -2
  26. package/src/worker/db/WorkerWASQLiteConnection.ts +3 -18
  27. package/src/worker/sync/SharedSyncImplementation.ts +15 -12
@@ -34,6 +34,22 @@ export class SharedWASQLiteConnection implements AsyncDatabaseConnection {
34
34
  this.activeHoldId = null;
35
35
  }
36
36
 
37
+ protected get logger() {
38
+ return this.options.logger;
39
+ }
40
+
41
+ protected get dbEntry() {
42
+ return this.options.dbMap.get(this.options.dbFilename)!;
43
+ }
44
+
45
+ protected get connection() {
46
+ return this.dbEntry.db;
47
+ }
48
+
49
+ protected get clientIds() {
50
+ return this.dbEntry.clientIds;
51
+ }
52
+
37
53
  async init(): Promise<void> {
38
54
  // No-op since the connection is already initialized when it was created
39
55
  }
@@ -51,20 +67,8 @@ export class SharedWASQLiteConnection implements AsyncDatabaseConnection {
51
67
  }
52
68
  }
53
69
 
54
- protected get logger() {
55
- return this.options.logger;
56
- }
57
-
58
- protected get dbEntry() {
59
- return this.options.dbMap.get(this.options.dbFilename)!;
60
- }
61
-
62
- protected get connection() {
63
- return this.dbEntry.db;
64
- }
65
-
66
- protected get clientIds() {
67
- return this.dbEntry.clientIds;
70
+ async isAutoCommit(): Promise<boolean> {
71
+ return this.connection.isAutoCommit();
68
72
  }
69
73
 
70
74
  /**
@@ -80,12 +84,11 @@ export class SharedWASQLiteConnection implements AsyncDatabaseConnection {
80
84
  clientIds.delete(clientId);
81
85
 
82
86
  if (this.activeHoldId) {
83
- /**
84
- * The hold hasn't been released, but we're closing now.
85
- * We can proactively cleanup and release the hold.
86
- */
87
- await this.connection.execute('ROLLBACK').catch(() => {});
88
- await this.connection.releaseHold(this.activeHoldId).catch(() => {});
87
+ // We can't cleanup here since we're not in a lock context.
88
+ // The cleanup will occur once a new hold is acquired.
89
+ this.logger.info(
90
+ `Hold ${this.activeHoldId} was still active when the connection was closed. Cleanup will occur once a new hold is acquired.`
91
+ );
89
92
  }
90
93
 
91
94
  if (clientIds.size == 0) {
@@ -9,7 +9,7 @@ import { AsyncDatabaseConnection } from '../../db/adapters/AsyncDatabaseConnecti
9
9
  import { WorkerDBOpenerOptions } from '../../db/adapters/wa-sqlite/WASQLiteOpenFactory';
10
10
  import { getNavigatorLocks } from '../../shared/navigator';
11
11
  import { SharedDBWorkerConnection, SharedWASQLiteConnection } from './SharedWASQLiteConnection';
12
- import { WorkerWASQLiteConnection, proxyWASQLiteConnection } from './WorkerWASQLiteConnection';
12
+ import { WorkerWASQLiteConnection } from './WorkerWASQLiteConnection';
13
13
 
14
14
  const baseLogger = createBaseLogger();
15
15
  baseLogger.useDefaults();
@@ -59,7 +59,7 @@ const openDBShared = async (options: WorkerDBOpenerOptions): Promise<AsyncDataba
59
59
  logger
60
60
  });
61
61
 
62
- return proxyWASQLiteConnection(sharedConnection);
62
+ return Comlink.proxy(sharedConnection);
63
63
  });
64
64
  };
65
65
 
@@ -1,26 +1,11 @@
1
1
  import * as Comlink from 'comlink';
2
- import { AsyncDatabaseConnection, OnTableChangeCallback } from '../../db/adapters/AsyncDatabaseConnection';
2
+ import { OnTableChangeCallback } from '../../db/adapters/AsyncDatabaseConnection';
3
3
  import { WASqliteConnection } from '../../db/adapters/wa-sqlite/WASQLiteConnection';
4
4
 
5
5
  /**
6
- * Fully proxies a WASQLiteConnection to be used as an AsyncDatabaseConnection.
6
+ * A Small proxy wrapper around the WASqliteConnection.
7
+ * This ensures that certain return types are properly proxied.
7
8
  */
8
- export function proxyWASQLiteConnection(connection: AsyncDatabaseConnection): AsyncDatabaseConnection {
9
- return Comlink.proxy({
10
- init: Comlink.proxy(() => connection.init()),
11
- close: Comlink.proxy(() => connection.close()),
12
- markHold: Comlink.proxy(() => connection.markHold()),
13
- releaseHold: Comlink.proxy((holdId: string) => connection.releaseHold(holdId)),
14
- execute: Comlink.proxy((sql: string, params?: any[]) => connection.execute(sql, params)),
15
- executeRaw: Comlink.proxy((sql: string, params?: any[]) => connection.executeRaw(sql, params)),
16
- executeBatch: Comlink.proxy((sql: string, params?: any[]) => connection.executeBatch(sql, params)),
17
- registerOnTableChange: Comlink.proxy((callback: OnTableChangeCallback) =>
18
- connection.registerOnTableChange(callback)
19
- ),
20
- getConfig: Comlink.proxy(() => connection.getConfig())
21
- });
22
- }
23
-
24
9
  export class WorkerWASQLiteConnection extends WASqliteConnection {
25
10
  async registerOnTableChange(callback: OnTableChangeCallback): Promise<() => void> {
26
11
  // Proxy the callback remove function
@@ -1,10 +1,4 @@
1
1
  import {
2
- type ILogger,
3
- type ILogLevel,
4
- type PowerSyncConnectionOptions,
5
- type StreamingSyncImplementation,
6
- type StreamingSyncImplementationListener,
7
- type SyncStatusOptions,
8
2
  AbortOperation,
9
3
  BaseObserver,
10
4
  ConnectionManager,
@@ -13,7 +7,13 @@ import {
13
7
  PowerSyncBackendConnector,
14
8
  SqliteBucketStorage,
15
9
  SubscribedStream,
16
- SyncStatus
10
+ SyncStatus,
11
+ type ILogger,
12
+ type ILogLevel,
13
+ type PowerSyncConnectionOptions,
14
+ type StreamingSyncImplementation,
15
+ type StreamingSyncImplementationListener,
16
+ type SyncStatusOptions
17
17
  } from '@powersync/common';
18
18
  import { Mutex } from 'async-mutex';
19
19
  import * as Comlink from 'comlink';
@@ -75,7 +75,7 @@ export type WrappedSyncPort = {
75
75
  clientProvider: Comlink.Remote<AbstractSharedSyncClientProvider>;
76
76
  db?: DBAdapter;
77
77
  currentSubscriptions: SubscribedStream[];
78
- closeListeners: (() => void)[];
78
+ closeListeners: (() => void | Promise<void>)[];
79
79
  };
80
80
 
81
81
  /**
@@ -334,12 +334,15 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
334
334
  }
335
335
 
336
336
  for (const closeListener of trackedPort.closeListeners) {
337
- closeListener();
337
+ await closeListener();
338
338
  }
339
339
 
340
340
  if (this.dbAdapter && this.dbAdapter == trackedPort.db) {
341
341
  // Unconditionally close the connection because the database it's writing to has just been closed.
342
- await this.connectionManager.disconnect();
342
+ // The connection has been closed previously, this might throw. We should be able to ignore it.
343
+ await this.connectionManager
344
+ .disconnect()
345
+ .catch((ex) => this.logger.warn('Error while disconnecting. Will attempt to reconnect.', ex));
343
346
 
344
347
  // Clearing the adapter will result in a new one being opened in connect
345
348
  this.dbAdapter = null;
@@ -482,9 +485,9 @@ export class SharedSyncImplementation extends BaseObserver<SharedSyncImplementat
482
485
  // that and ensure pending requests are aborted when the tab is closed.
483
486
  remoteCanCloseUnexpectedly: true
484
487
  });
485
- lastClient.closeListeners.push(() => {
488
+ lastClient.closeListeners.push(async () => {
486
489
  this.logger.info('Aborting open connection because associated tab closed.');
487
- wrapped.close();
490
+ await wrapped.close().catch((ex) => this.logger.warn('error closing database connection', ex));
488
491
  wrapped.markRemoteClosed();
489
492
  });
490
493