@powersync/web 1.31.0 → 1.33.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.
Files changed (113) hide show
  1. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapp-89f0ba.index.umd.js +1878 -0
  2. package/dist/_journeyapps_wa-sqlite-_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapp-89f0ba.index.umd.js.map +1 -0
  3. package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530150.index.umd.js +555 -0
  4. package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530150.index.umd.js.map +1 -0
  5. package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530151.index.umd.js +555 -0
  6. package/dist/_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js-_journeyapps_wa-sqlite_src_example-2530151.index.umd.js.map +1 -0
  7. package/dist/index.umd.js +4700 -43409
  8. package/dist/index.umd.js.map +1 -1
  9. package/dist/worker/SharedSyncImplementation.umd.js +4187 -4919
  10. package/dist/worker/SharedSyncImplementation.umd.js.map +1 -1
  11. package/dist/worker/WASQLiteDB.umd.js +4206 -4953
  12. package/dist/worker/WASQLiteDB.umd.js.map +1 -1
  13. package/dist/worker/{node_modules_bson_lib_bson_mjs.umd.js → node_modules_pnpm_bson_6_10_4_node_modules_bson_lib_bson_mjs.umd.js} +6 -6
  14. package/dist/worker/node_modules_pnpm_bson_6_10_4_node_modules_bson_lib_bson_mjs.umd.js.map +1 -0
  15. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-3a94cf.umd.js +44 -0
  16. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-3a94cf.umd.js.map +1 -0
  17. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-868779.umd.js +44 -0
  18. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-868779.umd.js.map +1 -0
  19. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-f60d0d.umd.js +44 -0
  20. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-f60d0d.umd.js.map +1 -0
  21. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +44 -0
  22. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +1 -0
  23. package/dist/worker/{node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-0d2437.umd.js} +24 -24
  24. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-0d2437.umd.js.map +1 -0
  25. package/dist/worker/{node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-1d4e74.umd.js} +18 -18
  26. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-1d4e74.umd.js.map +1 -0
  27. package/dist/worker/{node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js → node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-3622cf.umd.js} +18 -18
  28. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_4_1_node_modules_journeyapps_wa-sqlite_src_examples-3622cf.umd.js.map +1 -0
  29. package/lib/package.json +26 -22
  30. package/lib/src/attachments/IndexDBFileSystemAdapter.d.ts +25 -0
  31. package/lib/src/attachments/IndexDBFileSystemAdapter.js +104 -0
  32. package/lib/src/db/NavigatorTriggerClaimManager.d.ts +6 -0
  33. package/lib/src/db/NavigatorTriggerClaimManager.js +20 -0
  34. package/lib/src/db/PowerSyncDatabase.d.ts +5 -2
  35. package/lib/src/db/PowerSyncDatabase.js +46 -8
  36. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.d.ts +1 -1
  37. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js +1 -1
  38. package/lib/src/db/adapters/AbstractWebSQLOpenFactory.d.ts +2 -2
  39. package/lib/src/db/adapters/AbstractWebSQLOpenFactory.js +2 -2
  40. package/lib/src/db/adapters/AsyncDatabaseConnection.d.ts +1 -1
  41. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.d.ts +4 -4
  42. package/lib/src/db/adapters/LockedAsyncDatabaseAdapter.js +29 -14
  43. package/lib/src/db/adapters/WebDBAdapter.d.ts +5 -2
  44. package/lib/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.d.ts +2 -2
  45. package/lib/src/db/adapters/wa-sqlite/InternalWASQLiteDBAdapter.d.ts +12 -0
  46. package/lib/src/db/adapters/wa-sqlite/InternalWASQLiteDBAdapter.js +19 -0
  47. package/lib/src/db/adapters/wa-sqlite/WASQLiteConnection.d.ts +2 -2
  48. package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.d.ts +4 -4
  49. package/lib/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.js +6 -6
  50. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +4 -4
  51. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +7 -7
  52. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.d.ts +1 -1
  53. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js +3 -3
  54. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.d.ts +5 -5
  55. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js +5 -5
  56. package/lib/src/db/sync/WebRemote.js +1 -1
  57. package/lib/src/db/sync/WebStreamingSyncImplementation.d.ts +1 -1
  58. package/lib/src/db/sync/WebStreamingSyncImplementation.js +1 -1
  59. package/lib/src/index.d.ts +13 -12
  60. package/lib/src/index.js +13 -12
  61. package/lib/src/worker/db/SharedWASQLiteConnection.d.ts +2 -2
  62. package/lib/src/worker/db/WASQLiteDB.worker.js +3 -3
  63. package/lib/src/worker/db/WorkerWASQLiteConnection.d.ts +2 -2
  64. package/lib/src/worker/db/WorkerWASQLiteConnection.js +1 -1
  65. package/lib/src/worker/db/open-worker-database.d.ts +2 -2
  66. package/lib/src/worker/db/open-worker-database.js +1 -1
  67. package/lib/src/worker/sync/BroadcastLogger.d.ts +1 -1
  68. package/lib/src/worker/sync/SharedSyncImplementation.d.ts +4 -4
  69. package/lib/src/worker/sync/SharedSyncImplementation.js +5 -5
  70. package/lib/src/worker/sync/SharedSyncImplementation.worker.js +2 -2
  71. package/lib/src/worker/sync/WorkerClient.d.ts +1 -1
  72. package/lib/src/worker/sync/WorkerClient.js +2 -2
  73. package/lib/tsconfig.tsbuildinfo +1 -1
  74. package/package.json +21 -17
  75. package/src/attachments/IndexDBFileSystemAdapter.ts +117 -0
  76. package/src/db/NavigatorTriggerClaimManager.ts +23 -0
  77. package/src/db/PowerSyncDatabase.ts +53 -9
  78. package/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.ts +1 -1
  79. package/src/db/adapters/AbstractWebSQLOpenFactory.ts +3 -3
  80. package/src/db/adapters/AsyncDatabaseConnection.ts +1 -1
  81. package/src/db/adapters/LockedAsyncDatabaseAdapter.ts +32 -20
  82. package/src/db/adapters/WebDBAdapter.ts +6 -2
  83. package/src/db/adapters/WorkerWrappedAsyncDatabaseConnection.ts +2 -2
  84. package/src/db/adapters/wa-sqlite/InternalWASQLiteDBAdapter.ts +23 -0
  85. package/src/db/adapters/wa-sqlite/WASQLiteConnection.ts +2 -2
  86. package/src/db/adapters/wa-sqlite/WASQLiteDBAdapter.ts +8 -8
  87. package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +8 -8
  88. package/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.ts +3 -3
  89. package/src/db/sync/SharedWebStreamingSyncImplementation.ts +7 -7
  90. package/src/db/sync/WebRemote.ts +1 -1
  91. package/src/db/sync/WebStreamingSyncImplementation.ts +2 -2
  92. package/src/index.ts +13 -12
  93. package/src/worker/db/SharedWASQLiteConnection.ts +2 -2
  94. package/src/worker/db/WASQLiteDB.worker.ts +5 -5
  95. package/src/worker/db/WorkerWASQLiteConnection.ts +2 -2
  96. package/src/worker/db/open-worker-database.ts +2 -2
  97. package/src/worker/sync/BroadcastLogger.ts +1 -1
  98. package/src/worker/sync/SharedSyncImplementation.ts +9 -9
  99. package/src/worker/sync/SharedSyncImplementation.worker.ts +2 -2
  100. package/src/worker/sync/WorkerClient.ts +2 -2
  101. package/dist/worker/node_modules_bson_lib_bson_mjs.umd.js.map +0 -1
  102. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js +0 -44
  103. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite-async_mjs.umd.js.map +0 -1
  104. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js +0 -44
  105. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_mc-wa-sqlite_mjs.umd.js.map +0 -1
  106. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js +0 -44
  107. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite-async_mjs.umd.js.map +0 -1
  108. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +0 -44
  109. package/dist/worker/node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +0 -1
  110. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_AccessHandlePoolVFS_js.umd.js.map +0 -1
  111. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_IDBBatchAtomicVFS_js.umd.js.map +0 -1
  112. package/dist/worker/node_modules_journeyapps_wa-sqlite_src_examples_OPFSCoopSyncVFS_js.umd.js.map +0 -1
  113. /package/bin/{powersync.js → powersync.cjs} +0 -0
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@powersync/web",
3
- "version": "1.31.0",
3
+ "version": "1.33.0",
4
4
  "description": "PowerSync Web SDK",
