@powersync/web 1.39.0 → 2.1.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 (243) hide show
  1. package/README.md +0 -10
  2. package/bin/powersync.cjs +1 -1
  3. package/dist/index.react_native_web.js +1992 -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-BzodSqNq.js +2 -0
  16. package/dist/worker/OPFSWriteAheadVFS-BzodSqNq.js.map +1 -0
  17. package/dist/worker/assets/mc-wa-sqlite-DoDpgFfE.wasm +0 -0
  18. package/dist/worker/assets/mc-wa-sqlite-async-DYagSq56.wasm +0 -0
  19. package/dist/worker/assets/wa-sqlite-CagagB9I.wasm +0 -0
  20. package/dist/worker/assets/wa-sqlite-async-DCIP8kAx.wasm +0 -0
  21. package/dist/worker/mc-wa-sqlite-DDFgWP93.js +2 -0
  22. package/dist/worker/mc-wa-sqlite-DDFgWP93.js.map +1 -0
  23. package/dist/worker/mc-wa-sqlite-async-lGclTjKJ.js +2 -0
  24. package/dist/worker/mc-wa-sqlite-async-lGclTjKJ.js.map +1 -0
  25. package/dist/worker/wa-sqlite-B0tZMM0j.js +2 -0
  26. package/dist/worker/wa-sqlite-B0tZMM0j.js.map +1 -0
  27. package/dist/worker/wa-sqlite-async-CM6BmfRh.js +2 -0
  28. package/dist/worker/wa-sqlite-async-CM6BmfRh.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 +67 -0
  37. package/lib/{src/db → db}/PowerSyncDatabase.js +49 -63
  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 +15 -15
  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/options.d.ts +87 -0
  48. package/lib/db/adapters/options.js +6 -0
  49. package/lib/db/adapters/options.js.map +1 -0
  50. package/lib/db/adapters/resolveAndValidateOptions.d.ts +13 -0
  51. package/lib/db/adapters/resolveAndValidateOptions.js +41 -0
  52. package/lib/db/adapters/resolveAndValidateOptions.js.map +1 -0
  53. package/lib/{src/db → db}/adapters/wa-sqlite/ConcurrentConnection.d.ts +3 -4
  54. package/lib/{src/db → db}/adapters/wa-sqlite/ConcurrentConnection.js +2 -2
  55. package/lib/db/adapters/wa-sqlite/ConcurrentConnection.js.map +1 -0
  56. package/lib/{src/db → db}/adapters/wa-sqlite/DatabaseClient.d.ts +4 -4
  57. package/lib/{src/db → db}/adapters/wa-sqlite/DatabaseClient.js +11 -37
  58. package/lib/db/adapters/wa-sqlite/DatabaseClient.js.map +1 -0
  59. package/lib/{src/db → db}/adapters/wa-sqlite/DatabaseServer.d.ts +5 -5
  60. package/lib/{src/db → db}/adapters/wa-sqlite/DatabaseServer.js +14 -7
  61. package/lib/db/adapters/wa-sqlite/DatabaseServer.js.map +1 -0
  62. package/lib/{src/db → db}/adapters/wa-sqlite/RawSqliteConnection.d.ts +22 -12
  63. package/lib/{src/db → db}/adapters/wa-sqlite/RawSqliteConnection.js +12 -9
  64. package/lib/db/adapters/wa-sqlite/RawSqliteConnection.js.map +1 -0
  65. package/lib/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +18 -0
  66. package/lib/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +137 -0
  67. package/lib/db/adapters/wa-sqlite/WASQLiteOpenFactory.js.map +1 -0
  68. package/lib/{src/db → db}/adapters/wa-sqlite/vfs.d.ts +9 -2
  69. package/lib/{src/db → db}/adapters/wa-sqlite/vfs.js +6 -6
  70. package/lib/db/adapters/wa-sqlite/vfs.js.map +1 -0
  71. package/lib/{src/db → db}/sync/SSRWebStreamingSyncImplementation.d.ts +4 -8
  72. package/lib/{src/db → db}/sync/SSRWebStreamingSyncImplementation.js +4 -11
  73. package/lib/db/sync/SSRWebStreamingSyncImplementation.js.map +1 -0
  74. package/lib/{src/db → db}/sync/SharedWebStreamingSyncImplementation.d.ts +13 -14
  75. package/lib/{src/db → db}/sync/SharedWebStreamingSyncImplementation.js +32 -66
  76. package/lib/db/sync/SharedWebStreamingSyncImplementation.js.map +1 -0
  77. package/lib/db/sync/TabLocalStreamingSyncImplementation.d.ts +19 -0
  78. package/lib/db/sync/TabLocalStreamingSyncImplementation.js +70 -0
  79. package/lib/db/sync/TabLocalStreamingSyncImplementation.js.map +1 -0
  80. package/lib/db/sync/WebRemote.d.ts +10 -0
  81. package/lib/db/sync/WebRemote.js +33 -0
  82. package/lib/db/sync/WebRemote.js.map +1 -0
  83. package/lib/{src/db → db}/sync/WebStreamingSyncImplementation.d.ts +2 -4
  84. package/lib/{src/db → db}/sync/WebStreamingSyncImplementation.js +3 -2
  85. package/lib/db/sync/WebStreamingSyncImplementation.js.map +1 -0
  86. package/lib/db/sync/userAgent.js.map +1 -0
  87. package/lib/{src/index.d.ts → index.d.ts} +1 -3
  88. package/lib/{src/index.js → index.js} +1 -3
  89. package/lib/index.js.map +1 -0
  90. package/lib/shared/navigator.js.map +1 -0
  91. package/lib/shared/tab_close_signal.js.map +1 -0
  92. package/lib/worker/SharedWorkerConnectionRequest.d.ts +5 -0
  93. package/lib/worker/SharedWorkerConnectionRequest.js +2 -0
  94. package/lib/worker/SharedWorkerConnectionRequest.js.map +1 -0
  95. package/lib/worker/client.d.ts +17 -0
  96. package/lib/worker/client.js +90 -0
  97. package/lib/worker/client.js.map +1 -0
  98. package/lib/worker/db/MultiDatabaseServer.d.ts +22 -0
  99. package/lib/{src/worker → worker}/db/MultiDatabaseServer.js +25 -15
  100. package/lib/worker/db/MultiDatabaseServer.js.map +1 -0
  101. package/lib/worker/sync/AbstractSharedSyncClientProvider.d.ts +13 -0
  102. package/lib/worker/sync/AbstractSharedSyncClientProvider.js.map +1 -0
  103. package/lib/worker/sync/BroadcastLogger.d.ts +27 -0
  104. package/lib/worker/sync/BroadcastLogger.js +65 -0
  105. package/lib/worker/sync/BroadcastLogger.js.map +1 -0
  106. package/lib/{src/worker → worker}/sync/SharedSyncImplementation.d.ts +12 -15
  107. package/lib/{src/worker → worker}/sync/SharedSyncImplementation.js +44 -44
  108. package/lib/worker/sync/SharedSyncImplementation.js.map +1 -0
  109. package/lib/{src/worker → worker}/sync/WorkerClient.d.ts +3 -3
  110. package/lib/{src/worker → worker}/sync/WorkerClient.js +2 -2
  111. package/lib/worker/sync/WorkerClient.js.map +1 -0
  112. package/lib/worker/worker.js +34 -0
  113. package/lib/worker/worker.js.map +1 -0
  114. package/package.json +23 -31
  115. package/src/db/NavigatorTriggerClaimManager.ts +1 -1
  116. package/src/db/PowerSyncDatabase.ts +83 -127
  117. package/src/db/adapters/AsyncWebAdapter.ts +18 -27
  118. package/src/db/adapters/SSRDBAdapter.ts +14 -64
  119. package/src/db/adapters/WebDBAdapter.ts +1 -1
  120. package/src/db/adapters/options.ts +100 -0
  121. package/src/db/adapters/resolveAndValidateOptions.ts +49 -0
  122. package/src/db/adapters/wa-sqlite/ConcurrentConnection.ts +4 -5
  123. package/src/db/adapters/wa-sqlite/DatabaseClient.ts +20 -56
  124. package/src/db/adapters/wa-sqlite/DatabaseServer.ts +18 -12
  125. package/src/db/adapters/wa-sqlite/RawSqliteConnection.ts +36 -23
  126. package/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.ts +70 -125
  127. package/src/db/adapters/wa-sqlite/vfs.ts +13 -8
  128. package/src/db/sync/SSRWebStreamingSyncImplementation.ts +4 -22
  129. package/src/db/sync/SharedWebStreamingSyncImplementation.ts +39 -77
  130. package/src/db/sync/TabLocalStreamingSyncImplementation.ts +90 -0
  131. package/src/db/sync/WebRemote.ts +23 -26
  132. package/src/db/sync/WebStreamingSyncImplementation.ts +4 -5
  133. package/src/index.ts +1 -3
  134. package/src/worker/SharedWorkerConnectionRequest.ts +6 -0
  135. package/src/worker/client.ts +121 -0
  136. package/src/worker/db/MultiDatabaseServer.ts +40 -22
  137. package/src/worker/sync/AbstractSharedSyncClientProvider.ts +4 -10
  138. package/src/worker/sync/BroadcastLogger.ts +35 -103
  139. package/src/worker/sync/SharedSyncImplementation.ts +65 -64
  140. package/src/worker/sync/WorkerClient.ts +4 -4
  141. package/src/worker/worker.ts +38 -0
  142. package/dist/2075a31bb151adbb9767.wasm +0 -0
  143. package/dist/3322bc84de986b63c2cd.wasm +0 -0
  144. package/dist/8e97452e297be23b5e50.wasm +0 -0
  145. package/dist/fbc178b70d530e8ce02b.wasm +0 -0
  146. package/dist/index.umd.js +0 -7821
  147. package/dist/index.umd.js.map +0 -1
  148. package/dist/worker/SharedSyncImplementation.umd.js +0 -16142
  149. package/dist/worker/SharedSyncImplementation.umd.js.map +0 -1
  150. package/dist/worker/WASQLiteDB.umd.js +0 -17437
  151. package/dist/worker/WASQLiteDB.umd.js.map +0 -1
  152. 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
  153. 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
  154. 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
  155. 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
  156. 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
  157. 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
  158. 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
  159. 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
  160. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-2fb422.umd.js +0 -3562
  161. 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
  162. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-833585.umd.js +0 -1400
  163. 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
  164. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-96fb23.umd.js +0 -2478
  165. 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
  166. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-c89911.umd.js +0 -1681
  167. 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
  168. package/dist/worker/node_modules_pnpm_journeyapps_wa-sqlite_1_7_0_node_modules_journeyapps_wa-sqlite_src_examples-ec4eb1.umd.js +0 -1820
  169. 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
  170. package/lib/package.json +0 -91
  171. package/lib/src/attachments/IndexDBFileSystemAdapter.js.map +0 -1
  172. package/lib/src/db/NavigatorTriggerClaimManager.js.map +0 -1
  173. package/lib/src/db/PowerSyncDatabase.d.ts +0 -78
  174. package/lib/src/db/PowerSyncDatabase.js.map +0 -1
  175. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.d.ts +0 -23
  176. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js +0 -27
  177. package/lib/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js.map +0 -1
  178. package/lib/src/db/adapters/AsyncWebAdapter.d.ts +0 -50
  179. package/lib/src/db/adapters/AsyncWebAdapter.js.map +0 -1
  180. package/lib/src/db/adapters/SSRDBAdapter.d.ts +0 -30
  181. package/lib/src/db/adapters/SSRDBAdapter.js +0 -69
  182. package/lib/src/db/adapters/SSRDBAdapter.js.map +0 -1
  183. package/lib/src/db/adapters/WebDBAdapter.js.map +0 -1
  184. package/lib/src/db/adapters/wa-sqlite/ConcurrentConnection.js.map +0 -1
  185. package/lib/src/db/adapters/wa-sqlite/DatabaseClient.js.map +0 -1
  186. package/lib/src/db/adapters/wa-sqlite/DatabaseServer.js.map +0 -1
  187. package/lib/src/db/adapters/wa-sqlite/RawSqliteConnection.js.map +0 -1
  188. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.d.ts +0 -45
  189. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js +0 -146
  190. package/lib/src/db/adapters/wa-sqlite/WASQLiteOpenFactory.js.map +0 -1
  191. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.d.ts +0 -15
  192. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js +0 -22
  193. package/lib/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js.map +0 -1
  194. package/lib/src/db/adapters/wa-sqlite/vfs.js.map +0 -1
  195. package/lib/src/db/adapters/web-sql-flags.d.ts +0 -92
  196. package/lib/src/db/adapters/web-sql-flags.js +0 -37
  197. package/lib/src/db/adapters/web-sql-flags.js.map +0 -1
  198. package/lib/src/db/sync/SSRWebStreamingSyncImplementation.js.map +0 -1
  199. package/lib/src/db/sync/SharedWebStreamingSyncImplementation.js.map +0 -1
  200. package/lib/src/db/sync/WebRemote.d.ts +0 -7
  201. package/lib/src/db/sync/WebRemote.js +0 -33
  202. package/lib/src/db/sync/WebRemote.js.map +0 -1
  203. package/lib/src/db/sync/WebStreamingSyncImplementation.js.map +0 -1
  204. package/lib/src/db/sync/userAgent.js.map +0 -1
  205. package/lib/src/index.js.map +0 -1
  206. package/lib/src/shared/navigator.js.map +0 -1
  207. package/lib/src/shared/tab_close_signal.js.map +0 -1
  208. package/lib/src/worker/db/MultiDatabaseServer.d.ts +0 -17
  209. package/lib/src/worker/db/MultiDatabaseServer.js.map +0 -1
  210. package/lib/src/worker/db/WASQLiteDB.worker.d.ts +0 -4
  211. package/lib/src/worker/db/WASQLiteDB.worker.js +0 -31
  212. package/lib/src/worker/db/WASQLiteDB.worker.js.map +0 -1
  213. package/lib/src/worker/db/open-worker-database.d.ts +0 -14
  214. package/lib/src/worker/db/open-worker-database.js +0 -53
  215. package/lib/src/worker/db/open-worker-database.js.map +0 -1
  216. package/lib/src/worker/sync/AbstractSharedSyncClientProvider.d.ts +0 -19
  217. package/lib/src/worker/sync/AbstractSharedSyncClientProvider.js.map +0 -1
  218. package/lib/src/worker/sync/BroadcastLogger.d.ts +0 -47
  219. package/lib/src/worker/sync/BroadcastLogger.js +0 -129
  220. package/lib/src/worker/sync/BroadcastLogger.js.map +0 -1
  221. package/lib/src/worker/sync/SharedSyncImplementation.js.map +0 -1
  222. package/lib/src/worker/sync/SharedSyncImplementation.worker.js +0 -12
  223. package/lib/src/worker/sync/SharedSyncImplementation.worker.js.map +0 -1
  224. package/lib/src/worker/sync/WorkerClient.js.map +0 -1
  225. package/lib/tsconfig.tsbuildinfo +0 -1
  226. package/src/db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.ts +0 -47
  227. package/src/db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.ts +0 -24
  228. package/src/db/adapters/web-sql-flags.ts +0 -141
  229. package/src/worker/db/WASQLiteDB.worker.ts +0 -35
  230. package/src/worker/db/open-worker-database.ts +0 -62
  231. package/src/worker/sync/SharedSyncImplementation.worker.ts +0 -14
  232. /package/lib/{src/attachments → attachments}/IndexDBFileSystemAdapter.d.ts +0 -0
  233. /package/lib/{src/attachments → attachments}/IndexDBFileSystemAdapter.js +0 -0
  234. /package/lib/{src/db → db}/NavigatorTriggerClaimManager.js +0 -0
  235. /package/lib/{src/db → db}/adapters/WebDBAdapter.js +0 -0
  236. /package/lib/{src/db → db}/sync/userAgent.d.ts +0 -0
  237. /package/lib/{src/db → db}/sync/userAgent.js +0 -0
  238. /package/lib/{src/shared → shared}/navigator.d.ts +0 -0
  239. /package/lib/{src/shared → shared}/navigator.js +0 -0
  240. /package/lib/{src/shared → shared}/tab_close_signal.d.ts +0 -0
  241. /package/lib/{src/shared → shared}/tab_close_signal.js +0 -0
  242. /package/lib/{src/worker → worker}/sync/AbstractSharedSyncClientProvider.js +0 -0
  243. /package/lib/{src/worker/sync/SharedSyncImplementation.worker.d.ts → worker/worker.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  import type * as SQLite from '@journeyapps/wa-sqlite';
2
- import { ResolvedWASQLiteOpenFactoryOptions } from './WASQLiteOpenFactory.js';
2
+ import { RawWaSqliteDatabaseOptions } from './RawSqliteConnection.js';
3
3
 
4
4
  /**
5
5
  * List of currently tested virtual filesystems
@@ -32,6 +32,11 @@ export function vfsRequiresDedicatedWorkers(vfs: WASQLiteVFS) {
32
32
  return vfs != WASQLiteVFS.IDBBatchAtomicVFS && vfs != WASQLiteVFS.InMemoryVfs;
33
33
  }
34
34
 
35
+ /**
36
+ * @internal
37
+ */
38
+ export type WASQLiteModuleFactoryOptions = { dbFileName: string; encryptionKey?: string };
39
+
35
40
  /**
36
41
  * @internal
37
42
  */
@@ -62,9 +67,9 @@ async function syncModuleFactory(encryptionKey: string | undefined): Promise<SQL
62
67
  */
63
68
  export async function loadModuleAndVfs({
64
69
  vfs,
65
- dbFilename,
70
+ filename,
66
71
  encryptionKey
67
- }: ResolvedWASQLiteOpenFactoryOptions): Promise<{ module: SQLiteModule; vfs: SQLiteVFS }> {
72
+ }: RawWaSqliteDatabaseOptions): Promise<{ module: SQLiteModule; vfs: SQLiteVFS }> {
68
73
  let moduleFactory = syncModuleFactory;
69
74
  let resolveVfs: (module: any) => Promise<SQLiteVFS>;
70
75
 
@@ -74,32 +79,32 @@ export async function loadModuleAndVfs({
74
79
  const { IDBBatchAtomicVFS } = await import('@journeyapps/wa-sqlite/src/examples/IDBBatchAtomicVFS.js');
75
80
  resolveVfs = (module) => {
76
81
  // @ts-expect-error The types for this static method are missing upstream
77
- return IDBBatchAtomicVFS.create(dbFilename, module, { lockPolicy: 'exclusive' });
82
+ return IDBBatchAtomicVFS.create(filename, module, { lockPolicy: 'exclusive' });
78
83
  };
79
84
  break;
80
85
  }
81
86
  case WASQLiteVFS.AccessHandlePoolVFS: {
82
87
  // @ts-expect-error The types for this import are missing upstream
83
88
  const { AccessHandlePoolVFS } = await import('@journeyapps/wa-sqlite/src/examples/AccessHandlePoolVFS.js');
84
- resolveVfs = (module) => AccessHandlePoolVFS.create(dbFilename, module);
89
+ resolveVfs = (module) => AccessHandlePoolVFS.create(filename, module);
85
90
  break;
86
91
  }
87
92
  case WASQLiteVFS.OPFSCoopSyncVFS: {
88
93
  // @ts-expect-error The types for this import are missing upstream
89
94
  const { OPFSCoopSyncVFS } = await import('@journeyapps/wa-sqlite/src/examples/OPFSCoopSyncVFS.js');
90
- resolveVfs = (module) => OPFSCoopSyncVFS.create(dbFilename, module);
95
+ resolveVfs = (module) => OPFSCoopSyncVFS.create(filename, module);
91
96
  break;
92
97
  }
93
98
  case WASQLiteVFS.OPFSWriteAheadVFS: {
94
99
  // @ts-expect-error The types for this import are missing upstream
95
100
  const { OPFSWriteAheadVFS } = await import('@journeyapps/wa-sqlite/src/examples/OPFSWriteAheadVFS.js');
96
- resolveVfs = (module) => OPFSWriteAheadVFS.create(dbFilename, module, {});
101
+ resolveVfs = (module) => OPFSWriteAheadVFS.create(filename, module, {});
97
102
  break;
98
103
  }
99
104
  case WASQLiteVFS.InMemoryVfs: {
100
105
  const { MemoryVFS } = await import('@journeyapps/wa-sqlite/src/examples/MemoryVFS.js');
101
106
  // @ts-expect-error The types for this static method are missing upstream
102
- resolveVfs = (module) => MemoryVFS.create(dbFilename, module);
107
+ resolveVfs = (module) => MemoryVFS.create(filename, module);
103
108
  break;
104
109
  }
105
110
  }
@@ -1,14 +1,5 @@
1
- import {
2
- AbstractStreamingSyncImplementationOptions,
3
- BaseObserver,
4
- LockOptions,
5
- LockType,
6
- Mutex,
7
- PowerSyncConnectionOptions,
8
- StreamingSyncImplementation,
9
- SyncStatus,
10
- SyncStatusOptions
11
- } from '@powersync/common';
1
+ import { BaseObserver, SyncStatus } from '@powersync/common';
2
+ import { Mutex, StreamingSyncImplementation, LockOptions, LockType } from '@powersync/shared-internals';
12
3
 
13
4
  export class SSRStreamingSyncImplementation extends BaseObserver implements StreamingSyncImplementation {
14
5
  syncMutex: Mutex;
@@ -16,13 +7,11 @@ export class SSRStreamingSyncImplementation extends BaseObserver implements Stre
16
7
 
17
8
  isConnected: boolean;
18
9
  lastSyncedAt?: Date | undefined;
19
- syncStatus: SyncStatus;
20
10
 
21
- constructor(options: AbstractStreamingSyncImplementationOptions) {
11
+ constructor() {
22
12
  super();
23
13
  this.syncMutex = new Mutex();
24
14
  this.crudMutex = new Mutex();
25
- this.syncStatus = new SyncStatus({});
26
15
  this.isConnected = false;
27
16
  }
28
17
 
@@ -34,7 +23,7 @@ export class SSRStreamingSyncImplementation extends BaseObserver implements Stre
34
23
  /**
35
24
  * This is a no-op in SSR mode
36
25
  */
37
- async connect(options?: PowerSyncConnectionOptions): Promise<void> {}
26
+ async connect(): Promise<void> {}
38
27
 
39
28
  async dispose() {}
40
29
 
@@ -48,13 +37,6 @@ export class SSRStreamingSyncImplementation extends BaseObserver implements Stre
48
37
  */
49
38
  async waitForReady() {}
50
39
 
51
- /**
52
- * This will never resolve in SSR Mode.
53
- */
54
- async waitForStatus(status: SyncStatusOptions) {
55
- return this.waitUntilStatusMatches(() => false);
56
- }
57
-
58
40
  /**
59
41
  * This will never resolve in SSR Mode.
60
42
  */
@@ -1,21 +1,16 @@
1
- import {
2
- PowerSyncConnectionOptions,
3
- PowerSyncCredentials,
4
- SubscribedStream,
5
- SyncStatusOptions
6
- } from '@powersync/common';
1
+ import { LogRecord, PowerSyncCredentials } from '@powersync/common';
7
2
  import * as Comlink from 'comlink';
8
- import { getNavigatorLocks } from '../../shared/navigator.js';
9
3
  import { AbstractSharedSyncClientProvider } from '../../worker/sync/AbstractSharedSyncClientProvider.js';
10
4
  import { ManualSharedSyncPayload, SharedSyncClientEvent } from '../../worker/sync/SharedSyncImplementation.js';
11
5
  import { WorkerClient } from '../../worker/sync/WorkerClient.js';
12
6
  import { WebDBAdapter } from '../adapters/WebDBAdapter.js';
13
- import { DEFAULT_CACHE_SIZE_KB, TemporaryStorageOption, resolveWebSQLFlags } from '../adapters/web-sql-flags.js';
14
7
  import {
15
8
  WebStreamingSyncImplementation,
16
9
  WebStreamingSyncImplementationOptions
17
10
  } from './WebStreamingSyncImplementation.js';
18
11
  import { generateTabCloseSignal } from '../../shared/tab_close_signal.js';
12
+ import { SubscribedStream, SyncStatusJson, ResolvedSyncOptions } from '@powersync/shared-internals';
13
+ import { connectToExistingWorker, connectToWorker, WorkerConnection } from '../../worker/client.js';
19
14
 
20
15
  /**
21
16
  * The shared worker will trigger methods on this side of the message port
@@ -24,7 +19,7 @@ import { generateTabCloseSignal } from '../../shared/tab_close_signal.js';
24
19
  class SharedSyncClientProvider extends AbstractSharedSyncClientProvider {
25
20
  constructor(
26
21
  protected options: WebStreamingSyncImplementationOptions,
27
- public statusChanged: (status: SyncStatusOptions) => void,
22
+ public statusChanged: (status: SyncStatusJson) => void,
28
23
  protected webDB: WebDBAdapter
29
24
  ) {
30
25
  super();
@@ -68,34 +63,15 @@ class SharedSyncClientProvider extends AbstractSharedSyncClientProvider {
68
63
  return this.options.logger;
69
64
  }
70
65
 
71
- trace(...x: any[]): void {
72
- this.logger?.trace(...x);
73
- }
74
- debug(...x: any[]): void {
75
- this.logger?.debug(...x);
76
- }
77
- info(...x: any[]): void {
78
- this.logger?.info(...x);
79
- }
80
- log(...x: any[]): void {
81
- this.logger?.log(...x);
82
- }
83
- warn(...x: any[]): void {
84
- this.logger?.warn(...x);
85
- }
86
- error(...x: any[]): void {
87
- this.logger?.error(...x);
88
- }
89
- time(label: string): void {
90
- this.logger?.time(label);
91
- }
92
- timeEnd(label: string): void {
93
- this.logger?.timeEnd(label);
66
+ log(record: LogRecord): void {
67
+ this.logger.log(record);
94
68
  }
95
69
  }
96
70
 
97
71
  export interface SharedWebStreamingSyncImplementationOptions extends WebStreamingSyncImplementationOptions {
72
+ logLevel: number;
98
73
  db: WebDBAdapter;
74
+ enableBroadcastLogs: boolean;
99
75
  }
100
76
 
101
77
  /**
@@ -104,46 +80,31 @@ export interface SharedWebStreamingSyncImplementationOptions extends WebStreamin
104
80
  export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplementation {
105
81
  protected syncManager: Comlink.Remote<WorkerClient>;
106
82
  protected clientProvider: SharedSyncClientProvider;
107
- protected messagePort: MessagePort;
83
+ protected worker: WorkerConnection;
108
84
 
109
85
  protected isInitialized: Promise<void>;
110
86
  protected dbAdapter: WebDBAdapter;
111
87
  private abortOnClose = new AbortController();
88
+ private logLevel: number;
89
+ private enableBroadcastLogs: boolean;
112
90
 
113
91
  constructor(options: SharedWebStreamingSyncImplementationOptions) {
114
92
  super(options);
115
93
  this.dbAdapter = options.db;
116
- /**
117
- * Configure or connect to the shared sync worker.
118
- * This worker will manage all syncing operations remotely.
119
- */
120
- const resolvedWorkerOptions = {
121
- dbFilename: this.options.identifier!,
122
- temporaryStorage: TemporaryStorageOption.MEMORY,
123
- cacheSizeKb: DEFAULT_CACHE_SIZE_KB,
124
- ...options,
125
- flags: resolveWebSQLFlags(options.flags)
126
- };
94
+ this.logLevel = options.logLevel;
95
+ this.enableBroadcastLogs = options.enableBroadcastLogs;
127
96
 
128
97
  const syncWorker = options.sync?.worker;
129
- if (syncWorker) {
130
- if (typeof syncWorker === 'function') {
131
- this.messagePort = syncWorker(resolvedWorkerOptions).port;
132
- } else {
133
- this.messagePort = new SharedWorker(`${syncWorker}`, {
134
- /* @vite-ignore */
135
- name: `shared-sync-${this.webOptions.identifier}`
136
- }).port;
137
- }
98
+ if (typeof syncWorker === 'function') {
99
+ this.worker = connectToExistingWorker(syncWorker(), options.logger, 'sync');
138
100
  } else {
139
- this.messagePort = new SharedWorker(
140
- new URL('../../worker/sync/SharedSyncImplementation.worker.js', import.meta.url),
141
- {
142
- /* @vite-ignore */
143
- name: `shared-sync-${this.webOptions.identifier}`,
144
- type: 'module'
145
- }
146
- ).port;
101
+ this.worker = connectToWorker({
102
+ service: 'sync',
103
+ databaseIdentifier: this.webOptions.identifier!,
104
+ shared: true,
105
+ customWorker: syncWorker,
106
+ loggerForErrors: options.logger
107
+ });
147
108
  }
148
109
 
149
110
  /**
@@ -151,21 +112,21 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
151
112
  */
152
113
  this.clientProvider = new SharedSyncClientProvider(
153
114
  this.webOptions,
154
- (status) => {
155
- this.updateSyncStatus(status);
115
+ ({ core, dataFlow }) => {
116
+ this.updateSyncStatus(core, dataFlow);
156
117
  },
157
118
  options.db
158
119
  );
159
120
 
160
- this.syncManager = Comlink.wrap<WorkerClient>(this.messagePort);
121
+ this.syncManager = Comlink.wrap<WorkerClient>(this.worker.endpoint);
161
122
  /**
162
123
  * The sync worker will call this client provider when it needs
163
124
  * to fetch credentials or upload data.
164
125
  * This performs bi-directional method calling.
165
126
  */
166
- Comlink.expose(this.clientProvider, this.messagePort);
127
+ Comlink.expose(this.clientProvider, this.worker.endpoint);
167
128
 
168
- this.syncManager.setLogLevel(this.logger.getLevel());
129
+ this.syncManager.setLogLevel(this.logLevel);
169
130
 
170
131
  this.triggerCrudUpload = this.syncManager.triggerCrudUpload;
171
132
 
@@ -197,18 +158,16 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
197
158
  // Awaiting here ensures the worker is waiting for the lock
198
159
  await this.syncManager.addLockBasedCloseSignal(closeSignal);
199
160
 
200
- const { crudUploadThrottleMs, identifier, retryDelayMs } = this.options;
201
- const flags = { ...this.webOptions.flags, workers: undefined };
161
+ const { identifier } = this.options;
202
162
 
203
163
  await this.syncManager.setParams(
204
164
  {
205
165
  dbParams: this.dbAdapter.getConfiguration(),
206
166
  streamOptions: {
207
- crudUploadThrottleMs,
208
167
  identifier,
209
- retryDelayMs,
210
- flags: flags
211
- }
168
+ serializedSchema: this.options.serializedSchema
169
+ },
170
+ enableBroadcastLogs: this.enableBroadcastLogs
212
171
  },
213
172
  this.options.subscriptions
214
173
  );
@@ -218,9 +177,9 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
218
177
  * Starts the sync process, this effectively acts as a call to
219
178
  * `connect` if not yet connected.
220
179
  */
221
- async connect(options?: PowerSyncConnectionOptions): Promise<void> {
180
+ async connect(options: ResolvedSyncOptions): Promise<void> {
222
181
  await this.waitForReady();
223
- return this.syncManager.connect(options);
182
+ return this.syncManager.connect(options, this.options.serializedSchema);
224
183
  }
225
184
 
226
185
  async disconnect(): Promise<void> {
@@ -237,8 +196,11 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
237
196
  await this.waitForReady();
238
197
 
239
198
  await new Promise<void>((resolve) => {
199
+ // This will always be a message port since we use shared workers.
200
+ const messagePort = this.worker.endpoint as MessagePort;
201
+
240
202
  // Listen for the close acknowledgment from the worker
241
- this.messagePort.addEventListener('message', (event) => {
203
+ messagePort.addEventListener('message', (event) => {
242
204
  const payload = event.data as ManualSharedSyncPayload;
243
205
  if (payload?.event === SharedSyncClientEvent.CLOSE_ACK) {
244
206
  resolve();
@@ -250,7 +212,7 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
250
212
  event: SharedSyncClientEvent.CLOSE_CLIENT,
251
213
  data: {}
252
214
  };
253
- this.messagePort.postMessage(closeMessagePayload);
215
+ messagePort.postMessage(closeMessagePayload);
254
216
  });
255
217
 
256
218
  await super.dispose();
@@ -259,7 +221,7 @@ export class SharedWebStreamingSyncImplementation extends WebStreamingSyncImplem
259
221
 
260
222
  // Release the proxy
261
223
  this.syncManager[Comlink.releaseProxy]();
262
- this.messagePort.close();
224
+ this.worker.close();
263
225
  }
264
226
 
265
227
  async waitForReady() {
@@ -0,0 +1,90 @@
1
+ import {
2
+ LockOptions,
3
+ LockType,
4
+ SubscribedStream,
5
+ SyncStatusJson,
6
+ SyncStatusSnapshot
7
+ } from '@powersync/shared-internals';
8
+ import {
9
+ WebStreamingSyncImplementation,
10
+ WebStreamingSyncImplementationOptions
11
+ } from './WebStreamingSyncImplementation.js';
12
+
13
+ /**
14
+ * When multi-tab support is disabled and we don't use a shared worker for sync, only a single tab will be able to
15
+ * acquire the sync navigator lock and start a sync iteration.
16
+ *
17
+ * To be able to provide _some_ multi-tab support in that configuration, this utility:
18
+ *
19
+ * 1. Sends sync status updates from the syncing tab to others.
20
+ * 2. Allows other tabs to send notifications when their active sync stream subscriptions update, allowing the active
21
+ * tab to take those subscriptions into account.
22
+ */
23
+ export class TabLocalStreamingSyncImplementation extends WebStreamingSyncImplementation {
24
+ #statusUpdated: BroadcastChannel;
25
+ #subscriptionsChanged: BroadcastChannel;
26
+ #hasSyncLock = false;
27
+
28
+ constructor(options: WebStreamingSyncImplementationOptions) {
29
+ super(options);
30
+
31
+ const identifier = options.identifier;
32
+ this.#statusUpdated = new BroadcastChannel(`sync-status-${identifier}`);
33
+ this.#subscriptionsChanged = new BroadcastChannel(`subscription-change-${identifier}`);
34
+
35
+ this.#statusUpdated.onmessage = (event) => {
36
+ if (event.data == 'ping') {
37
+ this.#sendStatus(this.syncStatus);
38
+ return;
39
+ }
40
+
41
+ const { core, dataFlow } = event.data as SyncStatusJson;
42
+ this.updateSyncStatus(core, dataFlow);
43
+ };
44
+
45
+ // Request other tabs to share their sync status.
46
+ this.#statusUpdated.postMessage('ping');
47
+ this.#subscriptionsChanged.onmessage = () => {
48
+ // We can't update activeStreams since we don't know when another tab referencing them is closed. However,
49
+ // clients will update an internal table listing streams after subscribing, and updateSubscriptions() will
50
+ // scan that table.
51
+ super.updateSubscriptions(this.activeStreams);
52
+ };
53
+
54
+ this.registerListener({
55
+ statusChanged: (status) => this.#sendStatus(status)
56
+ });
57
+ }
58
+
59
+ #sendStatus(status: SyncStatusSnapshot) {
60
+ // Don't share sync status if this is not the tab currently syncing.
61
+ if (this.#hasSyncLock) {
62
+ this.#statusUpdated.postMessage(status.toJSON());
63
+ }
64
+ }
65
+
66
+ override updateSubscriptions(subscriptions: SubscribedStream[]): void {
67
+ super.updateSubscriptions(subscriptions);
68
+ this.#subscriptionsChanged.postMessage('');
69
+ }
70
+
71
+ override obtainLock<T>({ callback, type, signal }: LockOptions<T>): Promise<T> {
72
+ const wrappedCallback = async (): Promise<T> => {
73
+ this.#hasSyncLock = true;
74
+
75
+ try {
76
+ return await callback();
77
+ } finally {
78
+ this.#hasSyncLock = false;
79
+ }
80
+ };
81
+
82
+ return super.obtainLock({ callback: type == LockType.SYNC ? wrappedCallback : callback, type, signal });
83
+ }
84
+
85
+ override async dispose(): Promise<void> {
86
+ this.#statusUpdated.close();
87
+ this.#subscriptionsChanged.close();
88
+ await super.dispose();
89
+ }
90
+ }
@@ -1,43 +1,40 @@
1
- import {
2
- AbstractRemote,
3
- AbstractRemoteOptions,
4
- DEFAULT_REMOTE_LOGGER,
5
- FetchImplementation,
6
- FetchImplementationProvider,
7
- ILogger,
8
- RemoteConnector
9
- } from '@powersync/common';
1
+ import { LogLevels, PowerSyncLogger } from '@powersync/common';
2
+ import { AbstractRemote, FetchOptions, RemoteConnector } from '@powersync/shared-internals';
10
3
 
11
4
  import { getUserAgentInfo } from './userAgent.js';
12
-
13
- /*
14
- * Depends on browser's implementation of global fetch.
15
- */
16
- class WebFetchProvider extends FetchImplementationProvider {
17
- getFetch(): FetchImplementation {
18
- return fetch.bind(globalThis);
19
- }
20
- }
5
+ import type { WebSocketSyncStreamPlatform, WebSocketSupport } from '@powersync/shared-internals/websockets';
21
6
 
22
7
  export class WebRemote extends AbstractRemote {
23
8
  constructor(
24
9
  protected connector: RemoteConnector,
25
- protected logger: ILogger = DEFAULT_REMOTE_LOGGER,
26
- options?: Partial<AbstractRemoteOptions>
10
+ logger: PowerSyncLogger
27
11
  ) {
28
- super(connector, logger, {
29
- ...(options ?? {}),
30
- fetchImplementation: options?.fetchImplementation ?? new WebFetchProvider()
31
- });
12
+ super(connector, logger);
13
+ }
14
+
15
+ protected fetch({ resource, request }: FetchOptions): Promise<Response> {
16
+ return fetch(resource, request);
17
+ }
18
+
19
+ protected async loadWebSocketSupport(platform: WebSocketSyncStreamPlatform): Promise<WebSocketSupport> {
20
+ if (!websockets) {
21
+ // loadWebSocketSupport being called concurrently is safe, the import resolves to the same module in that case.
22
+ const module = await import('@powersync/shared-internals/websockets');
23
+ websockets = new module.WebSocketSupport(platform);
24
+ }
25
+
26
+ return websockets;
32
27
  }
33
28
 
34
29
  getUserAgent(): string {
35
30
  let ua = [super.getUserAgent(), `powersync-web`];
36
31
  try {
37
32
  ua.push(...getUserAgentInfo());
38
- } catch (e) {
39
- this.logger.warn('Failed to get user agent info', e);
33
+ } catch (error) {
34
+ this.logger.log({ level: LogLevels.warn, message: 'Failed to get user agent info', error });
40
35
  }
41
36
  return ua.join(' ');
42
37
  }
43
38
  }
39
+
40
+ let websockets: WebSocketSupport | undefined;
@@ -1,16 +1,15 @@
1
+ import { LogLevels } from '@powersync/common';
1
2
  import {
2
3
  AbstractStreamingSyncImplementation,
3
4
  AbstractStreamingSyncImplementationOptions,
4
5
  LockOptions,
5
6
  LockType
6
- } from '@powersync/common';
7
+ } from '@powersync/shared-internals';
7
8
  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
- flags?: WebSQLFlags;
12
11
  sync?: {
13
- worker?: string | URL | ((options: ResolvedWebSQLOpenOptions) => SharedWorker);
12
+ worker?: string | URL | (() => SharedWorker);
14
13
  };
15
14
  }
16
15
 
@@ -27,7 +26,7 @@ export class WebStreamingSyncImplementation extends AbstractStreamingSyncImpleme
27
26
  async obtainLock<T>(lockOptions: LockOptions<T>): Promise<T> {
28
27
  const identifier = `streaming-sync-${lockOptions.type}-${this.webOptions.identifier}`;
29
28
  if (lockOptions.type == LockType.SYNC) {
30
- this.logger.debug('requesting lock for ', identifier);
29
+ this.logger.log({ level: LogLevels.debug, message: `requesting lock for ${identifier}` });
31
30
  }
32
31
  return getNavigatorLocks().request(identifier, { signal: lockOptions.signal }, lockOptions.callback);
33
32
  }
package/src/index.ts CHANGED
@@ -1,10 +1,8 @@
1
1
  export * from '@powersync/common';
2
2
  export * from './attachments/IndexDBFileSystemAdapter.js';
3
- export * from './db/adapters/AbstractWebPowerSyncDatabaseOpenFactory.js';
4
3
  export { WASQLiteVFS } from './db/adapters/wa-sqlite/vfs.js';
5
4
  export * from './db/adapters/wa-sqlite/WASQLiteOpenFactory.js';
6
- export * from './db/adapters/wa-sqlite/WASQLitePowerSyncDatabaseOpenFactory.js';
7
- export * from './db/adapters/web-sql-flags.js';
5
+ export * from './db/adapters/options.js';
8
6
  export * from './db/PowerSyncDatabase.js';
9
7
  export * from './db/sync/SharedWebStreamingSyncImplementation.js';
10
8
  export * from './db/sync/WebRemote.js';
@@ -0,0 +1,6 @@
1
+ export type WorkerService = 'database' | 'sync';
2
+
3
+ export interface SharedWorkerConnectionRequest {
4
+ service: WorkerService;
5
+ port: MessagePort;
6
+ }
@@ -0,0 +1,121 @@
1
+ import { LogLevels, PowerSyncLogger } from '@powersync/common';
2
+ import { SharedWorkerConnectionRequest, WorkerService } from './SharedWorkerConnectionRequest.js';
3
+
4
+ export interface OpenWorkerOptions {
5
+ service: WorkerService;
6
+ databaseIdentifier: string;
7
+ customWorker?: string | URL;
8
+ shared: boolean;
9
+ loggerForErrors: PowerSyncLogger;
10
+ }
11
+
12
+ export interface WorkerConnection {
13
+ endpoint: MessagePort | Worker;
14
+ worker: Worker | SharedWorker;
15
+ close: () => void;
16
+ }
17
+
18
+ export function connectToWorker({
19
+ service,
20
+ databaseIdentifier,
21
+ customWorker,
22
+ shared,
23
+ loggerForErrors
24
+ }: OpenWorkerOptions): WorkerConnection {
25
+ const name = `${shared ? 'shared-' : ''}powersync-${databaseIdentifier}`;
26
+ let worker: Worker | SharedWorker;
27
+
28
+ if (customWorker) {
29
+ worker = shared
30
+ ? new SharedWorker(customWorker, {
31
+ /* @vite-ignore */
32
+ name,
33
+ type: 'module'
34
+ })
35
+ : new Worker(customWorker, {
36
+ /* @vite-ignore */
37
+ name,
38
+ type: 'module'
39
+ });
40
+ } else {
41
+ worker = spawnDefaultPowerSyncWorker(shared, name);
42
+ }
43
+
44
+ return connectToExistingWorker(worker, loggerForErrors, service);
45
+ }
46
+
47
+ /**
48
+ * Opens the default PowerSync worker.
49
+ *
50
+ * When users depend on the web SDK, we assume they use their own bundler (either vite or webpack). Both recognize the
51
+ * syntax of worker constructors with a string literal and will rewrite the URL as part of their bundling processes.
52
+ *
53
+ * React Native / Metro users can't rely on this on the web, as their app is not a JavaScript module and import.meta.url
54
+ * is not rewritten by Metro. For those users, we include a pre-bundled worker they can copy into a static assets
55
+ * directory and load with a custom URI. This also means that defaultWorker cannot work with Metro for React Native Web.
56
+ * We have a custom rollup plugin and conditional exports that replaces this function with a throwing stub for that
57
+ * platform. This allows a helpful error message.
58
+ */
59
+ // Note: When changing this function, also update disableDefaultWorkers in rollup.config.ts.
60
+ function spawnDefaultPowerSyncWorker(shared: boolean, name: string): Worker | SharedWorker {
61
+ return shared
62
+ ? new SharedWorker(new URL('./worker.js', import.meta.url), {
63
+ /* @vite-ignore */
64
+ name,
65
+ type: 'module'
66
+ })
67
+ : new Worker(new URL('./worker.js', import.meta.url), {
68
+ /* @vite-ignore */
69
+ name,
70
+ type: 'module'
71
+ });
72
+ }
73
+
74
+ export function connectToExistingWorker(
75
+ worker: Worker | SharedWorker,
76
+ logger: PowerSyncLogger,
77
+ service: WorkerService
78
+ ): WorkerConnection {
79
+ function logError(event: ErrorEvent) {
80
+ // TODO: Ideally, we should be able to handle worker errors by forwarding them to async Comlink callers.
81
+ // Currently, comlink calls on errored workers would just be stuck forever.
82
+ logger.log({
83
+ level: LogLevels.error,
84
+ error: event.error,
85
+ message: 'Error in database or sync worker, this likely disrupts PowerSync.'
86
+ });
87
+ }
88
+
89
+ (worker as AbstractWorker).addEventListener('error', logError);
90
+
91
+ const isShared = isSharedWorker(worker);
92
+ if (isShared) {
93
+ const { port1, port2 } = new MessageChannel();
94
+ const mainPort = (worker as SharedWorker).port;
95
+ mainPort.start();
96
+ mainPort.postMessage({ port: port1, service } satisfies SharedWorkerConnectionRequest, [port1]);
97
+
98
+ port2.start();
99
+ return {
100
+ endpoint: port2,
101
+ worker,
102
+ close() {
103
+ worker.removeEventListener('error', logError);
104
+ port2.close();
105
+ }
106
+ };
107
+ } else {
108
+ return {
109
+ endpoint: worker as Worker,
110
+ worker,
111
+ close() {
112
+ worker.removeEventListener('error', logError);
113
+ worker.terminate();
114
+ }
115
+ };
116
+ }
117
+ }
118
+
119
+ export function isSharedWorker(worker: Worker | SharedWorker): worker is SharedWorker {
120
+ return 'port' in worker;
121
+ }