@powersync/web 0.0.0-dev-20260708104358 → 0.0.0-dev-20260917074240

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 (267) hide show
  1. package/README.md +1 -11
  2. package/bin/powersync.cjs +1 -1
  3. package/dist/index.react_native_web.js +2095 -0
  4. package/dist/index.react_native_web.js.map +1 -0
  5. package/dist/worker/AccessHandlePoolVFS-BPUHfZME.js +2 -0
  6. package/dist/worker/AccessHandlePoolVFS-BPUHfZME.js.map +1 -0
  7. package/dist/worker/FacadeVFS-d1ZDvud7.js +2 -0
  8. package/dist/worker/FacadeVFS-d1ZDvud7.js.map +1 -0
  9. package/dist/worker/IDBBatchAtomicVFS-DbkDb777.js +2 -0
  10. package/dist/worker/IDBBatchAtomicVFS-DbkDb777.js.map +1 -0
  11. package/dist/worker/MemoryVFS-DVJL5F8j.js +2 -0
  12. package/dist/worker/MemoryVFS-DVJL5F8j.js.map +1 -0
  13. package/dist/worker/OPFSCoopSyncVFS-BgTiWPfa.js +2 -0
  14. package/dist/worker/OPFSCoopSyncVFS-BgTiWPfa.js.map +1 -0
  15. package/dist/worker/OPFSWriteAheadVFS-Rt5CGCZP.js +2 -0
  16. package/dist/worker/OPFSWriteAheadVFS-Rt5CGCZP.js.map +1 -0
  17. package/dist/worker/assets/mc-wa-sqlite-BHScYYZw.wasm +0 -0
  18. package/dist/worker/assets/mc-wa-sqlite-async-DdlQmAUV.wasm +0 -0
  19. package/dist/worker/assets/wa-sqlite-CIxTmRHQ.wasm +0 -0
  20. package/dist/worker/assets/wa-sqlite-async-zc68fxQq.wasm +0 -0
  21. package/dist/worker/mc-wa-sqlite-PubB6u8c.js +2 -0
  22. package/dist/worker/mc-wa-sqlite-PubB6u8c.js.map +1 -0
  23. package/dist/worker/mc-wa-sqlite-async-DJG_ANKO.js +2 -0
  24. package/dist/worker/mc-wa-sqlite-async-DJG_ANKO.js.map +1 -0
  25. package/dist/worker/wa-sqlite-D1_4mGs8.js +2 -0
  26. package/dist/worker/wa-sqlite-D1_4mGs8.js.map +1 -0
  27. package/dist/worker/wa-sqlite-async-BxkwNY-2.js +2 -0
  28. package/dist/worker/wa-sqlite-async-BxkwNY-2.js.map +1 -0
  29. package/dist/worker/websockets-Q8W_lerF.js +9 -0
  30. package/dist/worker/websockets-Q8W_lerF.js.map +1 -0
  31. package/dist/worker/worker.js +7 -0
  32. package/dist/worker/worker.js.map +1 -0
  33. package/lib/attachments/IndexDBFileSystemAdapter.js.map +1 -0
  34. package/lib/{src/db → db}/NavigatorTriggerClaimManager.d.ts +1 -1
  35. package/lib/db/NavigatorTriggerClaimManager.js.map +1 -0
  36. package/lib/db/PowerSyncDatabase.d.ts +66 -0
  37. package/lib/{src/db → db}/PowerSyncDatabase.js +60 -79
  38. package/lib/db/PowerSyncDatabase.js.map +1 -0
  39. package/lib/db/adapters/AsyncWebAdapter.d.ts +32 -0
  40. package/lib/{src/db → db}/adapters/AsyncWebAdapter.js +18 -69
  41. package/lib/db/adapters/AsyncWebAdapter.js.map +1 -0
  42. package/lib/db/adapters/SSRDBAdapter.d.ts +17 -0
  43. package/lib/db/adapters/SSRDBAdapter.js +37 -0
  44. package/lib/db/adapters/SSRDBAdapter.js.map +1 -0
  45. package/lib/{src/db → db}/adapters/WebDBAdapter.d.ts +1 -1
  46. package/lib/db/adapters/WebDBAdapter.js.map +1 -0
  47. package/lib/db/adapters/acquireFromPool.d.ts +7 -0
  48. package/lib/db/adapters/acquireFromPool.js +60 -0
  49. package/lib/db/adapters/acquireFromPool.js.map +1 -0
  50. package/lib/db/adapters/memory-pool/client.d.ts +70 -0
  51. package/lib/db/adapters/memory-pool/client.js +269 -0
  52. package/lib/db/adapters/memory-pool/client.js.map +1 -0
  53. package/lib/db/adapters/memory-pool/shared.d.ts +51 -0
  54. package/lib/db/adapters/memory-pool/shared.js +16 -0
  55. package/lib/db/adapters/memory-pool/shared.js.map +1 -0
  56. package/lib/db/adapters/memory-pool/vfs.d.ts +19 -0
  57. package/lib/db/adapters/memory-pool/vfs.js +247 -0
  58. package/lib/db/adapters/memory-pool/vfs.js.map +1 -0
  59. package/lib/db/adapters/memory-pool/worker.js +45 -0
  60. package/lib/db/adapters/memory-pool/worker.js.map +1 -0
  61. package/lib/db/adapters/options.d.ts +94 -0
  62. package/lib/db/adapters/options.js +6 -0
  63. package/lib/db/adapters/options.js.map +1 -0
  64. package/lib/db/adapters/resolveAndValidateOptions.d.ts +13 -0
  65. package/lib/db/adapters/resolveAndValidateOptions.js +41 -0
  66. package/lib/db/adapters/resolveAndValidateOptions.js.map +1 -0
  67. package/lib/{src/db → db}/adapters/wa-sqlite/ConcurrentConnection.d.ts +3 -4
  68. package/lib/{src/db → db}/adapters/wa-sqlite/ConcurrentConnection.js +2 -2
  69. package/lib/db/adapters/wa-sqlite/ConcurrentConnection.js.map +1 -0
  70. package/lib/{src/db → db}/adapters/wa-sqlite/DatabaseClient.d.ts +4 -4
  71. package/lib/{src/db → db}/adapters/wa-sqlite/DatabaseClient.js +11 -37
  72. package/lib/db/adapters/wa-sqlite/DatabaseClient.js.map +1 -0
  73. package/lib/{src/db → db}/adapters/wa-sqlite/DatabaseServer.d.ts +5 -5
  74. package/lib/{src/db → db}/adapters/wa-sqlite/DatabaseServer.js +14 -7
  75. package/lib/db/adapters/wa-sqlite/DatabaseServer.js.map +1 -0
  76. package/lib/{src/db → db}/adapters/wa-sqlite/RawSqliteConnection.d.ts +30 -12
  77. package/lib/{src/db → db}/adapters/wa-sqlite/RawSqliteConnection.js +70 -16
  78. package/lib/db/adapters/wa-sqlite/RawSqliteConnection.js.map +1 -0
  79. package/lib/db/adapters/wa-sqlite/StatementCache.d.ts +16 -0
  80. package/lib/db/adapters/wa-sqlite/StatementCache.js +44 -0
  81. package/lib/db/adapters/wa-sqlite/StatementCache.js.map +1 -0
  82. package/lib/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +18 -0
  83. package/lib/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +140 -0
  84. package/lib/db/adapters/wa-sqlite/WASQLiteOpenFactory.js.map +1 -0
  85. package/lib/{src/db → db}/adapters/wa-sqlite/vfs.d.ts +9 -2
  86. package/lib/{src/db → db}/adapters/wa-sqlite/vfs.js +6 -6
  87. package/lib/db/adapters/wa-sqlite/vfs.js.map +1 -0
  88. package/lib/{src/db → db}/sync/SSRWebStreamingSyncImplementation.d.ts +5 -16
  89. package/lib/{src/db → db}/sync/SSRWebStreamingSyncImplementation.js +7 -23
  90. package/lib/db/sync/SSRWebStreamingSyncImplementation.js.map +1 -0
  91. package/lib/{src/db → db}/sync/SharedWebStreamingSyncImplementation.d.ts +15 -15
  92. package/lib/{src/db → db}/sync/SharedWebStreamingSyncImplementation.js +38 -70
  93. package/lib/db/sync/SharedWebStreamingSyncImplementation.js.map +1 -0
  94. package/lib/db/sync/TabLocalStreamingSyncImplementation.d.ts +19 -0
  95. package/lib/db/sync/TabLocalStreamingSyncImplementation.js +70 -0
  96. package/lib/db/sync/TabLocalStreamingSyncImplementation.js.map +1 -0
  97. package/lib/db/sync/WebRemote.d.ts +10 -0
  98. package/lib/db/sync/WebRemote.js +33 -0
  99. package/lib/db/sync/WebRemote.js.map +1 -0
  100. package/lib/{src/db → db}/sync/WebStreamingSyncImplementation.d.ts +2 -4
  101. package/lib/{src/db → db}/sync/WebStreamingSyncImplementation.js +3 -2
  102. package/lib/db/sync/WebStreamingSyncImplementation.js.map +1 -0
  103. package/lib/db/sync/userAgent.js.map +1 -0
  104. package/lib/{src/index.d.ts → index.d.ts} +1 -3
  105. package/lib/{src/index.js → index.js} +1 -3
  106. package/lib/index.js.map +1 -0
  107. package/lib/shared/navigator.js.map +1 -0
  108. package/lib/shared/tab_close_signal.js.map +1 -0
  109. package/lib/worker/SharedWorkerConnectionRequest.d.ts +5 -0
  110. package/lib/worker/SharedWorkerConnectionRequest.js +2 -0
  111. package/lib/worker/SharedWorkerConnectionRequest.js.map +1 -0
  112. package/lib/worker/client.d.ts +17 -0
  113. package/lib/worker/client.js +90 -0
  114. package/lib/worker/client.js.map +1 -0
  115. package/lib/worker/db/MultiDatabaseServer.d.ts +21 -0
  116. package/lib/{src/worker → worker}/db/MultiDatabaseServer.js +45 -24
  117. package/lib/worker/db/MultiDatabaseServer.js.map +1 -0
  118. package/lib/worker/sync/AbstractSharedSyncClientProvider.d.ts +14 -0
  119. package/lib/worker/sync/AbstractSharedSyncClientProvider.js.map +1 -0
  120. package/lib/worker/sync/BroadcastLogger.d.ts +27 -0
  121. package/lib/worker/sync/BroadcastLogger.js +65 -0
  122. package/lib/worker/sync/BroadcastLogger.js.map +1 -0
  123. package/lib/{src/worker → worker}/sync/SharedSyncImplementation.d.ts +14 -25
  124. package/lib/{src/worker → worker}/sync/SharedSyncImplementation.js +140 -107
  125. package/lib/worker/sync/SharedSyncImplementation.js.map +1 -0
  126. package/lib/{src/worker → worker}/sync/WorkerClient.d.ts +4 -4
  127. package/lib/{src/worker → worker}/sync/WorkerClient.js +5 -5
  128. package/lib/worker/sync/WorkerClient.js.map +1 -0
  129. package/lib/worker/worker.d.ts +1 -0
  130. package/lib/worker/worker.js +34 -0
  131. package/lib/worker/worker.js.map +1 -0
  132. package/package.json +31 -32
  133. package/src/db/NavigatorTriggerClaimManager.ts +1 -1
  134. package/src/db/PowerSyncDatabase.ts +96 -144
  135. package/src/db/adapters/AsyncWebAdapter.ts +29 -86
  136. package/src/db/adapters/SSRDBAdapter.ts +14 -64
  137. package/src/db/adapters/WebDBAdapter.ts +1 -1
  138. package/src/db/adapters/acquireFromPool.ts +73 -0
  139. package/src/db/adapters/memory-pool/client.ts +367 -0
  140. package/src/db/adapters/memory-pool/shared.ts +79 -0
  141. package/src/db/adapters/memory-pool/vfs.ts +293 -0
  142. package/src/db/adapters/memory-pool/worker.ts +53 -0
  143. package/src/db/adapters/options.ts +108 -0
  144. package/src/db/adapters/resolveAndValidateOptions.ts +49 -0
  145. package/src/db/adapters/wa-sqlite/ConcurrentConnection.ts +4 -5
  146. package/src/db/adapters/wa-sqlite/DatabaseClient.ts +20 -56
  147. package/src/db/adapters/wa-sqlite/DatabaseServer.ts +18 -12
  148. package/src/db/adapters/wa-sqlite/RawSqliteConnection.ts +108 -30
  149. package/src/db/adapters/wa-sqlite/StatementCache.ts +50 -0
  150. package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +82 -125
  151. package/src/db/adapters/wa-sqlite/vfs.ts +13 -8
  152. package/src/db/sync/SSRWebStreamingSyncImplementation.ts +8 -36
  153. package/src/db/sync/SharedWebStreamingSyncImplementation.ts +47 -82
  154. package/src/db/sync/TabLocalStreamingSyncImplementation.ts +90 -0
  155. package/src/db/sync/WebRemote.ts +23 -26
  156. package/src/db/sync/WebStreamingSyncImplementation.ts +4 -5
  157. package/src/index.ts +1 -3
  158. package/src/worker/SharedWorkerConnectionRequest.ts +6 -0
  159. package/src/worker/client.ts +121 -0
  160. package/src/worker/db/MultiDatabaseServer.ts +59 -33
  161. package/src/worker/sync/AbstractSharedSyncClientProvider.ts +5 -10
  162. package/src/worker/sync/BroadcastLogger.ts +35 -103
  163. package/src/worker/sync/SharedSyncImplementation.ts +197 -138
  164. package/src/worker/sync/WorkerClient.ts +8 -8
  165. package/src/worker/worker.ts +38 -0
  166. package/dist/2075a31bb151adbb9767.wasm +0 -0
  167. package/dist/3322bc84de986b63c2cd.wasm +0 -0
  168. package/dist/8e97452e297be23b5e50.wasm +0 -0
  169. package/dist/fbc178b70d530e8ce02b.wasm +0 -0
  170. package/dist/index.umd.js +0 -7821
  171. package/dist/index.umd.js.map +0 -1
  172. package/dist/worker/SharedSyncImplementation.umd.js +0 -16139
  173. package/dist/worker/SharedSyncImplementation.umd.js.map +0 -1
  174. package/dist/worker/WASQLiteDB.umd.js +0 -17434
  175. package/dist/worker/WASQLiteDB.umd.js.map +0 -1
  176. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-9af0a7.umd.js +0 -31
  177. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-9af0a7.umd.js.map +0 -1
  178. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-bbf5a9.umd.js +0 -31
  179. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_mc-wa-s-bbf5a9.umd.js.map +0 -1
  180. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-c26e0f.umd.js +0 -31
  181. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqli-c26e0f.umd.js.map +0 -1
  182. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js +0 -31
  183. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_dist_wa-sqlite_mjs.umd.js.map +0 -1
  184. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-2fb422.umd.js +0 -3562
  185. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-2fb422.umd.js.map +0 -1
  186. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-833585.umd.js +0 -1400
  187. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-833585.umd.js.map +0 -1
  188. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-96fb23.umd.js +0 -2478
  189. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-96fb23.umd.js.map +0 -1
  190. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-c89911.umd.js +0 -1681
  191. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-c89911.umd.js.map +0 -1
  192. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-ec4eb1.umd.js +0 -1820
  193. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-ec4eb1.umd.js.map +0 -1
  194. package/lib/package.json +0 -91
  195. package/lib/src/attachments/IndexDBFileSystemAdapter.js.map +0 -1
  196. package/lib/src/db/NavigatorTriggerClaimManager.js.map +0 -1
  197. package/lib/src/db/PowerSyncDatabase.d.ts +0 -78
  198. package/lib/src/db/PowerSyncDatabase.js.map +0 -1
  199. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.d.ts +0 -23
  200. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js +0 -27
  201. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js.map +0 -1
  202. package/lib/src/db/adapters/AsyncWebAdapter.d.ts +0 -50
  203. package/lib/src/db/adapters/AsyncWebAdapter.js.map +0 -1
  204. package/lib/src/db/adapters/SSRDBAdapter.d.ts +0 -30
  205. package/lib/src/db/adapters/SSRDBAdapter.js +0 -69
  206. package/lib/src/db/adapters/SSRDBAdapter.js.map +0 -1
  207. package/lib/src/db/adapters/WebDBAdapter.js.map +0 -1
  208. package/lib/src/db/adapters/wa-sqlite/ConcurrentConnection.js.map +0 -1
  209. package/lib/src/db/adapters/wa-sqlite/DatabaseClient.js.map +0 -1
  210. package/lib/src/db/adapters/wa-sqlite/DatabaseServer.js.map +0 -1
  211. package/lib/src/db/adapters/wa-sqlite/RawSqliteConnection.js.map +0 -1
  212. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +0 -45
  213. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +0 -146
  214. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js.map +0 -1
  215. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.d.ts +0 -15
  216. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js +0 -22
  217. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js.map +0 -1
  218. package/lib/src/db/adapters/wa-sqlite/vfs.js.map +0 -1
  219. package/lib/src/db/adapters/web-sql-flags.d.ts +0 -92
  220. package/lib/src/db/adapters/web-sql-flags.js +0 -37
  221. package/lib/src/db/adapters/web-sql-flags.js.map +0 -1
  222. package/lib/src/db/sync/SSRWebStreamingSyncImplementation.js.map +0 -1
  223. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js.map +0 -1
  224. package/lib/src/db/sync/WebRemote.d.ts +0 -7
  225. package/lib/src/db/sync/WebRemote.js +0 -33
  226. package/lib/src/db/sync/WebRemote.js.map +0 -1
  227. package/lib/src/db/sync/WebStreamingSyncImplementation.js.map +0 -1
  228. package/lib/src/db/sync/userAgent.js.map +0 -1
  229. package/lib/src/index.js.map +0 -1
  230. package/lib/src/shared/navigator.js.map +0 -1
  231. package/lib/src/shared/tab_close_signal.js.map +0 -1
  232. package/lib/src/worker/db/MultiDatabaseServer.d.ts +0 -17
  233. package/lib/src/worker/db/MultiDatabaseServer.js.map +0 -1
  234. package/lib/src/worker/db/WASQLiteDB.worker.d.ts +0 -4
  235. package/lib/src/worker/db/WASQLiteDB.worker.js +0 -31
  236. package/lib/src/worker/db/WASQLiteDB.worker.js.map +0 -1
  237. package/lib/src/worker/db/open-worker-database.d.ts +0 -14
  238. package/lib/src/worker/db/open-worker-database.js +0 -53
  239. package/lib/src/worker/db/open-worker-database.js.map +0 -1
  240. package/lib/src/worker/sync/AbstractSharedSyncClientProvider.d.ts +0 -19
  241. package/lib/src/worker/sync/AbstractSharedSyncClientProvider.js.map +0 -1
  242. package/lib/src/worker/sync/BroadcastLogger.d.ts +0 -47
  243. package/lib/src/worker/sync/BroadcastLogger.js +0 -129
  244. package/lib/src/worker/sync/BroadcastLogger.js.map +0 -1
  245. package/lib/src/worker/sync/SharedSyncImplementation.js.map +0 -1
  246. package/lib/src/worker/sync/SharedSyncImplementation.worker.js +0 -12
  247. package/lib/src/worker/sync/SharedSyncImplementation.worker.js.map +0 -1
  248. package/lib/src/worker/sync/WorkerClient.js.map +0 -1
  249. package/lib/tsconfig.tsbuildinfo +0 -1
  250. package/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.ts +0 -47
  251. package/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.ts +0 -24
  252. package/src/db/adapters/web-sql-flags.ts +0 -141
  253. package/src/worker/db/WASQLiteDB.worker.ts +0 -35
  254. package/src/worker/db/open-worker-database.ts +0 -62
  255. package/src/worker/sync/SharedSyncImplementation.worker.ts +0 -14
  256. /package/lib/{src/attachments → attachments}/IndexDBFileSystemAdapter.d.ts +0 -0
  257. /package/lib/{src/attachments → attachments}/IndexDBFileSystemAdapter.js +0 -0
  258. /package/lib/{src/db → db}/NavigatorTriggerClaimManager.js +0 -0
  259. /package/lib/{src/db → db}/adapters/WebDBAdapter.js +0 -0
  260. /package/lib/{src/worker/sync/SharedSyncImplementation.worker.d.ts → db/adapters/memory-pool/worker.d.ts} +0 -0
  261. /package/lib/{src/db → db}/sync/userAgent.d.ts +0 -0
  262. /package/lib/{src/db → db}/sync/userAgent.js +0 -0
  263. /package/lib/{src/shared → shared}/navigator.d.ts +0 -0
  264. /package/lib/{src/shared → shared}/navigator.js +0 -0
  265. /package/lib/{src/shared → shared}/tab_close_signal.d.ts +0 -0
  266. /package/lib/{src/shared → shared}/tab_close_signal.js +0 -0
  267. /package/lib/{src/worker → worker}/sync/AbstractSharedSyncClientProvider.js +0 -0