5
5
  "main": "lib/src/index.js",
6
+ "module": "lib/src/index.js",
7
+ "type": "module",
6
8
  "types": "lib/src/index.d.ts",
7
9
  "bin": {
8
- "powersync-web": "bin/powersync.js"
10
+ "powersync-web": "bin/powersync.cjs"
9
11
  },
10
12
  "files": [
11
13
  "bin",
@@ -15,21 +17,23 @@
15
17
  "src"
16
18
  ],
17
19
  "exports": {
18
- ".": "./lib/src/index.js",
20
+ ".": {
21
+ "types": "./lib/src/index.d.ts",
22
+ "default": "./lib/src/index.js"
23
+ },
19
24
  "./umd": {
20
- "import": "./dist/index.umd.js",
21
- "require": "./dist/index.umd.js",
22
- "types": "./lib/src/index.d.ts"
25
+ "types": "./lib/src/index.d.ts",
26
+ "default": "./dist/index.umd.js"
23
27
  },
24
28
  "./umd/worker/db": {
29
+ "types": "./lib/src/index.d.ts",
25
30
  "import": "./dist/worker/WASQLiteDB.umd.js",
26
- "require": "./dist/worker/WASQLiteDB.umd.js",
27
- "types": "./lib/src/index.d.ts"
31
+ "require": "./dist/worker/WASQLiteDB.umd.js"
28
32
  },
29
33
  "./umd/worker/sync": {
34
+ "types": "./lib/src/index.d.ts",
30
35
  "import": "./dist/worker/SharedSyncImplementation.umd.js",
31
- "require": "./dist/worker/SharedSyncImplementation.umd.js",
32
- "types": "./lib/src/index.d.ts"
36
+ "require": "./dist/worker/SharedSyncImplementation.umd.js"
33
37
  }
34
38
  },
35
39
  "repository": "https://github.com/powersync-ja/powersync-js",
@@ -52,27 +56,26 @@
52
56
  "license": "Apache-2.0",
53
57
  "peerDependencies": {
54
58
  "@journeyapps/wa-sqlite": "^1.4.1",
55
- "@powersync/common": "^1.45.0"
59
+ "@powersync/common": "^1.47.0"
56
60
  },
57
61
  "dependencies": {
58
62
  "async-mutex": "^0.5.0",
59
63
  "bson": "^6.10.4",
60
64
  "comlink": "^4.4.2",
61
65
  "commander": "^12.1.0",
62
- "@powersync/common": "1.45.0"
66
+ "@powersync/common": "1.47.0"
63
67
  },
64
68
  "devDependencies": {
65
69
  "@journeyapps/wa-sqlite": "^1.4.1",
66
70
  "@types/uuid": "^9.0.6",
67
71
  "crypto-browserify": "^3.12.0",
72
+ "glob": "^11.0.0",
68
73
  "p-defer": "^4.0.1",
69
74
  "source-map-loader": "^5.0.0",
70
75
  "stream-browserify": "^3.0.0",
71
76
  "terser-webpack-plugin": "^5.3.9",
72
- "uuid": "^9.0.1",
73
- "vite": "^6.1.0",
74
- "vite-plugin-top-level-await": "^1.4.4",
75
- "vite-plugin-wasm": "^3.3.0",
77
+ "uuid": "^11.1.0",
78
+ "vite": "^7.3.1",
76
79
  "vm-browserify": "^1.1.2",
77
80
  "webpack": "^5.90.1",
78
81
  "webpack-cli": "^5.1.4",
@@ -86,6 +89,7 @@
86
89
  "build:prod": "pnpm run build:tsc --sourceMap false && pnpm run build:webpack-main && pnpm run build:webpack-workers",
87
90
  "clean": "rm -rf lib dist tsconfig.tsbuildinfo",
88
91
  "watch": "tsc --build -w",
89
- "test": "pnpm build && vitest"
92
+ "test": "pnpm build && vitest",
93
+ "test:exports": "attw --pack . --entrypoints . --profile=esm-only "
90
94
  }
91
95
  }