@@ -1,11 +1,11 @@
1
- import { ILogger } from '@powersync/common';
1
+ import { LogLevels, PowerSyncLogger } from '@powersync/common';
2
2
  import { ConcurrentSqliteConnection, ConnectionLeaseToken } from './ConcurrentConnection.js';
3
- import { RawQueryResult } from './RawSqliteConnection.js';
3
+ import { RawWebResult } from './RawSqliteConnection.js';
4
4
 
5
5
  export interface DatabaseServerOptions {
6
6
  inner: ConcurrentSqliteConnection;
7
7
  onClose: () => void;
8
- logger: ILogger;
8
+ logger: PowerSyncLogger;
9
9
  }
10
10
 
11
11
  /**
@@ -24,7 +24,7 @@ export class DatabaseServer {
24
24
  constructor(options: DatabaseServerOptions) {
25
25
  this.#options = options;
26
26
  const inner = options.inner;
27
- this.#updateBroadcastChannel = new BroadcastChannel(`${inner.options.dbFilename}-table-updates`);
27
+ this.#updateBroadcastChannel = new BroadcastChannel(`${inner.options.filename}-table-updates`);
28
28
 
29
29
  this.#updateBroadcastChannel.onmessage = ({ data }) => {
30
30
  this.#pushTableUpdateToClients(data as string[]);
@@ -85,7 +85,7 @@ export class DatabaseServer {
85
85
 
86
86
  // If the client holds a connection lease it hasn't returned, return that now.
87
87
  for (const { lease } of connectionLeases.values()) {
88
- this.#logger.debug(`Closing connection lease that hasn't been returned.`);
88
+ this.#logger.log({ level: LogLevels.debug, message: `Closing connection lease that hasn't been returned.` });
89
89
  await lease.returnLease();
90
90
  }
91
91
 
@@ -94,7 +94,10 @@ export class DatabaseServer {
94
94
  if (this.#activeClients.size == 0) {
95
95
  await this.forceClose();
96
96
  } else {
97
- this.#logger.debug('Keeping underlying connection active since its used by other clients.');
97
+ this.#logger.log({
98
+ level: LogLevels.debug,
99
+ message: 'Keeping underlying connection active since its used by other clients.'
100
+ });
98
101
  }
99
102
  }
100
103
  };
@@ -133,9 +136,9 @@ export class DatabaseServer {
133
136
  try {
134
137
  if (lease.write) {
135
138
  // Collect update hooks invoked while the client had the write connection.
136
- const { resultSet } = await lease.lease.use((conn) => conn.execute(`SELECT powersync_update_hooks('get')`));
137
- if (resultSet) {
138
- const updatedTables: string[] = JSON.parse(resultSet.rows[0][0] as string);
139
+ const { rawRows } = await lease.lease.use((conn) => conn.execute(`SELECT powersync_update_hooks('get')`));
140
+ if (rawRows.length) {
141
+ const updatedTables: string[] = JSON.parse(rawRows[0][0] as string);
139
142
  if (updatedTables.length) {
140
143
  this.#updateBroadcastChannel.postMessage(updatedTables);
141
144
  this.#pushTableUpdateToClients(updatedTables);
@@ -169,7 +172,10 @@ export class DatabaseServer {
169
172
  }
170
173
 
171
174
  async forceClose() {
172
- this.#logger.debug(`Closing connection to ${this.#inner.options}.`);
175
+ this.#logger.log({
176
+ level: LogLevels.debug,
177
+ message: `Closing connection to ${JSON.stringify(this.#inner.options)}.`
178
+ });
173
179
  const connection = this.#inner;
174
180
  this.#options.onClose();
175
181
  this.#updateBroadcastChannel.close();
@@ -190,8 +196,8 @@ export interface ClientConnectionView {
190
196
  * give other clients access to the database afterwards.
191
197
  */
192
198
  requestAccess(write: boolean, timeoutMs?: number): Promise<string>;
193
- execute(token: string, sql: string, params: any[] | undefined): Promise<RawQueryResult>;
194
- executeBatch(token: string, sql: string, params: any[][]): Promise<RawQueryResult[]>;
199
+ execute(token: string, sql: string, params: any[] | undefined): Promise<RawWebResult>;
200
+ executeBatch(token: string, sql: string, params: any[][]): Promise<RawWebResult[]>;
195
201
  completeAccess(token: string): Promise<void>;
196
202
 
197
203
  /**
@@ -1,18 +1,34 @@
1
1
  import { Factory as WaSqliteFactory, SQLITE_ROW } from '@journeyapps/wa-sqlite';
2
2
 
3
- import { loadModuleAndVfs } from './vfs.js';
4
- import { ResolvedWASQLiteOpenFactoryOptions } from './WASQLiteOpenFactory.js';
3
+ import { loadModuleAndVfs, WASQLiteVFS } from './vfs.js';
4
+ import { TemporaryStorageOption } from '../options.js';
5
+ import { RawQueryResult, SqliteValue } from '@powersync/common';
6
+ import { maxPathNameLength } from '../resolveAndValidateOptions.js';
7
+ import { PreparedStatementCache } from './StatementCache.js';
8
+
9
+ export interface RawWebResult extends Required<RawQueryResult> {
10
+ autocommit: boolean;
11
+ }
5
12
 
6
13
  export interface RawResultSet {
7
- columns: string[];
8
- rows: SQLiteCompatibleType[][];
14
+ columnNames: string[];
15
+ rawRows: SqliteValue[][];
9
16
  }
10
17
 
11
- export interface RawQueryResult {
12
- changes: number;
13
- lastInsertRowId: number;
14
- autocommit: boolean;
15
- resultSet: RawResultSet | undefined;
18
+ /**
19
+ * @internal
20
+ */
21
+ export interface RawWaSqliteDatabaseOptions {
22
+ filename: string;
23
+ readonly: boolean;
24
+ vfs: WASQLiteVFS;
25
+ encryptionKey: string | undefined;
26
+ temporaryStorage: TemporaryStorageOption;
27
+ cacheSizeKb: number;
28
+ /**
29
+ * The amount of prepared statements to cache, or 0 to disable caching.
30
+ */
31
+ preparedStatementsCache: number;
16
32
  }