@@ -0,0 +1,117 @@
1
+ import { AttachmentData, EncodingType, LocalStorageAdapter } from '@powersync/common';
2
+
3
+ /**
4
+ * IndexDBFileSystemStorageAdapter implements LocalStorageAdapter using IndexedDB.
5
+ * Suitable for web browsers and web-based environments.
6
+ */
7
+ export class IndexDBFileSystemStorageAdapter implements LocalStorageAdapter {
8
+ private dbPromise!: Promise<IDBDatabase>;
9
+
10
+ constructor(private databaseName: string = 'PowerSyncFiles') {}
11
+
12
+ async initialize(): Promise<void> {
13
+ this.dbPromise = new Promise<IDBDatabase>((resolve, reject) => {
14
+ const request = indexedDB.open(this.databaseName, 1);
15
+ request.onupgradeneeded = () => {
16
+ request.result.createObjectStore('files');
17
+ };
18
+ request.onsuccess = () => resolve(request.result);
19
+ request.onerror = () => reject(request.error);
20
+ });
21
+ }
22
+
23
+ async clear(): Promise<void> {
24
+ const db = await this.dbPromise;
25
+ return new Promise((resolve, reject) => {
26
+ const tx = db.transaction('files', 'readwrite');
27
+ const store = tx.objectStore('files');
28
+ const req = store.clear();
29
+ req.onsuccess = () => resolve();
30
+ req.onerror = () => reject(req.error);
31
+ });
32
+ }
33
+
34
+ getLocalUri(filename: string): string {
35
+ return `indexeddb://${this.databaseName}/files/${filename}`;
36
+ }
37
+
38
+ private async getStore(mode: IDBTransactionMode = 'readonly'): Promise<IDBObjectStore> {
39
+ const db = await this.dbPromise;
40
+ const tx = db.transaction('files', mode);
41
+ return tx.objectStore('files');
42
+ }
43
+
44
+ async saveFile(filePath: string, data: AttachmentData): Promise<number> {
45
+ const store = await this.getStore('readwrite');
46
+
47
+ let dataToStore: ArrayBuffer;
48
+ let size: number;
49
+
50
+ if (typeof data === 'string') {
51
+ const binaryString = atob(data);
52
+ const bytes = new Uint8Array(binaryString.length);
53
+ for (let i = 0; i < binaryString.length; i++) {
54
+ bytes[i] = binaryString.charCodeAt(i);
55
+ }
56
+ dataToStore = bytes.buffer;
57
+ size = bytes.byteLength;
58
+ } else {
59
+ dataToStore = data;
60
+ size = dataToStore.byteLength;
61
+ }
62
+
63
+ return await new Promise<number>((resolve, reject) => {
64
+ const req = store.put(dataToStore, filePath);
65
+ req.onsuccess = () => resolve(size);
66
+ req.onerror = () => reject(req.error);
67
+ });
68
+ }
69
+
70
+ async readFile(fileUri: string, options?: { encoding?: EncodingType; mediaType?: string }): Promise<ArrayBuffer> {
71
+ const store = await this.getStore();
72
+ return new Promise<ArrayBuffer>((resolve, reject) => {
73
+ const req = store.get(fileUri);
74
+ req.onsuccess = async () => {
75
+ if (!req.result) {
76
+ reject(new Error('File not found'));
77
+ return;
78
+ }
79
+
80
+ resolve(req.result as ArrayBuffer);
81
+ };
82
+ req.onerror = () => reject(req.error);
83
+ });
84
+ }
85
+
86
+ async deleteFile(uri: string, options?: { filename?: string }): Promise<void> {
87
+ const store = await this.getStore('readwrite');
88
+ await new Promise<void>((resolve, reject) => {
89
+ const req = store.delete(uri);
90
+ req.onsuccess = () => resolve();
91
+ req.onerror = () => reject(req.error);
92
+ });
93
+ }
94
+
95
+ async fileExists(fileUri: string): Promise<boolean> {
96
+ const store = await this.getStore();
97
+ return new Promise<boolean>((resolve, reject) => {
98
+ const req = store.get(fileUri);
99
+ req.onsuccess = () => resolve(!!req.result);
100
+ req.onerror = () => reject(req.error);
101
+ });
102
+ }
103
+
104
+ async makeDir(path: string): Promise<void> {
105
+ // No-op for IndexedDB as it does not have a directory structure
106
+ }
107
+
108
+ async rmDir(path: string): Promise<void> {
109
+ const store = await this.getStore('readwrite');
110
+ const range = IDBKeyRange.bound(path + '/', path + '/\uffff', false, false);
111
+ await new Promise<void>((resolve, reject) => {
112
+ const req = store.delete(range);
113
+ req.onsuccess = () => resolve();
114
+ req.onerror = () => reject(req.error);
115
+ });
116
+ }
117
+ }
@@ -0,0 +1,23 @@
1
+ import { TriggerClaimManager } from '@powersync/common';
2
+ import { getNavigatorLocks } from '../shared/navigator.js';
3
+
4
+ /**
5
+ * @internal
6
+ * @experimental
7
+ */
8
+ export const NAVIGATOR_TRIGGER_CLAIM_MANAGER: TriggerClaimManager = {
9
+ async obtainClaim(identifier: string): Promise<() => Promise<void>> {
10
+ return new Promise((resolveReleaser) => {
11
+ getNavigatorLocks().request(identifier, async () => {
12
+ await new Promise<void>((releaseLock) => {
13
+ resolveReleaser(async () => releaseLock());
14
+ });
15
+ });
16
+ });
17
+ },
18
+
19
+ async checkClaim(identifier: string): Promise<boolean> {
20
+ const currentState = await getNavigatorLocks().query();
21
+ return currentState.held?.find((heldLock) => heldLock.name == identifier) != null;
22
+ }
23
+ };
@@ -7,6 +7,7 @@ import {
7
7
  PowerSyncDatabaseOptionsWithSettings,
8
8
  SqliteBucketStorage,
9
9
  StreamingSyncImplementation,
10
+ TriggerManagerConfig,
10
11
  isDBAdapter,
11
12
  isSQLOpenFactory,
12
13
  type BucketStorageAdapter,
@@ -15,22 +16,25 @@ import {
15
16
  type RequiredAdditionalConnectionOptions
16
17
  } from '@powersync/common';
17
18
  import { Mutex } from 'async-mutex';
18
- import { getNavigatorLocks } from '../shared/navigator';
19
- import { WebDBAdapter } from './adapters/WebDBAdapter';
20
- import { WASQLiteOpenFactory } from './adapters/wa-sqlite/WASQLiteOpenFactory';
19
+ import { getNavigatorLocks } from '../shared/navigator.js';
20
+ import { NAVIGATOR_TRIGGER_CLAIM_MANAGER } from './NavigatorTriggerClaimManager.js';
21
+ import { LockedAsyncDatabaseAdapter } from './adapters/LockedAsyncDatabaseAdapter.js';
22
+ import { WebDBAdapter } from './adapters/WebDBAdapter.js';
23
+ import { WASQLiteOpenFactory } from './adapters/wa-sqlite/WASQLiteOpenFactory.js';
21
24
  import {
22
25
  DEFAULT_WEB_SQL_FLAGS,
23
26
  ResolvedWebSQLOpenOptions,
24
27
  WebSQLFlags,
28
+ isServerSide,
25
29
  resolveWebSQLFlags
26
- } from './adapters/web-sql-flags';
27
- import { SSRStreamingSyncImplementation } from './sync/SSRWebStreamingSyncImplementation';
28
- import { SharedWebStreamingSyncImplementation } from './sync/SharedWebStreamingSyncImplementation';
29
- import { WebRemote } from './sync/WebRemote';
30
+ } from './adapters/web-sql-flags.js';
31
+ import { SSRStreamingSyncImplementation } from './sync/SSRWebStreamingSyncImplementation.js';
32
+ import { SharedWebStreamingSyncImplementation } from './sync/SharedWebStreamingSyncImplementation.js';
33
+ import { WebRemote } from './sync/WebRemote.js';
30
34
  import {
31
35
  WebStreamingSyncImplementation,
32
36
  WebStreamingSyncImplementationOptions
33
- } from './sync/WebStreamingSyncImplementation';
37
+ } from './sync/WebStreamingSyncImplementation.js';
34
38
 
35
39
  export interface WebPowerSyncFlags extends WebSQLFlags {
36
40
  /**
@@ -143,7 +147,33 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
143
147
  }
144
148
  }
145
149
 
146
- async _initialize(): Promise<void> {}
150
+ async _initialize(): Promise<void> {
151
+ if (this.database instanceof LockedAsyncDatabaseAdapter) {
152
+ /**
153
+ * While init is done automatically,
154
+ * LockedAsyncDatabaseAdapter only exposes config after init.
155
+ * We can explicitly wait for init here in order to access config.
156
+ */
157
+ await this.database.init();
158
+ }
159
+
160
+ // In some cases, like the SQLJs adapter, we don't pass a WebDBAdapter, so we need to check.
161
+ if (typeof (this.database as WebDBAdapter).getConfiguration == 'function') {
162
+ const config = (this.database as WebDBAdapter).getConfiguration();
163
+ if (config.requiresPersistentTriggers) {
164
+ this.triggersImpl.updateDefaults({
165
+ useStorageByDefault: true
166
+ });
167
+ }
168
+ }
169
+ }
170
+
171
+ protected generateTriggerManagerConfig(): TriggerManagerConfig {
172
+ return {
173
+ // We need to share hold information between tabs for web
174
+ claimManager: NAVIGATOR_TRIGGER_CLAIM_MANAGER
175
+ };
176
+ }
147
177
 
148
178
  protected openDBAdapter(options: WebPowerSyncDatabaseOptionsWithSettings): DBAdapter {
149
179
  const defaultFactory = new WASQLiteOpenFactory({
@@ -169,6 +199,20 @@ export class PowerSyncDatabase extends AbstractPowerSyncDatabase {
169
199
  });
170
200
  }
171
201
 
202
+ protected async loadVersion(): Promise<void> {
203
+ if (isServerSide()) {
204
+ return;
205
+ }
206
+ return super.loadVersion();
207
+ }
208
+
209
+ protected async resolveOfflineSyncStatus() {
210
+ if (isServerSide()) {
211
+ return;
212
+ }
213
+ return super.resolveOfflineSyncStatus();
214
+ }
215
+
172
216
  protected generateBucketStorageAdapter(): BucketStorageAdapter {
173
217
  return new SqliteBucketStorage(this.database);
174
218
  }
@@ -9,7 +9,7 @@ import {
9
9
  WebPowerSyncDatabaseOptions,
10
10
  WebPowerSyncFlags,
11
11
  resolveWebPowerSyncFlags
12
- } from '../../db/PowerSyncDatabase';
12
+ } from '../../db/PowerSyncDatabase.js';
13
13
 
14
14
  /**
15
15
  * {@link WebPowerSyncFlags}
@@ -1,6 +1,6 @@
1
- import { type ILogger, createLogger, DBAdapter, SQLOpenFactory } from '@powersync/common';
2
- import { SSRDBAdapter } from './SSRDBAdapter';
3
- import { ResolvedWebSQLFlags, WebSQLOpenFactoryOptions, isServerSide, resolveWebSQLFlags } from './web-sql-flags';
1
+ import { DBAdapter, type ILogger, SQLOpenFactory, createLogger } from '@powersync/common';
2
+ import { SSRDBAdapter } from './SSRDBAdapter.js';
3
+ import { ResolvedWebSQLFlags, WebSQLOpenFactoryOptions, isServerSide, resolveWebSQLFlags } from './web-sql-flags.js';
4
4
 
5
5
  export abstract class AbstractWebSQLOpenFactory implements SQLOpenFactory {
6
6
  protected resolvedFlags: ResolvedWebSQLFlags;
@@ -1,5 +1,5 @@
1
1
  import { BatchedUpdateNotification, QueryResult } from '@powersync/common';
2
- import { ResolvedWebSQLOpenOptions } from './web-sql-flags';
2
+ import { ResolvedWebSQLOpenOptions } from './web-sql-flags.js';
3
3
 
4
4
  /**
5
5
  * @internal
@@ -11,13 +11,13 @@ import {
11
11
  createLogger,
12
12
  type ILogger
13
13
  } from '@powersync/common';
14
- import { getNavigatorLocks } from '../../shared/navigator';
15
- import { AsyncDatabaseConnection } from './AsyncDatabaseConnection';
16
- import { SharedConnectionWorker, WebDBAdapter } from './WebDBAdapter';
17
- import { WorkerWrappedAsyncDatabaseConnection } from './WorkerWrappedAsyncDatabaseConnection';
18
- import { WASQLiteVFS } from './wa-sqlite/WASQLiteConnection';
19
- import { ResolvedWASQLiteOpenFactoryOptions } from './wa-sqlite/WASQLiteOpenFactory';
20
- import { ResolvedWebSQLOpenOptions } from './web-sql-flags';
14
+ import { getNavigatorLocks } from '../../shared/navigator.js';
15
+ import { AsyncDatabaseConnection } from './AsyncDatabaseConnection.js';
16
+ import { SharedConnectionWorker, WebDBAdapter, WebDBAdapterConfiguration } from './WebDBAdapter.js';
17
+ import { WorkerWrappedAsyncDatabaseConnection } from './WorkerWrappedAsyncDatabaseConnection.js';
18
+ import { WASQLiteVFS } from './wa-sqlite/WASQLiteConnection.js';
19
+ import { ResolvedWASQLiteOpenFactoryOptions } from './wa-sqlite/WASQLiteOpenFactory.js';
20
+ import { ResolvedWebSQLOpenOptions } from './web-sql-flags.js';
21
21
 
22
22
  /**
23
23
  * @internal
@@ -151,13 +151,15 @@ export class LockedAsyncDatabaseAdapter
151
151
  * Returns a pending operation if one is already in progress.
152
152
  */