17
33
 
18
34
  /**
@@ -23,35 +39,48 @@ export interface RawQueryResult {
23
39
  */
24
40
  export class RawSqliteConnection {
25
41
  private _sqliteAPI: SQLiteAPI | null = null;
42
+ private sqlite3_stmt_isexplain!: (stmt: number) => 0 | 1 | 2;
43
+
26
44
  /**
27
45
  * The `sqlite3*` connection pointer.
28
46
  */
29
47
  private db: number = 0;
48
+ private statementCache: PreparedStatementCache | null;
30
49
 
31
- constructor(readonly options: ResolvedWASQLiteOpenFactoryOptions) {}
50
+ constructor(readonly options: RawWaSqliteDatabaseOptions) {
51
+ this.statementCache =
52
+ options.preparedStatementsCache > 0 ? new PreparedStatementCache(options.preparedStatementsCache) : null;
53
+ }
32
54
 
33
55
  get isOpen(): boolean {
34
56
  return this.db != 0;
35
57
  }
36
58
 
37
59
  async init() {
38
- const api = (this._sqliteAPI = await this.openSQLiteAPI());
60
+ const { module, vfs } = await loadModuleAndVfs(this.options);
61
+ await this.initWithModule(module, vfs);
62
+ }
63
+
64
+ async initWithModule(module: any, vfs: any) {
65
+ const api = (this._sqliteAPI = await this.openSQLiteAPI(module, vfs));
39
66
  this.db = await api.open_v2(
40
- this.options.dbFilename,
41
- this.options.isReadOnly ? 1 /* SQLITE_OPEN_READONLY */ : 6 /* SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE */
67
+ this.options.filename,
68
+ this.options.readonly ? 1 /* SQLITE_OPEN_READONLY */ : 6 /* SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE */
42
69
  );
43
70
  await this.executeRaw(`PRAGMA temp_store = ${this.options.temporaryStorage};`);
44
71
  if (this.options.encryptionKey) {
45
- const escapedKey = this.options.encryptionKey.replace("'", "''");
46
- await this.executeRaw(`PRAGMA key = '${escapedKey}'`);
72
+ const escapedKey = this.options.encryptionKey.replaceAll("'", "''");
73
+ await this.executeRaw(`PRAGMA key = '${escapedKey}';`);
47
74
  }
48
75
  await this.executeRaw(`PRAGMA cache_size = -${this.options.cacheSizeKb};`);
49
76
 
50
77
  await this.executeRaw(`SELECT powersync_update_hooks('install');`);
51
78
  }
52
79
 
53
- private async openSQLiteAPI(): Promise<SQLiteAPI> {
54
- const { module, vfs } = await loadModuleAndVfs(this.options);
80
+ private async openSQLiteAPI(module: any, vfs: SQLiteVFS): Promise<SQLiteAPI> {
81
+ vfs.mxPathname = maxPathNameLength;
82
+
83
+ this.sqlite3_stmt_isexplain = module.cwrap('sqlite3_stmt_isexplain', 'int', ['int']);
55
84
  const sqlite3 = WaSqliteFactory(module);
56
85
  sqlite3.vfs_register(vfs, true);
57
86
  /**
@@ -63,7 +92,7 @@ export class RawSqliteConnection {
63
92
  * Create the multiple cipher vfs if an encryption key is provided
64
93
  */
65
94
  if (this.options.encryptionKey) {
66
- const createResult = module.ccall('sqlite3mc_vfs_create', 'int', ['string', 'int'], [this.options.dbFilename, 1]);
95
+ const createResult = module.ccall('sqlite3mc_vfs_create', 'int', ['string', 'int'], [this.options.filename, 1]);
67
96
  if (createResult !== 0) {
68
97
  throw new Error('Failed to create multiple cipher vfs, Database encryption will not work');
69
98
  }
@@ -87,12 +116,12 @@ export class RawSqliteConnection {
87
116
  return this.requireSqlite().get_autocommit(this.db) != 0;
88
117
  }
89
118
 
90
- async execute(sql: string, bindings?: any[]): Promise<RawQueryResult> {
119
+ async execute(sql: string, bindings?: any[]): Promise<RawWebResult> {
91
120
  const resultSet = await this.executeSingleStatementRaw(sql, bindings);
92
121
  return this.wrapQueryResults(this.requireSqlite(), resultSet);
93
122
  }
94
123
 
95
- async executeBatch(sql: string, bindings: any[][]): Promise<RawQueryResult[]> {
124
+ async executeBatch(sql: string, bindings: any[][]): Promise<RawWebResult[]> {
96
125
  const results = [];
97
126
  const api = this.requireSqlite();
98
127
  for await (const stmt of api.statements(this.db, sql)) {
@@ -110,31 +139,32 @@ export class RawSqliteConnection {
110
139
  return results;
111
140
  }
112
141
 
113
- private wrapQueryResults(api: SQLiteAPI, rs: RawResultSet | undefined): RawQueryResult {
142
+ private wrapQueryResults(api: SQLiteAPI, { rawRows, columnNames }: RawResultSet): RawWebResult {
114
143
  return {
115
- changes: api.changes(this.db),
116
- lastInsertRowId: api.last_insert_id(this.db),
144
+ rowsAffected: api.changes(this.db),
145
+ insertId: api.last_insert_id(this.db),
117
146
  autocommit: api.get_autocommit(this.db) != 0,
118
- resultSet: rs
147
+ rawRows,
148
+ columnNames
119
149
  };
120
150
  }
121
151
 
122
152
  /**
123
153
  * This executes a single statement using SQLite3 and returns the results as a {@link RawResultSet}.
124
154
  */
125
- private async executeSingleStatementRaw(sql: string, bindings?: any[]): Promise<RawResultSet | undefined> {
155
+ private async executeSingleStatementRaw(sql: string, bindings?: any[]): Promise<RawResultSet> {
126
156
  const results = await this.executeRaw(sql, bindings);
127
- return results.length ? results[0] : undefined;
157
+ return results.length ? results[0] : { columnNames: [], rawRows: [] };
128
158
  }
129
159
 
130
160
  async executeRaw(sql: string, bindings?: any[]): Promise<RawResultSet[]> {
131
161
  const results = [];
132
162
  const api = this.requireSqlite();
133
- for await (const stmt of api.statements(this.db, sql)) {
163
+ for await (const stmt of this.cachedStatements(api, sql)) {
134
164
  let columns;
135
165
 
136
166
  const rs = await this.stepThroughStatement(api, stmt, bindings ?? [], columns);
137
- columns = rs.columns;
167
+ columns = rs.columnNames;
138
168
  if (columns.length) {
139
169
  results.push(rs);
140
170
  }
@@ -176,13 +206,61 @@ export class RawSqliteConnection {
176
206
  }
177
207
 
178
208
  knownColumns ??= api.column_names(stmt);
179
- return { columns: knownColumns, rows };
209
+ return { columnNames: knownColumns, rawRows: rows };
180
210
  }
181
211
 
182
212
  async close() {
183
213
  if (this.isOpen) {
184
- await this.requireSqlite().close(this.db);
214
+ const api = this.requireSqlite();
215
+
216
+ if (this.statementCache) {
217
+ for (const stmt of this.statementCache.drain()) {
218
+ await api.finalize(stmt);
219
+ }
220
+ }
221
+
222
+ await api.close(this.db);
185
223
  this.db = 0;
186
224
  }
187
225
  }
226
+
227
+ private async *cachedStatements(api: SQLiteAPI, sql: string): AsyncIterable<number> {
228
+ {
229
+ const existing = this.statementCache?.lookup(sql);
230
+ if (existing != null) {
231
+ yield existing;
232
+ return;
233
+ }
234
+ }
235
+
236
+ const inner = api.statements(this.db, sql, { unscoped: true });
237
+ const preparedStatements: number[] = [];
238
+
239
+ try {
240
+ for await (const stmt of inner) {
241
+ preparedStatements.push(stmt);
242
+ yield stmt;
243
+ }
244
+ } finally {
245
+ // We can only cache statements if the sql text corresponds to a single statement, otherwise it's not clear what
246
+ // portion of the original sql text to use as a key.
247
+ if (preparedStatements.length === 1 && this.statementCache) {
248
+ const stmt = preparedStatements[0];
249
+ // Don't cache EXPLAIN statements, their result becomes invalid after schema changes.
250
+ if (this.sqlite3_stmt_isexplain(stmt) == 0) {
251
+ const evicted = this.statementCache.addStatement(sql, stmt);
252
+ if (evicted != null) {
253
+ await api.finalize(evicted);
254
+ }
255
+
256
+ return;
257
+ }
258
+ }
259
+
260
+ // We're not caching statements, so finalize them.
261
+ for (const stmt of preparedStatements) {
262
+ await api.finalize(stmt);
263
+ }
264
+ }
265
+ }
188
266
  }
@@ -0,0 +1,50 @@
1
+ export class PreparedStatementCache {
2
+ readonly #size: number;
3
+ // Note that Map preserves insertion order, which allows using it as an LRU
4
+ // cache (with the first element being the first element to evict).
5
+ readonly #statements = new Map<string, number>();
6
+
7
+ constructor(size: number) {
8
+ this.#size = size;
9
+ }
10
+
11
+ /**
12
+ * Attempts to look up the cached sql statement, if it's currently cached.
13
+ */
14
+ lookup(sql: string): number | null {
15
+ const foundStatement = this.#statements.get(sql);
16
+ if (foundStatement != null) {
17
+ // Delete and re-insert to move to the end (most-recently-used position).
18
+ this.#statements.delete(sql);
19
+ this.#statements.set(sql, foundStatement);
20
+ return foundStatement;
21
+ }
22
+
23
+ return null;
24
+ }
25
+
26
+ /**
27
+ * Adds a new statement into the cache.
28
+ *
29
+ * If that exceeds the target size of the statement cache, returns an old statement to evict.
30
+ * The caller is responsible for freeing that statement.
31
+ */
32
+ addStatement(sql: string, statement: number): number | null {
33
+ this.#statements.set(sql, statement);
34
+
35
+ if (this.#statements.size > this.#size) {
36
+ for (const [k, v] of this.#statements.entries()) {
37
+ this.#statements.delete(k);
38
+ return v;
39
+ }
40
+ }
41
+
42
+ return null;
43
+ }
44
+
45
+ drain(): number[] {
46
+ const values = [...this.#statements.values()];
47
+ this.#statements.clear();
48
+ return values;
49
+ }
50
+ }
@@ -1,70 +1,38 @@
1
- import { createLogger, DBAdapter, ILogger, SQLOpenFactory, type ILogLevel } from '@powersync/common';
1
+ import { DBAdapter, LogLevels, PowerSyncLogger, SQLOpenFactory } from '@powersync/common';
2
2
  import * as Comlink from 'comlink';
3
- import { openWorkerDatabasePort, resolveWorkerDatabasePortFactory } from '../../../worker/db/open-worker-database.js';
4
- import {
5
- DEFAULT_CACHE_SIZE_KB,
6
- isServerSide,
7
- ResolvedWebSQLFlags,
8
- ResolvedWebSQLOpenOptions,
9
- resolveWebSQLFlags,
10
- TemporaryStorageOption,
11
- WebSQLOpenFactoryOptions
12
- } from '../web-sql-flags.js';
3
+ import { ResolvedWebSQLOpenOptions, WebSQLOpenOptions } from '../options.js';
13
4
  import { SSRDBAdapter } from '../SSRDBAdapter.js';
14
5
  import { vfsRequiresDedicatedWorkers, WASQLiteVFS } from './vfs.js';
15
6
  import { MultiDatabaseServer } from '../../../worker/db/MultiDatabaseServer.js';
16
7
  import { DatabaseClient, OpenWorkerConnection } from './DatabaseClient.js';
17
8
  import { generateTabCloseSignal } from '../../../shared/tab_close_signal.js';
18
9
  import { AsyncDbAdapter, PoolConnection } from '../AsyncWebAdapter.js';
10
+ import { RawWaSqliteDatabaseOptions } from './RawSqliteConnection.js';
11
+ import { maxPathNameLength, resolveAndValidateOptions } from '../resolveAndValidateOptions.js';
12
+ import { connectToExistingWorker, connectToWorker, WorkerConnection } from '../../../worker/client.js';
19
13
 
20
- export interface WASQLiteOpenFactoryOptions extends WebSQLOpenFactoryOptions {
21
- vfs?: WASQLiteVFS;
22
- /**
23
- * If the {@link vfs} supports it, an additional amount of read-only connections to open. Using additional read
24
- * connections can speed up queries by dispatching them to multiple workers running them concurrently.
25
- *
26
- * {@link WASQLiteVFS.OPFSWriteAheadVFS} is the only VFS with support for multiple connections, so this option is
27
- * ignored for other VFS implementations.
28
- *
29
- * Defaults to 1.
30
- */
31
- additionalReaders?: number;
32
- }
33
-
34
- export interface ResolvedWASQLiteOpenFactoryOptions extends ResolvedWebSQLOpenOptions {
35
- vfs: WASQLiteVFS;
36
-
37
- /**
38
- * Whether this is a read-only connection opened for the `OPFSWriteAheadVFS` file system.
39
- */
40
- isReadOnly: boolean;
41
- }
42
-
43
- export interface WorkerDBOpenerOptions extends ResolvedWASQLiteOpenFactoryOptions {
44
- logLevel: ILogLevel;
45
- /**
46
- * A lock that is currently held by the client. When the lock is returned, we know the client is gone and that we need
47
- * to clean up resources.
48
- */
49
- lockName: string;
14
+ export interface WASQLiteOpenFactoryOptions {
15
+ open: WebSQLOpenOptions;
16
+ logger: PowerSyncLogger;
50
17
  }
51
18
 
52
19
  /**
53
20
  * Opens a SQLite connection using WA-SQLite.
54
21
  */
55
22
  export class WASQLiteOpenFactory implements SQLOpenFactory {
56
- private resolvedFlags: ResolvedWebSQLFlags;
57
- private logger: ILogger;
23
+ private options: ResolvedWebSQLOpenOptions;
24
+ private logger: PowerSyncLogger;
58
25
 
59
- constructor(private options: WASQLiteOpenFactoryOptions) {
60
- assertValidWASQLiteOpenFactoryOptions(options);
61
- this.resolvedFlags = resolveWebSQLFlags(options.flags);
62
- this.logger = options.logger ?? createLogger(`WASQLiteOpenFactory - ${this.options.dbFilename}`);
63
- }
26
+ constructor(options: WASQLiteOpenFactoryOptions) {
27
+ this.options = resolveAndValidateOptions(options.open);
28
+
29
+ // Account for the fact that SQLite might append -journal suffixes
30
+ const maxLength = maxPathNameLength - 16;
31
+ if (this.options.dbFilename.length > maxLength) {
32
+ throw new Error(`dbFilename too long (max length is ${maxLength})`);
33
+ }
64
34
 
65
- get waOptions(): WASQLiteOpenFactoryOptions {
66
- // Cast to extended type
67
- return this.options;
35
+ this.logger = options.logger;
68
36
  }
69
37
 
70
38
  protected openAdapter(): DBAdapter {
@@ -72,84 +40,91 @@ export class WASQLiteOpenFactory implements SQLOpenFactory {
72
40
  }
73
41
 
74
42
  openDB(): DBAdapter {
75
- const {
76
- resolvedFlags: { disableSSRWarning, enableMultiTabs, ssrMode = isServerSide() }
77
- } = this;
43
+ const { disableSSRWarning, enableMultiTabs, ssrMode } = this.options;
44
+
78
45
  if (ssrMode) {
79
46
  if (!disableSSRWarning) {
80
- this.logger.warn(
81
- `
47
+ this.logger.log({
48
+ level: LogLevels.warn,
49
+ message: `
82
50
  Running PowerSync in SSR mode.
83
51
  Only empty query results will be returned.
84
52
  Disable this warning by setting 'disableSSRWarning: true' in options.`
85
- );
53
+ });
86
54
  }
87
55
 
88
56
  return new SSRDBAdapter();
89
57
  }
90
58
 
91
59
  if (!enableMultiTabs) {
92
- this.logger.warn(
93
- 'Multiple tab support is not enabled. Using this site across multiple tabs may not function correctly.'
94
- );
60
+ this.logger.log({
61
+ level: LogLevels.warn,
62
+ message: 'Multiple tab support is not enabled. Using this site across multiple tabs may not function correctly.'
63
+ });
95
64
  }
96
65
 
97
66
  return this.openAdapter();
98
67
  }
99
68
 
100
69
  async openConnection(): Promise<PoolConnection> {
101
- const { enableMultiTabs, useWebWorker } = this.resolvedFlags;
102
70
  const {
103
- vfs = WASQLiteVFS.IDBBatchAtomicVFS,
104
- temporaryStorage = TemporaryStorageOption.MEMORY,
105
- cacheSizeKb = DEFAULT_CACHE_SIZE_KB,
106
- encryptionKey
107
- } = this.waOptions;
108
-
109
- if (!enableMultiTabs) {
110
- this.logger.warn('Multiple tabs are not enabled in this browser');
111
- }
112
-
113
- const resolveOptions = (isReadOnly: boolean): ResolvedWASQLiteOpenFactoryOptions => ({
114
- dbFilename: this.options.dbFilename,
115
- dbLocation: this.options.dbLocation,
116
- debugMode: this.options.debugMode,
71
+ enableMultiTabs,
72
+ useWebWorker,
117
73
  vfs,
74
+ dbFilename,
75
+ encryptionKey,
118
76
  temporaryStorage,
119
77
  cacheSizeKb,
120
- flags: this.resolvedFlags,
121
- encryptionKey: encryptionKey,
122
- isReadOnly
123
- });
78
+ preparedStatementsCache
79
+ } = this.options;
80
+
81
+ if (!enableMultiTabs) {
82
+ this.logger.log({ level: LogLevels.warn, message: 'Multiple tabs are not enabled in this browser' });
83
+ }
124
84
 
125
85
  let client: DatabaseClient;
126
86
  let additionalReaders: DatabaseClient[] = [];
127
87
  let requiresPersistentTriggers = vfsRequiresDedicatedWorkers(vfs);
128
88
 
89
+ function resolveRawWaSqliteDatabaseOptions(readonly: boolean): RawWaSqliteDatabaseOptions {
90
+ return {
91
+ filename: dbFilename,
92
+ readonly,
93
+ vfs,
94
+ encryptionKey,
95
+ temporaryStorage,
96
+ cacheSizeKb,
97
+ // TODO: Enable prepared statement cache by default?
98
+ preparedStatementsCache: preparedStatementsCache ?? 0
99
+ };
100
+ }
101
+
129
102
  if (useWebWorker) {
130
103
  const optionsDbWorker = this.options.worker;
131
104
 
132
- const openDatabaseWorker = async (
133
- resolvedOptions: ResolvedWASQLiteOpenFactoryOptions
134
- ): Promise<DatabaseClient> => {
135
- const workerPort =
136
- typeof optionsDbWorker == 'function'
137
- ? resolveWorkerDatabasePortFactory(() =>
138
- optionsDbWorker({
139
- ...this.options,
140
- temporaryStorage,
141
- cacheSizeKb,
142
- flags: this.resolvedFlags,
143
- encryptionKey
144
- })
145
- )
146
- : openWorkerDatabasePort(this.options.dbFilename, enableMultiTabs, optionsDbWorker, this.waOptions.vfs);
147
-
148
- const source = Comlink.wrap<OpenWorkerConnection>(workerPort);
105
+ const openDatabaseWorker = async (readonly: boolean): Promise<DatabaseClient> => {
106
+ let workerConnection: WorkerConnection;
107
+ if (typeof optionsDbWorker == 'function') {
108
+ const worker = optionsDbWorker(this.options);
109
+ workerConnection = connectToExistingWorker(worker, this.logger, 'database');
110
+ } else {
111
+ const needsDedicated = vfsRequiresDedicatedWorkers(vfs);
112
+ const useShared = !needsDedicated && enableMultiTabs;
113
+
114
+ workerConnection = connectToWorker({
115
+ service: 'database',
116
+ databaseIdentifier: this.options.dbFilename,
117
+ shared: useShared,
118
+ customWorker: optionsDbWorker,
119
+ loggerForErrors: this.logger
120
+ });
121
+ }
122
+
123
+ const source = Comlink.wrap<OpenWorkerConnection>(workerConnection.endpoint);
149
124
  const closeSignal = new AbortController();
150
125
  const connection = await source.connect({
151
- ...resolvedOptions,
152
- logLevel: this.logger.getLevel(),
126
+ database: resolveRawWaSqliteDatabaseOptions(readonly),
127
+ logLevel: this.options.databaseWorkerLogLevel,
153
128
  lockName: await generateTabCloseSignal(closeSignal.signal)
154
129
  });
155
130
  const clientOptions = {
@@ -159,42 +134,39 @@ export class WASQLiteOpenFactory implements SQLOpenFactory {
159
134
  remoteCanCloseUnexpectedly: false,
160
135
  onClose: () => {
161
136
  closeSignal.abort();
162
- if (workerPort instanceof Worker) {
163
- workerPort.terminate();
164
- } else {
165
- workerPort.close();
166
- }
137
+ workerConnection.close();
167
138
  }
168
139
  };
169
140
 
170
141
  return new DatabaseClient(clientOptions, {
171
- ...resolvedOptions,
142
+ ...this.options,
172
143
  requiresPersistentTriggers
173
144
  });
174
145
  };
175
146
 
176
- client = await openDatabaseWorker(resolveOptions(false));
147
+ client = await openDatabaseWorker(false);
177
148
 
178
149
  if (vfs == WASQLiteVFS.OPFSWriteAheadVFS) {
179
150
  // This VFS supports concurrent reads, so we can open additional workers to host read-only connections for
180
151
  // concurrent reads / writes.
181
152
  const additionalReadersCount = this.options.additionalReaders ?? 1;
153
+
154
+ const additionalReaderPromises: Promise<DatabaseClient>[] = [];
182
155
  for (let i = 0; i < additionalReadersCount; i++) {
183
- const reader = await openDatabaseWorker(resolveOptions(true));
184
- additionalReaders.push(reader);
156
+ additionalReaderPromises.push(openDatabaseWorker(true));
185
157
  }
158
+ additionalReaders.push(...(await Promise.all(additionalReaderPromises)));
186
159
  }
187
160
  } else {
188
161
  // Don't use a web worker. Instead, open the MultiDatabaseServer a worker would use locally.
189
162
  const localServer = new MultiDatabaseServer(this.logger);
190
163
  requiresPersistentTriggers = true;
191
164
 
192
- const resolvedOptions = resolveOptions(false);
193
- const connection = await localServer.openConnectionLocally(resolvedOptions);
165
+ const connection = await localServer.openConnectionLocally(this.logger, resolveRawWaSqliteDatabaseOptions(false));
194
166
  client = new DatabaseClient(
195
167
  { connection, source: null, remoteCanCloseUnexpectedly: false },
196
168
  {
197
- ...resolvedOptions,
169
+ ...this.options,
198
170
  requiresPersistentTriggers
199
171
  }
200
172
  );
@@ -206,18 +178,3 @@ export class WASQLiteOpenFactory implements SQLOpenFactory {
206
178
  };
207
179
  }
208
180
  }
209
-
210
- /**
211
- * Asserts that the factory options are valid.
212
- */
213
- function assertValidWASQLiteOpenFactoryOptions(options: WASQLiteOpenFactoryOptions): void {
214
- // The OPFS VFS only works in dedicated web workers.
215
- if ('vfs' in options && 'flags' in options) {
216
- const { vfs, flags = {} } = options;
217
- if (vfs && vfsRequiresDedicatedWorkers(vfs) && 'useWebWorker' in flags && !flags.useWebWorker) {
218
- throw new Error(
219
- `Invalid configuration: The 'useWebWorker' flag must be true when using an OPFS-based VFS (${vfs}).`
220
- );
221
- }
222
- }
223
- }