153
153
  async reOpenInternalDB(): Promise<void> {
154
- if (!this.options.reOpenOnConnectionClosed) {
155
- throw new Error(`Cannot re-open underlying database, reOpenOnConnectionClosed is not enabled`);
156
- }
157
- if (this.databaseOpenPromise) {
154
+ if (this.closing || !this.options.reOpenOnConnectionClosed) {
155
+ // No-op
156
+ return;
157
+ } else if (this.databaseOpenPromise) {
158
+ // Already busy opening
158
159
  return this.databaseOpenPromise;
160
+ } else {
161
+ return this._reOpen();
159
162
  }
160
- return this._reOpen();
161
163
  }
162
164
 
163
165
  protected async _init() {
@@ -181,11 +183,15 @@ export class LockedAsyncDatabaseAdapter
181
183
  this.iterateListeners((cb) => cb.initialized?.());
182
184
  }
183
185
 
184
- getConfiguration(): ResolvedWebSQLOpenOptions {
186
+ getConfiguration(): WebDBAdapterConfiguration {
185
187
  if (!this._config) {
186
188
  throw new Error(`Cannot get config before initialization is completed`);
187
189
  }
188
- return this._config;
190
+ return {
191
+ ...this._config,
192
+ // This can be overridden by the adapter later
193
+ requiresPersistentTriggers: false
194
+ };
189
195
  }
190
196
 
191
197
  protected async waitForInitialized() {
@@ -313,9 +319,17 @@ export class LockedAsyncDatabaseAdapter
313
319
  protected async acquireLock(callback: () => Promise<any>, options?: { timeoutMs?: number }): Promise<any> {
314
320
  await this.waitForInitialized();
315
321
 
316
- // The database is being opened in the background. Wait for it here.
322
+ // The database is being (re)opened in the background. Wait for it here.
317
323
  if (this.databaseOpenPromise) {
318
324
  await this.databaseOpenPromise;
325
+ } else if (!this._db) {
326
+ /**
327
+ * The database is not open anymore, we might need to re-open it.
328
+ * Typically, _db, can be `null` if we tried to reOpen the database, but failed to succeed in re-opening.
329
+ * This can happen when disconnecting the client.
330
+ * Note: It is safe to re-enter this method multiple times.
331
+ */
332
+ await this.reOpenInternalDB();
319
333
  }
320
334
 
321
335
  return this._acquireLock(async () => {
@@ -335,11 +349,9 @@ export class LockedAsyncDatabaseAdapter
335
349
  return await callback();
336
350
  } catch (ex) {
337
351
  if (ConnectionClosedError.MATCHES(ex)) {
338
- if (this.options.reOpenOnConnectionClosed && !this.databaseOpenPromise && !this.closing) {
339
- // Immediately re-open the database. We need to miss as little table updates as possible.
340
- // Note, don't await this since it uses the same lock as we're in now.
341
- this.reOpenInternalDB();
342
- }
352
+ // Immediately re-open the database. We need to miss as little table updates as possible.
353
+ // Note, don't await this since it uses the same lock as we're in now.
354
+ this.reOpenInternalDB();
343
355
  }
344
356
  throw ex;
345
357
  } finally {
@@ -1,11 +1,15 @@
1
1
  import { DBAdapter } from '@powersync/common';
2
- import { ResolvedWebSQLOpenOptions } from './web-sql-flags';
2
+ import { ResolvedWebSQLOpenOptions } from './web-sql-flags.js';
3
3
 
4
4
  export type SharedConnectionWorker = {
5
5
  identifier: string;
6
6
  port: MessagePort;
7
7
  };
8
8
 
9
+ export type WebDBAdapterConfiguration = ResolvedWebSQLOpenOptions & {
10
+ requiresPersistentTriggers: boolean;
11
+ };
12
+
9
13
  export interface WebDBAdapter extends DBAdapter {
10
14
  /**
11
15
  * Get a MessagePort which can be used to share the internals of this connection.
@@ -16,5 +20,5 @@ export interface WebDBAdapter extends DBAdapter {
16
20
  * Get the config options used to open this connection.
17
21
  * This is useful for sharing connections.
18
22
  */
19
- getConfiguration(): ResolvedWebSQLOpenOptions;
23
+ getConfiguration(): WebDBAdapterConfiguration;
20
24
  }
@@ -5,8 +5,8 @@ import {
5
5
  OnTableChangeCallback,
6
6
  OpenAsyncDatabaseConnection,
7
7
  ProxiedQueryResult
8
- } from './AsyncDatabaseConnection';
9
- import { ResolvedWebSQLOpenOptions } from './web-sql-flags';
8
+ } from './AsyncDatabaseConnection.js';
9
+ import { ResolvedWebSQLOpenOptions } from './web-sql-flags.js';
10
10
 
11
11
  export type SharedConnectionWorker = {
12
12
  identifier: string;
@@ -0,0 +1,23 @@
1
+ import { LockedAsyncDatabaseAdapter } from '../LockedAsyncDatabaseAdapter.js';
2
+ import { WebDBAdapterConfiguration } from '../WebDBAdapter.js';
3
+ import { WASQLiteVFS } from './WASQLiteConnection.js';
4
+ import { ResolvedWASQLiteOpenFactoryOptions } from './WASQLiteOpenFactory.js';
5
+
6
+ /**
7
+ * @internal
8
+ * An intermediary implementation of WASQLiteDBAdapter, which takes the same
9
+ * constructor arguments as {@link LockedAsyncDatabaseAdapter}, but provides some
10
+ * basic WA-SQLite specific functionality.
11
+ * This base class is used to avoid requiring overloading the constructor of {@link WASQLiteDBAdapter}
12
+ */
13
+ export class InternalWASQLiteDBAdapter extends LockedAsyncDatabaseAdapter {
14
+ getConfiguration(): WebDBAdapterConfiguration {
15
+ // This is valid since we only handle WASQLite connections
16
+ const baseConfig = super.getConfiguration() as unknown as ResolvedWASQLiteOpenFactoryOptions;
17
+ return {
18
+ ...super.getConfiguration(),
19
+ requiresPersistentTriggers:
20
+ baseConfig.vfs == WASQLiteVFS.OPFSCoopSyncVFS || baseConfig.vfs == WASQLiteVFS.AccessHandlePoolVFS
21
+ };
22
+ }
23
+ }
@@ -1,8 +1,8 @@
1
1
  import * as SQLite from '@journeyapps/wa-sqlite';
2
2
  import { BaseObserver, BatchedUpdateNotification } from '@powersync/common';
3
3
  import { Mutex } from 'async-mutex';
4
- import { AsyncDatabaseConnection, OnTableChangeCallback, ProxiedQueryResult } from '../AsyncDatabaseConnection';
5
- import { ResolvedWASQLiteOpenFactoryOptions } from './WASQLiteOpenFactory';
4
+ import { AsyncDatabaseConnection, OnTableChangeCallback, ProxiedQueryResult } from '../AsyncDatabaseConnection.js';
5
+ import { ResolvedWASQLiteOpenFactoryOptions } from './WASQLiteOpenFactory.js';
6
6
  /**
7
7
  * List of currently tested virtual filesystems
8
8
  */
@@ -1,17 +1,17 @@
1
1
  import { type PowerSyncOpenFactoryOptions } from '@powersync/common';
2
2
  import * as Comlink from 'comlink';
3
- import { resolveWebPowerSyncFlags } from '../../PowerSyncDatabase';
4
- import { OpenAsyncDatabaseConnection } from '../AsyncDatabaseConnection';
5
- import { LockedAsyncDatabaseAdapter } from '../LockedAsyncDatabaseAdapter';
3
+ import { resolveWebPowerSyncFlags } from '../../PowerSyncDatabase.js';
4
+ import { OpenAsyncDatabaseConnection } from '../AsyncDatabaseConnection.js';
6
5
  import {
7
6
  DEFAULT_CACHE_SIZE_KB,
8
7
  ResolvedWebSQLOpenOptions,
9
8
  TemporaryStorageOption,
10
9
  WebSQLFlags
11
- } from '../web-sql-flags';
12
- import { WorkerWrappedAsyncDatabaseConnection } from '../WorkerWrappedAsyncDatabaseConnection';
13
- import { WASQLiteVFS } from './WASQLiteConnection';
14
- import { WASQLiteOpenFactory } from './WASQLiteOpenFactory';
10
+ } from '../web-sql-flags.js';
11
+ import { WorkerWrappedAsyncDatabaseConnection } from '../WorkerWrappedAsyncDatabaseConnection.js';
12
+ import { InternalWASQLiteDBAdapter } from './InternalWASQLiteDBAdapter.js';
13
+ import { WASQLiteVFS } from './WASQLiteConnection.js';
14
+ import { WASQLiteOpenFactory } from './WASQLiteOpenFactory.js';
15
15
 
16
16
  /**
17
17
  * These flags are the same as {@link WebSQLFlags}.
@@ -44,7 +44,7 @@ export interface WASQLiteDBAdapterOptions extends Omit<PowerSyncOpenFactoryOptio
44
44
  /**
45
45
  * Adapter for WA-SQLite SQLite connections.
46
46
  */
47
- export class WASQLiteDBAdapter extends LockedAsyncDatabaseAdapter {
47
+ export class WASQLiteDBAdapter extends InternalWASQLiteDBAdapter {
48
48
  constructor(options: WASQLiteDBAdapterOptions) {
49
49
  super({
50
50
  name: options.dbFilename,
@@ -1,17 +1,17 @@
1
1
  import { DBAdapter, type ILogLevel } from '@powersync/common';
2
2
  import * as Comlink from 'comlink';
3
- import { openWorkerDatabasePort, resolveWorkerDatabasePortFactory } from '../../../worker/db/open-worker-database';
4
- import { AbstractWebSQLOpenFactory } from '../AbstractWebSQLOpenFactory';
5
- import { AsyncDatabaseConnection, OpenAsyncDatabaseConnection } from '../AsyncDatabaseConnection';
6
- import { LockedAsyncDatabaseAdapter } from '../LockedAsyncDatabaseAdapter';
7
- import { WorkerWrappedAsyncDatabaseConnection } from '../WorkerWrappedAsyncDatabaseConnection';
3
+ import { openWorkerDatabasePort, resolveWorkerDatabasePortFactory } from '../../../worker/db/open-worker-database.js';
4
+ import { AbstractWebSQLOpenFactory } from '../AbstractWebSQLOpenFactory.js';
5
+ import { AsyncDatabaseConnection, OpenAsyncDatabaseConnection } from '../AsyncDatabaseConnection.js';
6
+ import { WorkerWrappedAsyncDatabaseConnection } from '../WorkerWrappedAsyncDatabaseConnection.js';
8
7
  import {
9
8
  DEFAULT_CACHE_SIZE_KB,
10
9
  ResolvedWebSQLOpenOptions,
11
10
  TemporaryStorageOption,
12
11
  WebSQLOpenFactoryOptions
13
- } from '../web-sql-flags';
14
- import { WASQLiteVFS, WASqliteConnection } from './WASQLiteConnection';
12
+ } from '../web-sql-flags.js';
13
+ import { InternalWASQLiteDBAdapter } from './InternalWASQLiteDBAdapter.js';
14
+ import { WASQLiteVFS, WASqliteConnection } from './WASQLiteConnection.js';
15
15
 
16
16
  export interface WASQLiteOpenFactoryOptions extends WebSQLOpenFactoryOptions {
17
17
  vfs?: WASQLiteVFS;
@@ -41,7 +41,7 @@ export class WASQLiteOpenFactory extends AbstractWebSQLOpenFactory {
41
41
  }
42
42
 
43
43
  protected openAdapter(): DBAdapter {
44
- return new LockedAsyncDatabaseAdapter({
44
+ return new InternalWASQLiteDBAdapter({
45
45
  name: this.options.dbFilename,
46
46
  openConnection: () => this.openConnection(),
47
47
  debugMode: this.options.debugMode,
@@ -1,7 +1,7 @@
1
1
  import { AbstractPowerSyncDatabase, DBAdapter, PowerSyncDatabaseOptions } from '@powersync/common';
2
- import { PowerSyncDatabase } from '../../../db/PowerSyncDatabase';
3
- import { AbstractWebPowerSyncDatabaseOpenFactory } from '../AbstractWebPowerSyncDatabaseOpenFactory';
4
- import { WASQLiteOpenFactory } from './WASQLiteOpenFactory';
2
+ import { PowerSyncDatabase } from '../../../db/PowerSyncDatabase.js';
3
+ import { AbstractWebPowerSyncDatabaseOpenFactory } from '../AbstractWebPowerSyncDatabaseOpenFactory.js';
4
+ import { WASQLiteOpenFactory } from './WASQLiteOpenFactory.js';
5
5
 
6
6
  /**
7
7
  * @deprecated {@link PowerSyncDatabase} can now be constructed directly
@@ -5,16 +5,16 @@ import {
5
5
  SyncStatusOptions
6
6
  } from '@powersync/common';
7
7
  import * as Comlink from 'comlink';
8
- import { getNavigatorLocks } from '../../shared/navigator';
9
- import { AbstractSharedSyncClientProvider } from '../../worker/sync/AbstractSharedSyncClientProvider';
10
- import { ManualSharedSyncPayload, SharedSyncClientEvent } from '../../worker/sync/SharedSyncImplementation';
11
- import { WorkerClient } from '../../worker/sync/WorkerClient';
12
- import { WebDBAdapter } from '../adapters/WebDBAdapter';
13
- import { DEFAULT_CACHE_SIZE_KB, TemporaryStorageOption, resolveWebSQLFlags } from '../adapters/web-sql-flags';
8
+ import { getNavigatorLocks } from '../../shared/navigator.js';
9
+ import { AbstractSharedSyncClientProvider } from '../../worker/sync/AbstractSharedSyncClientProvider.js';
10
+ import { ManualSharedSyncPayload, SharedSyncClientEvent } from '../../worker/sync/SharedSyncImplementation.js';
11
+ import { WorkerClient } from '../../worker/sync/WorkerClient.js';
12
+ import { WebDBAdapter } from '../adapters/WebDBAdapter.js';
13
+ import { DEFAULT_CACHE_SIZE_KB, TemporaryStorageOption, resolveWebSQLFlags } from '../adapters/web-sql-flags.js';
14
14
  import {
15
15
  WebStreamingSyncImplementation,
16
16
  WebStreamingSyncImplementationOptions
17
- } from './WebStreamingSyncImplementation';
17
+ } from './WebStreamingSyncImplementation.js';
18
18
 
19
19
  /**
20
20
  * The shared worker will trigger methods on this side of the message port
@@ -9,7 +9,7 @@ import {
9
9
  RemoteConnector
10
10
  } from '@powersync/common';
11
11
 
12
- import { getUserAgentInfo } from './userAgent';
12
+ import { getUserAgentInfo } from './userAgent.js';
13
13
 
14
14
  /*
15
15
  * Depends on browser's implementation of global fetch.
@@ -4,8 +4,8 @@ import {
4
4
  LockOptions,
5
5
  LockType
6
6
  } from '@powersync/common';
7
- import { getNavigatorLocks } from '../../shared/navigator';
8
- import { ResolvedWebSQLOpenOptions, WebSQLFlags } from '../adapters/web-sql-flags';
7
+ import { getNavigatorLocks } from '../../shared/navigator.js';
8
+ import { ResolvedWebSQLOpenOptions, WebSQLFlags } from '../adapters/web-sql-flags.js';
9
9
 
10
10
  export interface WebStreamingSyncImplementationOptions extends AbstractStreamingSyncImplementationOptions {
11
11
  flags?: WebSQLFlags;