@powersync/service-core 0.8.8 → 0.10.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 (376) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/api/RouteAPI.d.ts +67 -0
  3. package/dist/api/RouteAPI.js +2 -0
  4. package/dist/api/RouteAPI.js.map +1 -0
  5. package/dist/api/api-index.d.ts +1 -0
  6. package/dist/api/api-index.js +1 -0
  7. package/dist/api/api-index.js.map +1 -1
  8. package/dist/api/diagnostics.d.ts +4 -4
  9. package/dist/api/diagnostics.js +170 -158
  10. package/dist/api/diagnostics.js.map +1 -1
  11. package/dist/api/schema.d.ts +3 -5
  12. package/dist/api/schema.js +14 -80
  13. package/dist/api/schema.js.map +1 -1
  14. package/dist/auth/CachedKeyCollector.js.map +1 -1
  15. package/dist/auth/KeySpec.js.map +1 -1
  16. package/dist/auth/KeyStore.d.ts +7 -4
  17. package/dist/auth/KeyStore.js +1 -1
  18. package/dist/auth/KeyStore.js.map +1 -1
  19. package/dist/auth/LeakyBucket.js.map +1 -1
  20. package/dist/auth/RemoteJWKSCollector.d.ts +0 -2
  21. package/dist/auth/RemoteJWKSCollector.js.map +1 -1
  22. package/dist/auth/StaticSupabaseKeyCollector.d.ts +19 -0
  23. package/dist/auth/StaticSupabaseKeyCollector.js +28 -0
  24. package/dist/auth/StaticSupabaseKeyCollector.js.map +1 -0
  25. package/dist/auth/auth-index.d.ts +1 -1
  26. package/dist/auth/auth-index.js +1 -1
  27. package/dist/auth/auth-index.js.map +1 -1
  28. package/dist/db/mongo.js +5 -3
  29. package/dist/db/mongo.js.map +1 -1
  30. package/dist/entry/cli-entry.js +3 -2
  31. package/dist/entry/cli-entry.js.map +1 -1
  32. package/dist/entry/commands/compact-action.js +90 -14
  33. package/dist/entry/commands/compact-action.js.map +1 -1
  34. package/dist/entry/commands/migrate-action.js +4 -5
  35. package/dist/entry/commands/migrate-action.js.map +1 -1
  36. package/dist/entry/commands/teardown-action.js +2 -2
  37. package/dist/entry/commands/teardown-action.js.map +1 -1
  38. package/dist/index.d.ts +4 -2
  39. package/dist/index.js +4 -2
  40. package/dist/index.js.map +1 -1
  41. package/dist/locks/MongoLocks.js.map +1 -1
  42. package/dist/metrics/Metrics.d.ts +2 -2
  43. package/dist/metrics/Metrics.js +5 -13
  44. package/dist/metrics/Metrics.js.map +1 -1
  45. package/dist/migrations/db/migrations/1684951997326-init.d.ts +2 -2
  46. package/dist/migrations/db/migrations/1684951997326-init.js +4 -2
  47. package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
  48. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +2 -2
  49. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +4 -2
  50. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
  51. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +2 -2
  52. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +4 -2
  53. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
  54. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.d.ts +3 -0
  55. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js +31 -0
  56. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js.map +1 -0
  57. package/dist/migrations/executor.js.map +1 -1
  58. package/dist/migrations/migrations.d.ts +8 -0
  59. package/dist/migrations/migrations.js +19 -7
  60. package/dist/migrations/migrations.js.map +1 -1
  61. package/dist/migrations/store/migration-store.js.map +1 -1
  62. package/dist/modules/AbstractModule.d.ts +26 -0
  63. package/dist/modules/AbstractModule.js +11 -0
  64. package/dist/modules/AbstractModule.js.map +1 -0
  65. package/dist/modules/ModuleManager.d.ts +11 -0
  66. package/dist/modules/ModuleManager.js +32 -0
  67. package/dist/modules/ModuleManager.js.map +1 -0
  68. package/dist/modules/modules-index.d.ts +2 -0
  69. package/dist/modules/modules-index.js +3 -0
  70. package/dist/modules/modules-index.js.map +1 -0
  71. package/dist/replication/AbstractReplicationJob.d.ts +37 -0
  72. package/dist/replication/AbstractReplicationJob.js +51 -0
  73. package/dist/replication/AbstractReplicationJob.js.map +1 -0
  74. package/dist/replication/AbstractReplicator.d.ts +53 -0
  75. package/dist/replication/AbstractReplicator.js +250 -0
  76. package/dist/replication/AbstractReplicator.js.map +1 -0
  77. package/dist/replication/ErrorRateLimiter.d.ts +0 -10
  78. package/dist/replication/ErrorRateLimiter.js +1 -42
  79. package/dist/replication/ErrorRateLimiter.js.map +1 -1
  80. package/dist/replication/ReplicationEngine.d.ts +18 -0
  81. package/dist/replication/ReplicationEngine.js +41 -0
  82. package/dist/replication/ReplicationEngine.js.map +1 -0
  83. package/dist/replication/ReplicationModule.d.ts +51 -0
  84. package/dist/replication/ReplicationModule.js +68 -0
  85. package/dist/replication/ReplicationModule.js.map +1 -0
  86. package/dist/replication/replication-index.d.ts +4 -6
  87. package/dist/replication/replication-index.js +4 -6
  88. package/dist/replication/replication-index.js.map +1 -1
  89. package/dist/routes/RouterEngine.d.ts +42 -0
  90. package/dist/routes/RouterEngine.js +80 -0
  91. package/dist/routes/RouterEngine.js.map +1 -0
  92. package/dist/routes/auth.d.ts +2 -2
  93. package/dist/routes/auth.js +11 -11
  94. package/dist/routes/auth.js.map +1 -1
  95. package/dist/routes/configure-fastify.d.ts +37 -23
  96. package/dist/routes/configure-fastify.js +18 -18
  97. package/dist/routes/configure-fastify.js.map +1 -1
  98. package/dist/routes/configure-rsocket.d.ts +3 -4
  99. package/dist/routes/configure-rsocket.js +7 -4
  100. package/dist/routes/configure-rsocket.js.map +1 -1
  101. package/dist/routes/endpoints/admin.d.ts +30 -0
  102. package/dist/routes/endpoints/admin.js +46 -67
  103. package/dist/routes/endpoints/admin.js.map +1 -1
  104. package/dist/routes/endpoints/checkpointing.js +103 -15
  105. package/dist/routes/endpoints/checkpointing.js.map +1 -1
  106. package/dist/routes/endpoints/socket-route.js +8 -6
  107. package/dist/routes/endpoints/socket-route.js.map +1 -1
  108. package/dist/routes/endpoints/sync-rules.d.ts +1 -1
  109. package/dist/routes/endpoints/sync-rules.js +32 -23
  110. package/dist/routes/endpoints/sync-rules.js.map +1 -1
  111. package/dist/routes/endpoints/sync-stream.d.ts +0 -1
  112. package/dist/routes/endpoints/sync-stream.js +8 -8
  113. package/dist/routes/endpoints/sync-stream.js.map +1 -1
  114. package/dist/routes/hooks.js.map +1 -1
  115. package/dist/routes/route-register.js.map +1 -1
  116. package/dist/routes/router.d.ts +9 -2
  117. package/dist/routes/router.js.map +1 -1
  118. package/dist/routes/routes-index.d.ts +1 -0
  119. package/dist/routes/routes-index.js +1 -0
  120. package/dist/routes/routes-index.js.map +1 -1
  121. package/dist/runner/teardown.js +109 -76
  122. package/dist/runner/teardown.js.map +1 -1
  123. package/dist/storage/BucketStorage.d.ts +86 -36
  124. package/dist/storage/BucketStorage.js +6 -10
  125. package/dist/storage/BucketStorage.js.map +1 -1
  126. package/dist/storage/ChecksumCache.js.map +1 -1
  127. package/dist/storage/MongoBucketStorage.d.ts +7 -11
  128. package/dist/storage/MongoBucketStorage.js +48 -41
  129. package/dist/storage/MongoBucketStorage.js.map +1 -1
  130. package/dist/storage/ReplicationEventPayload.d.ts +14 -0
  131. package/dist/storage/ReplicationEventPayload.js +2 -0
  132. package/dist/storage/ReplicationEventPayload.js.map +1 -0
  133. package/dist/storage/SourceEntity.d.ts +20 -0
  134. package/dist/storage/SourceEntity.js +2 -0
  135. package/dist/storage/SourceEntity.js.map +1 -0
  136. package/dist/storage/SourceTable.d.ts +12 -5
  137. package/dist/storage/SourceTable.js +12 -5
  138. package/dist/storage/SourceTable.js.map +1 -1
  139. package/dist/storage/StorageEngine.d.ts +28 -0
  140. package/dist/storage/StorageEngine.js +45 -0
  141. package/dist/storage/StorageEngine.js.map +1 -0
  142. package/dist/storage/StorageProvider.d.ts +21 -0
  143. package/dist/storage/StorageProvider.js +2 -0
  144. package/dist/storage/StorageProvider.js.map +1 -0
  145. package/dist/storage/WriteCheckpointAPI.d.ts +74 -0
  146. package/dist/storage/WriteCheckpointAPI.js +16 -0
  147. package/dist/storage/WriteCheckpointAPI.js.map +1 -0
  148. package/dist/storage/mongo/MongoBucketBatch.d.ts +24 -5
  149. package/dist/storage/mongo/MongoBucketBatch.js +119 -62
  150. package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
  151. package/dist/storage/mongo/MongoCompactor.js +20 -3
  152. package/dist/storage/mongo/MongoCompactor.js.map +1 -1
  153. package/dist/storage/mongo/MongoIdSequence.js.map +1 -1
  154. package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +2 -2
  155. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +2 -2
  156. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -1
  157. package/dist/storage/mongo/MongoStorageProvider.d.ts +5 -0
  158. package/dist/storage/mongo/MongoStorageProvider.js +26 -0
  159. package/dist/storage/mongo/MongoStorageProvider.js.map +1 -0
  160. package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +18 -10
  161. package/dist/storage/mongo/MongoSyncBucketStorage.js +140 -25
  162. package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
  163. package/dist/storage/mongo/MongoSyncRulesLock.js +1 -1
  164. package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -1
  165. package/dist/storage/mongo/MongoWriteCheckpointAPI.d.ts +20 -0
  166. package/dist/storage/mongo/MongoWriteCheckpointAPI.js +103 -0
  167. package/dist/storage/mongo/MongoWriteCheckpointAPI.js.map +1 -0
  168. package/dist/storage/mongo/OperationBatch.d.ts +13 -4
  169. package/dist/storage/mongo/OperationBatch.js +25 -7
  170. package/dist/storage/mongo/OperationBatch.js.map +1 -1
  171. package/dist/storage/mongo/PersistedBatch.d.ts +3 -3
  172. package/dist/storage/mongo/PersistedBatch.js +2 -2
  173. package/dist/storage/mongo/PersistedBatch.js.map +1 -1
  174. package/dist/storage/mongo/config.d.ts +19 -0
  175. package/dist/storage/mongo/config.js +26 -0
  176. package/dist/storage/mongo/config.js.map +1 -0
  177. package/dist/storage/mongo/db.d.ts +3 -2
  178. package/dist/storage/mongo/db.js +1 -0
  179. package/dist/storage/mongo/db.js.map +1 -1
  180. package/dist/storage/mongo/models.d.ts +20 -5
  181. package/dist/storage/mongo/models.js.map +1 -1
  182. package/dist/storage/mongo/util.d.ts +12 -1
  183. package/dist/storage/mongo/util.js +50 -2
  184. package/dist/storage/mongo/util.js.map +1 -1
  185. package/dist/storage/storage-index.d.ts +8 -2
  186. package/dist/storage/storage-index.js +8 -2
  187. package/dist/storage/storage-index.js.map +1 -1
  188. package/dist/sync/BroadcastIterable.d.ts +0 -1
  189. package/dist/sync/BroadcastIterable.js.map +1 -1
  190. package/dist/sync/LastValueSink.d.ts +0 -1
  191. package/dist/sync/LastValueSink.js.map +1 -1
  192. package/dist/sync/merge.d.ts +0 -1
  193. package/dist/sync/merge.js.map +1 -1
  194. package/dist/sync/safeRace.js.map +1 -1
  195. package/dist/sync/sync.d.ts +1 -1
  196. package/dist/sync/sync.js +5 -5
  197. package/dist/sync/sync.js.map +1 -1
  198. package/dist/sync/util.d.ts +0 -2
  199. package/dist/sync/util.js.map +1 -1
  200. package/dist/system/ServiceContext.d.ts +37 -0
  201. package/dist/system/ServiceContext.js +48 -0
  202. package/dist/system/ServiceContext.js.map +1 -0
  203. package/dist/system/system-index.d.ts +1 -1
  204. package/dist/system/system-index.js +1 -1
  205. package/dist/system/system-index.js.map +1 -1
  206. package/dist/util/Mutex.js.map +1 -1
  207. package/dist/util/config/collectors/config-collector.js.map +1 -1
  208. package/dist/util/config/collectors/impl/base64-config-collector.js.map +1 -1
  209. package/dist/util/config/collectors/impl/filesystem-config-collector.js.map +1 -1
  210. package/dist/util/config/compound-config-collector.d.ts +9 -2
  211. package/dist/util/config/compound-config-collector.js +31 -23
  212. package/dist/util/config/compound-config-collector.js.map +1 -1
  213. package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js.map +1 -1
  214. package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js.map +1 -1
  215. package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js.map +1 -1
  216. package/dist/util/config/sync-rules/sync-rules-provider.d.ts +9 -0
  217. package/dist/util/config/sync-rules/sync-rules-provider.js +15 -0
  218. package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -0
  219. package/dist/util/config/types.d.ts +7 -4
  220. package/dist/util/config/types.js.map +1 -1
  221. package/dist/util/config.d.ts +3 -4
  222. package/dist/util/config.js +5 -20
  223. package/dist/util/config.js.map +1 -1
  224. package/dist/util/memory-tracking.js.map +1 -1
  225. package/dist/util/secs.js.map +1 -1
  226. package/dist/util/util-index.d.ts +3 -6
  227. package/dist/util/util-index.js +3 -6
  228. package/dist/util/util-index.js.map +1 -1
  229. package/dist/util/utils.d.ts +10 -7
  230. package/dist/util/utils.js +36 -25
  231. package/dist/util/utils.js.map +1 -1
  232. package/package.json +8 -12
  233. package/src/api/RouteAPI.ts +78 -0
  234. package/src/api/api-index.ts +1 -0
  235. package/src/api/diagnostics.ts +18 -70
  236. package/src/api/schema.ts +18 -90
  237. package/src/auth/KeyStore.ts +9 -6
  238. package/src/auth/RemoteJWKSCollector.ts +4 -1
  239. package/src/auth/StaticSupabaseKeyCollector.ts +31 -0
  240. package/src/auth/auth-index.ts +1 -1
  241. package/src/db/mongo.ts +5 -3
  242. package/src/entry/cli-entry.ts +3 -2
  243. package/src/entry/commands/compact-action.ts +24 -12
  244. package/src/entry/commands/migrate-action.ts +5 -8
  245. package/src/entry/commands/teardown-action.ts +2 -2
  246. package/src/index.ts +5 -2
  247. package/src/metrics/Metrics.ts +6 -16
  248. package/src/migrations/db/migrations/1684951997326-init.ts +9 -4
  249. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -4
  250. package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +6 -4
  251. package/src/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.ts +37 -0
  252. package/src/migrations/migrations.ts +24 -8
  253. package/src/modules/AbstractModule.ts +37 -0
  254. package/src/modules/ModuleManager.ts +34 -0
  255. package/src/modules/modules-index.ts +2 -0
  256. package/src/replication/AbstractReplicationJob.ts +79 -0
  257. package/src/replication/AbstractReplicator.ts +228 -0
  258. package/src/replication/ErrorRateLimiter.ts +0 -44
  259. package/src/replication/ReplicationEngine.ts +43 -0
  260. package/src/replication/ReplicationModule.ts +122 -0
  261. package/src/replication/replication-index.ts +4 -6
  262. package/src/routes/RouterEngine.ts +120 -0
  263. package/src/routes/auth.ts +21 -12
  264. package/src/routes/configure-fastify.ts +26 -27
  265. package/src/routes/configure-rsocket.ts +13 -8
  266. package/src/routes/endpoints/admin.ts +72 -76
  267. package/src/routes/endpoints/checkpointing.ts +51 -11
  268. package/src/routes/endpoints/socket-route.ts +10 -6
  269. package/src/routes/endpoints/sync-rules.ts +41 -25
  270. package/src/routes/endpoints/sync-stream.ts +8 -8
  271. package/src/routes/router.ts +8 -3
  272. package/src/routes/routes-index.ts +1 -0
  273. package/src/runner/teardown.ts +50 -88
  274. package/src/storage/BucketStorage.ts +103 -41
  275. package/src/storage/MongoBucketStorage.ts +65 -53
  276. package/src/storage/ReplicationEventPayload.ts +16 -0
  277. package/src/storage/SourceEntity.ts +22 -0
  278. package/src/storage/SourceTable.ts +14 -7
  279. package/src/storage/StorageEngine.ts +62 -0
  280. package/src/storage/StorageProvider.ts +27 -0
  281. package/src/storage/WriteCheckpointAPI.ts +85 -0
  282. package/src/storage/mongo/MongoBucketBatch.ts +164 -84
  283. package/src/storage/mongo/MongoCompactor.ts +25 -4
  284. package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +7 -4
  285. package/src/storage/mongo/MongoStorageProvider.ts +31 -0
  286. package/src/storage/mongo/MongoSyncBucketStorage.ts +118 -41
  287. package/src/storage/mongo/MongoSyncRulesLock.ts +7 -3
  288. package/src/storage/mongo/MongoWriteCheckpointAPI.ts +151 -0
  289. package/src/storage/mongo/OperationBatch.ts +28 -12
  290. package/src/storage/mongo/PersistedBatch.ts +10 -6
  291. package/src/storage/mongo/config.ts +40 -0
  292. package/src/storage/mongo/db.ts +4 -1
  293. package/src/storage/mongo/models.ts +21 -5
  294. package/src/storage/mongo/util.ts +48 -3
  295. package/src/storage/storage-index.ts +8 -2
  296. package/src/sync/sync.ts +7 -4
  297. package/src/sync/util.ts +0 -1
  298. package/src/system/ServiceContext.ts +68 -0
  299. package/src/system/system-index.ts +1 -1
  300. package/src/util/config/compound-config-collector.ts +48 -30
  301. package/src/util/config/sync-rules/sync-rules-provider.ts +18 -0
  302. package/src/util/config/types.ts +7 -5
  303. package/src/util/config.ts +6 -23
  304. package/src/util/util-index.ts +3 -6
  305. package/src/util/utils.ts +48 -41
  306. package/test/src/__snapshots__/sync.test.ts.snap +14 -14
  307. package/test/src/auth.test.ts +7 -7
  308. package/test/src/broadcast_iterable.test.ts +1 -1
  309. package/test/src/compacting.test.ts +50 -40
  310. package/test/src/data_storage.test.ts +382 -202
  311. package/test/src/env.ts +1 -3
  312. package/test/src/merge_iterable.test.ts +1 -6
  313. package/test/src/routes/probes.integration.test.ts +34 -30
  314. package/test/src/setup.ts +1 -1
  315. package/test/src/stream_utils.ts +42 -0
  316. package/test/src/sync.test.ts +115 -39
  317. package/test/src/util.ts +48 -51
  318. package/test/tsconfig.json +1 -1
  319. package/tsconfig.tsbuildinfo +1 -1
  320. package/vitest.config.ts +7 -1
  321. package/dist/auth/SupabaseKeyCollector.d.ts +0 -22
  322. package/dist/auth/SupabaseKeyCollector.js +0 -61
  323. package/dist/auth/SupabaseKeyCollector.js.map +0 -1
  324. package/dist/replication/PgRelation.d.ts +0 -16
  325. package/dist/replication/PgRelation.js +0 -26
  326. package/dist/replication/PgRelation.js.map +0 -1
  327. package/dist/replication/WalConnection.d.ts +0 -34
  328. package/dist/replication/WalConnection.js +0 -190
  329. package/dist/replication/WalConnection.js.map +0 -1
  330. package/dist/replication/WalStream.d.ts +0 -57
  331. package/dist/replication/WalStream.js +0 -519
  332. package/dist/replication/WalStream.js.map +0 -1
  333. package/dist/replication/WalStreamManager.d.ts +0 -30
  334. package/dist/replication/WalStreamManager.js +0 -198
  335. package/dist/replication/WalStreamManager.js.map +0 -1
  336. package/dist/replication/WalStreamRunner.d.ts +0 -38
  337. package/dist/replication/WalStreamRunner.js +0 -155
  338. package/dist/replication/WalStreamRunner.js.map +0 -1
  339. package/dist/replication/util.d.ts +0 -9
  340. package/dist/replication/util.js +0 -62
  341. package/dist/replication/util.js.map +0 -1
  342. package/dist/system/CorePowerSyncSystem.d.ts +0 -23
  343. package/dist/system/CorePowerSyncSystem.js +0 -52
  344. package/dist/system/CorePowerSyncSystem.js.map +0 -1
  345. package/dist/util/PgManager.d.ts +0 -24
  346. package/dist/util/PgManager.js +0 -55
  347. package/dist/util/PgManager.js.map +0 -1
  348. package/dist/util/migration_lib.d.ts +0 -11
  349. package/dist/util/migration_lib.js +0 -64
  350. package/dist/util/migration_lib.js.map +0 -1
  351. package/dist/util/pgwire_utils.d.ts +0 -24
  352. package/dist/util/pgwire_utils.js +0 -117
  353. package/dist/util/pgwire_utils.js.map +0 -1
  354. package/dist/util/populate_test_data.d.ts +0 -8
  355. package/dist/util/populate_test_data.js +0 -65
  356. package/dist/util/populate_test_data.js.map +0 -1
  357. package/src/auth/SupabaseKeyCollector.ts +0 -67
  358. package/src/replication/PgRelation.ts +0 -42
  359. package/src/replication/WalConnection.ts +0 -227
  360. package/src/replication/WalStream.ts +0 -631
  361. package/src/replication/WalStreamManager.ts +0 -213
  362. package/src/replication/WalStreamRunner.ts +0 -180
  363. package/src/replication/util.ts +0 -76
  364. package/src/system/CorePowerSyncSystem.ts +0 -64
  365. package/src/util/PgManager.ts +0 -64
  366. package/src/util/migration_lib.ts +0 -79
  367. package/src/util/pgwire_utils.ts +0 -139
  368. package/src/util/populate_test_data.ts +0 -78
  369. package/test/src/__snapshots__/pg_test.test.ts.snap +0 -256
  370. package/test/src/large_batch.test.ts +0 -194
  371. package/test/src/pg_test.test.ts +0 -450
  372. package/test/src/schema_changes.test.ts +0 -545
  373. package/test/src/slow_tests.test.ts +0 -338
  374. package/test/src/validation.test.ts +0 -63
  375. package/test/src/wal_stream.test.ts +0 -319
  376. package/test/src/wal_stream_utils.ts +0 -156
@@ -1,7 +1,10 @@
1
+ import * as bson from 'bson';
1
2
  import crypto from 'crypto';
2
- import { logger } from '@powersync/lib-services-framework';
3
- import { pgwireRows } from '@powersync/service-jpgwire';
4
- import { retriedQuery } from './pgwire_utils.js';
3
+ import * as uuid from 'uuid';
4
+ export const ID_NAMESPACE = 'a396dd91-09fc-4017-a28d-3df722f651e9';
5
+ export function escapeIdentifier(identifier) {
6
+ return `"${identifier.replace(/"/g, '""').replace(/\./g, '"."')}"`;
7
+ }
5
8
  export function hashData(type, id, data) {
6
9
  const hash = crypto.createHash('sha256');
7
10
  hash.update(`put.${type}.${id}.${data}`);
@@ -70,31 +73,39 @@ export function addBucketChecksums(a, b) {
70
73
  };
71
74
  }
72
75
  }
73
- export async function getClientCheckpoint(db, bucketStorage, options) {
74
- const start = Date.now();
75
- const [{ lsn }] = pgwireRows(await db.query(`SELECT pg_logical_emit_message(false, 'powersync', 'ping') as lsn`));
76
- // This old API needs a persisted checkpoint id.
77
- // Since we don't use LSNs anymore, the only way to get that is to wait.
78
- const timeout = options?.timeout ?? 50000;
79
- logger.info(`Waiting for LSN checkpoint: ${lsn}`);
80
- while (Date.now() - start < timeout) {
81
- const cp = await bucketStorage.getActiveCheckpoint();
82
- if (!cp.hasSyncRules()) {
83
- throw new Error('No sync rules available');
84
- }
85
- if (cp.lsn >= lsn) {
86
- logger.info(`Got write checkpoint: ${lsn} : ${cp.checkpoint}`);
87
- return cp.checkpoint;
76
+ function getRawReplicaIdentity(tuple, columns) {
77
+ let result = {};
78
+ for (let column of columns) {
79
+ const name = column.name;
80
+ result[name] = tuple[name];
81
+ }
82
+ return result;
83
+ }
84
+ export function getUuidReplicaIdentityBson(tuple, columns) {
85
+ if (columns.length == 0) {
86
+ // REPLICA IDENTITY NOTHING - generate random id
87
+ return new bson.UUID(uuid.v4());
88
+ }
89
+ const rawIdentity = getRawReplicaIdentity(tuple, columns);
90
+ return uuidForRowBson(rawIdentity);
91
+ }
92
+ export function uuidForRowBson(row) {
93
+ // Important: This must not change, since it will affect how ids are generated.
94
+ // Use BSON so that it's a well-defined format without encoding ambiguities.
95
+ const repr = bson.serialize(row);
96
+ const buffer = Buffer.alloc(16);
97
+ return new bson.UUID(uuid.v5(repr, ID_NAMESPACE, buffer));
98
+ }
99
+ export function hasToastedValues(row) {
100
+ for (let key in row) {
101
+ if (typeof row[key] == 'undefined') {
102
+ return true;
88
103
  }
89
- await new Promise((resolve) => setTimeout(resolve, 30));
90
104
  }
91
- throw new Error('Timeout while waiting for checkpoint');
105
+ return false;
92
106
  }
93
- export async function createWriteCheckpoint(db, bucketStorage, user_id) {
94
- const [{ lsn }] = pgwireRows(await retriedQuery(db, `SELECT pg_logical_emit_message(false, 'powersync', 'ping') as lsn`));
95
- const id = await bucketStorage.createWriteCheckpoint(user_id, { '1': lsn });
96
- logger.info(`Write checkpoint 2: ${JSON.stringify({ lsn, id: String(id) })}`);
97
- return id;
107
+ export function isCompleteRow(row) {
108
+ return !hasToastedValues(row);
98
109
  }
99
110
  export function checkpointUserId(user_id, client_id) {
100
111
  if (user_id == null) {
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/util/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/util/utils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
- "version": "0.8.8",
8
+ "version": "0.10.0",
9
9
  "main": "dist/index.js",
10
10
  "license": "FSL-1.1-Apache-2.0",
11
11
  "type": "module",
@@ -28,32 +28,28 @@
28
28
  "lru-cache": "^10.2.2",
29
29
  "mongodb": "^6.7.0",
30
30
  "node-fetch": "^3.3.2",
31
- "pgwire": "github:kagis/pgwire#f1cb95f9a0f42a612bb5a6b67bb2eb793fc5fc87",
32
31
  "ts-codec": "^1.2.2",
32
+ "uri-js": "^4.4.1",
33
33
  "uuid": "^9.0.1",
34
34
  "winston": "^3.13.0",
35
35
  "yaml": "^2.3.2",
36
- "@powersync/lib-services-framework": "0.1.1",
36
+ "@powersync/lib-services-framework": "0.2.0",
37
37
  "@powersync/service-jsonbig": "0.17.10",
38
- "@powersync/service-jpgwire": "0.17.14",
39
- "@powersync/service-rsocket-router": "0.0.13",
40
- "@powersync/service-sync-rules": "0.20.0",
41
- "@powersync/service-types": "0.2.0"
38
+ "@powersync/service-rsocket-router": "0.0.14",
39
+ "@powersync/service-sync-rules": "0.21.0",
40
+ "@powersync/service-types": "0.4.0"
42
41
  },
43
42
  "devDependencies": {
44
43
  "@types/async": "^3.2.24",
45
44
  "@types/lodash": "^4.17.5",
46
45
  "@types/uuid": "^9.0.4",
47
46
  "fastify": "4.23.2",
48
- "fastify-plugin": "^4.5.1",
49
- "typescript": "^5.2.2",
50
- "vite-tsconfig-paths": "^4.3.2",
51
- "vitest": "^0.34.6"
47
+ "fastify-plugin": "^4.5.1"
52
48
  },
53
49
  "scripts": {
54
50
  "build": "tsc -b",
55
51
  "build:tests": "tsc -b test/tsconfig.json",
56
- "test": "vitest --no-threads",
52
+ "test": "vitest",
57
53
  "clean": "rm -rf ./dist && tsc -b --clean"
58
54
  }
59
55
  }
@@ -0,0 +1,78 @@
1
+ import { SqlSyncRules, TablePattern } from '@powersync/service-sync-rules';
2
+ import * as types from '@powersync/service-types';
3
+ import { ParseSyncRulesOptions, SyncRulesBucketStorage } from '../storage/BucketStorage.js';
4
+
5
+ export interface PatternResult {
6
+ schema: string;
7
+ pattern: string;
8
+ wildcard: boolean;
9
+ tables?: types.TableInfo[];
10
+ table?: types.TableInfo;
11
+ }
12
+
13
+ export interface ReplicationLagOptions {
14
+ bucketStorage: SyncRulesBucketStorage;
15
+ }
16
+
17
+ /**
18
+ * Describes all the methods currently required to service the sync API endpoints.
19
+ */
20
+ export interface RouteAPI {
21
+ /**
22
+ * @returns basic identification of the connection
23
+ */
24
+ getSourceConfig(): Promise<types.configFile.ResolvedDataSourceConfig>;
25
+
26
+ /**
27
+ * Checks the current connection status of the data source.
28
+ * This is usually some test query to verify the source can be reached.
29
+ */
30
+ getConnectionStatus(): Promise<types.ConnectionStatusV2>;
31
+
32
+ /**
33
+ * Generates replication table information from a given pattern of tables.
34
+ *
35
+ * @param tablePatterns A set of table patterns which typically come from
36
+ * the tables listed in sync rules definitions.
37
+ *
38
+ * @param sqlSyncRules
39
+ * @returns A result of all the tables and columns which should be replicated
40
+ * based off the input patterns. Certain tests are executed on the
41
+ * tables to ensure syncing should function according to the input
42
+ * pattern. Debug errors and warnings are reported per table.
43
+ */
44
+ getDebugTablesInfo(tablePatterns: TablePattern[], sqlSyncRules: SqlSyncRules): Promise<PatternResult[]>;
45
+
46
+ /**
47
+ * @returns The replication lag: that is the amount of data which has not been
48
+ * replicated yet, in bytes.
49
+ */
50
+ getReplicationLag(options: ReplicationLagOptions): Promise<number | undefined>;
51
+
52
+ /**
53
+ * Get the current LSN or equivalent replication HEAD position identifier
54
+ */
55
+ getReplicationHead(): Promise<string>;
56
+
57
+ /**
58
+ * @returns The schema for tables inside the connected database. This is typically
59
+ * used to validate sync rules.
60
+ */
61
+ getConnectionSchema(): Promise<types.DatabaseSchema[]>;
62
+
63
+ /**
64
+ * Executes a query and return the result from the data source. This is currently used in the
65
+ * admin API which is exposed in Collide.
66
+ */
67
+ executeQuery(query: string, params: any[]): Promise<types.internal_routes.ExecuteSqlResponse>;
68
+
69
+ /**
70
+ * Close any resources that need graceful termination.
71
+ */
72
+ shutdown(): Promise<void>;
73
+
74
+ /**
75
+ * Get the default schema (or database) when only a table name is specified in sync rules.
76
+ */
77
+ getParseSyncRulesOptions(): ParseSyncRulesOptions;
78
+ }
@@ -1,2 +1,3 @@
1
1
  export * from './diagnostics.js';
2
+ export * from './RouteAPI.js';
2
3
  export * from './schema.js';
@@ -1,51 +1,9 @@
1
+ import { logger } from '@powersync/lib-services-framework';
1
2
  import { DEFAULT_TAG, SourceTableInterface, SqlSyncRules } from '@powersync/service-sync-rules';
2
- import { pgwireRows } from '@powersync/service-jpgwire';
3
- import { ConnectionStatus, SyncRulesStatus, TableInfo, baseUri } from '@powersync/service-types';
3
+ import { SyncRulesStatus, TableInfo } from '@powersync/service-types';
4
4
 
5
- import * as replication from '../replication/replication-index.js';
6
5
  import * as storage from '../storage/storage-index.js';
7
- import * as util from '../util/util-index.js';
8
-
9
- import { CorePowerSyncSystem } from '../system/CorePowerSyncSystem.js';
10
- import { logger } from '@powersync/lib-services-framework';
11
-
12
- export async function getConnectionStatus(system: CorePowerSyncSystem): Promise<ConnectionStatus | null> {
13
- if (system.pgwire_pool == null) {
14
- return null;
15
- }
16
-
17
- const pool = system.requirePgPool();
18
-
19
- const base = {
20
- id: system.config.connection!.id,
21
- postgres_uri: baseUri(system.config.connection!)
22
- };
23
- try {
24
- await util.retriedQuery(pool, `SELECT 'PowerSync connection test'`);
25
- } catch (e) {
26
- return {
27
- ...base,
28
- connected: false,
29
- errors: [{ level: 'fatal', message: e.message }]
30
- };
31
- }
32
-
33
- try {
34
- await replication.checkSourceConfiguration(pool);
35
- } catch (e) {
36
- return {
37
- ...base,
38
- connected: true,
39
- errors: [{ level: 'fatal', message: e.message }]
40
- };
41
- }
42
-
43
- return {
44
- ...base,
45
- connected: true,
46
- errors: []
47
- };
48
- }
6
+ import { RouteAPI } from './RouteAPI.js';
49
7
 
50
8
  export interface DiagnosticsOptions {
51
9
  /**
@@ -66,9 +24,12 @@ export interface DiagnosticsOptions {
66
24
  check_connection: boolean;
67
25
  }
68
26
 
27
+ export const DEFAULT_DATASOURCE_ID = 'default';
28
+
69
29
  export async function getSyncRulesStatus(
30
+ bucketStorage: storage.BucketStorageFactory,
31
+ apiHandler: RouteAPI,
70
32
  sync_rules: storage.PersistedSyncRulesContent | null,
71
- system: CorePowerSyncSystem,
72
33
  options: DiagnosticsOptions
73
34
  ): Promise<SyncRulesStatus | undefined> {
74
35
  if (sync_rules == null) {
@@ -82,7 +43,7 @@ export async function getSyncRulesStatus(
82
43
  let rules: SqlSyncRules;
83
44
  let persisted: storage.PersistedSyncRules;
84
45
  try {
85
- persisted = sync_rules.parsed();
46
+ persisted = sync_rules.parsed(apiHandler.getParseSyncRulesOptions());
86
47
  rules = persisted.sync_rules;
87
48
  } catch (e) {
88
49
  return {
@@ -92,21 +53,19 @@ export async function getSyncRulesStatus(
92
53
  };
93
54
  }
94
55
 
95
- const systemStorage = live_status ? await system.storage.getInstance(persisted) : undefined;
56
+ const sourceConfig = await apiHandler.getSourceConfig();
57
+ // This method can run under some situations if no connection is configured yet.
58
+ // It will return a default tag in such a case. This default tag is not module specific.
59
+ const tag = sourceConfig.tag ?? DEFAULT_TAG;
60
+ using systemStorage = live_status ? bucketStorage.getInstance(sync_rules) : undefined;
96
61
  const status = await systemStorage?.getStatus();
97
62
  let replication_lag_bytes: number | undefined = undefined;
98
63
 
99
64
  let tables_flat: TableInfo[] = [];
100
65
 
101
66
  if (check_connection) {
102
- const pool = system.requirePgPool();
103
-
104
67
  const source_table_patterns = rules.getSourceTables();
105
- const wc = new replication.WalConnection({
106
- db: pool,
107
- sync_rules: rules
108
- });
109
- const resolved_tables = await wc.getDebugTablesInfo(source_table_patterns);
68
+ const resolved_tables = await apiHandler.getDebugTablesInfo(source_table_patterns, rules);
110
69
  tables_flat = resolved_tables.flatMap((info) => {
111
70
  if (info.table) {
112
71
  return [info.table];
@@ -119,19 +78,9 @@ export async function getSyncRulesStatus(
119
78
 
120
79
  if (systemStorage) {
121
80
  try {
122
- const results = await util.retriedQuery(pool, {
123
- statement: `SELECT
124
- slot_name,
125
- confirmed_flush_lsn,
126
- pg_current_wal_lsn(),
127
- (pg_current_wal_lsn() - confirmed_flush_lsn) AS lsn_distance
128
- FROM pg_replication_slots WHERE slot_name = $1 LIMIT 1;`,
129
- params: [{ type: 'varchar', value: systemStorage!.slot_name }]
81
+ replication_lag_bytes = await apiHandler.getReplicationLag({
82
+ bucketStorage: systemStorage
130
83
  });
131
- const [row] = pgwireRows(results);
132
- if (row) {
133
- replication_lag_bytes = Number(row.lsn_distance);
134
- }
135
84
  } catch (e) {
136
85
  // Ignore
137
86
  logger.warn(`Unable to get replication lag`, e);
@@ -139,7 +88,6 @@ export async function getSyncRulesStatus(
139
88
  }
140
89
  } else {
141
90
  const source_table_patterns = rules.getSourceTables();
142
- const tag = system.config.connection!.tag ?? DEFAULT_TAG;
143
91
 
144
92
  tables_flat = source_table_patterns.map((pattern): TableInfo => {
145
93
  if (pattern.isWildcard) {
@@ -190,8 +138,8 @@ export async function getSyncRulesStatus(
190
138
  content: include_content ? sync_rules.sync_rules_content : undefined,
191
139
  connections: [
192
140
  {
193
- id: system.config.connection!.id,
194
- tag: system.config.connection!.tag ?? DEFAULT_TAG,
141
+ id: sourceConfig.id ?? DEFAULT_DATASOURCE_ID,
142
+ tag: tag,
195
143
  slot_name: sync_rules.slot_name,
196
144
  initial_replication_done: status?.snapshot_done ?? false,
197
145
  // TODO: Rename?
package/src/api/schema.ts CHANGED
@@ -1,99 +1,27 @@
1
- import type * as pgwire from '@powersync/service-jpgwire';
2
- import { pgwireRows } from '@powersync/service-jpgwire';
3
- import { DatabaseSchema, internal_routes } from '@powersync/service-types';
1
+ import { internal_routes } from '@powersync/service-types';
4
2
 
5
- import * as util from '../util/util-index.js';
6
- import { CorePowerSyncSystem } from '../system/CorePowerSyncSystem.js';
3
+ import * as api from '../api/api-index.js';
7
4
 
8
- export async function getConnectionsSchema(system: CorePowerSyncSystem): Promise<internal_routes.GetSchemaResponse> {
9
- if (system.config.connection == null) {
10
- return { connections: [] };
5
+ export async function getConnectionsSchema(api: api.RouteAPI): Promise<internal_routes.GetSchemaResponse> {
6
+ if (!api) {
7
+ return {
8
+ connections: [],
9
+ defaultConnectionTag: 'default',
10
+ defaultSchema: ''
11
+ };
11
12
  }
12
- const schemas = await getConnectionSchema(system.requirePgPool());
13
+
14
+ const baseConfig = await api.getSourceConfig();
15
+
13
16
  return {
14
17
  connections: [
15
18
  {
16
- schemas,
17
- tag: system.config.connection!.tag,
18
- id: system.config.connection!.id
19
+ id: baseConfig.id,
20
+ tag: baseConfig.tag,
21
+ schemas: await api.getConnectionSchema()
19
22
  }
20
- ]
23
+ ],
24
+ defaultConnectionTag: baseConfig.tag!,
25
+ defaultSchema: api.getParseSyncRulesOptions().defaultSchema
21
26
  };
22
27
  }
23
-
24
- export async function getConnectionSchema(db: pgwire.PgClient): Promise<DatabaseSchema[]> {
25
- // https://github.com/Borvik/vscode-postgres/blob/88ec5ed061a0c9bced6c5d4ec122d0759c3f3247/src/language/server.ts
26
- const results = await util.retriedQuery(
27
- db,
28
- `SELECT
29
- tbl.schemaname,
30
- tbl.tablename,
31
- tbl.quoted_name,
32
- json_agg(a ORDER BY attnum) as columns
33
- FROM
34
- (
35
- SELECT
36
- n.nspname as schemaname,
37
- c.relname as tablename,
38
- (quote_ident(n.nspname) || '.' || quote_ident(c.relname)) as quoted_name
39
- FROM
40
- pg_catalog.pg_class c
41
- JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
42
- WHERE
43
- c.relkind = 'r'
44
- AND n.nspname not in ('information_schema', 'pg_catalog', 'pg_toast')
45
- AND n.nspname not like 'pg_temp_%'
46
- AND n.nspname not like 'pg_toast_temp_%'
47
- AND c.relnatts > 0
48
- AND has_schema_privilege(n.oid, 'USAGE') = true
49
- AND has_table_privilege(quote_ident(n.nspname) || '.' || quote_ident(c.relname), 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') = true
50
- ) as tbl
51
- LEFT JOIN (
52
- SELECT
53
- attrelid,
54
- attname,
55
- format_type(atttypid, atttypmod) as data_type,
56
- (SELECT typname FROM pg_catalog.pg_type WHERE oid = atttypid) as pg_type,
57
- attnum,
58
- attisdropped
59
- FROM
60
- pg_attribute
61
- ) as a ON (
62
- a.attrelid = tbl.quoted_name::regclass
63
- AND a.attnum > 0
64
- AND NOT a.attisdropped
65
- AND has_column_privilege(tbl.quoted_name, a.attname, 'SELECT, INSERT, UPDATE, REFERENCES')
66
- )
67
- GROUP BY schemaname, tablename, quoted_name`
68
- );
69
- const rows = pgwireRows(results);
70
-
71
- let schemas: Record<string, any> = {};
72
-
73
- for (let row of rows) {
74
- const schema = (schemas[row.schemaname] ??= {
75
- name: row.schemaname,
76
- tables: []
77
- });
78
- const table = {
79
- name: row.tablename,
80
- columns: [] as any[]
81
- };
82
- schema.tables.push(table);
83
-
84
- const columnInfo = JSON.parse(row.columns);
85
- for (let column of columnInfo) {
86
- let pg_type = column.pg_type as string;
87
- if (pg_type.startsWith('_')) {
88
- pg_type = `${pg_type.substring(1)}[]`;
89
- }
90
- table.columns.push({
91
- name: column.attname,
92
- type: column.data_type,
93
- pg_type: pg_type
94
- });
95
- }
96
- }
97
-
98
- return Object.values(schemas);
99
- }
@@ -1,9 +1,9 @@
1
+ import { logger } from '@powersync/lib-services-framework';
1
2
  import * as jose from 'jose';
2
3
  import secs from '../util/secs.js';
3
- import { KeyOptions, KeySpec, SUPPORTED_ALGORITHMS } from './KeySpec.js';
4
- import { KeyCollector } from './KeyCollector.js';
5
4
  import { JwtPayload } from './JwtPayload.js';
6
- import { logger } from '@powersync/lib-services-framework';
5
+ import { KeyCollector } from './KeyCollector.js';
6
+ import { KeyOptions, KeySpec, SUPPORTED_ALGORITHMS } from './KeySpec.js';
7
7
 
8
8
  /**
9
9
  * KeyStore to get keys and verify tokens.
@@ -32,10 +32,13 @@ import { logger } from '@powersync/lib-services-framework';
32
32
  * If we have a matching kid, we can generally get a detailed error (e.g. signature verification failed, invalid algorithm, etc).
33
33
  * If we don't have a matching kid, we'll generally just get an error "Could not find an appropriate key...".
34
34
  */
35
- export class KeyStore {
36
- private collector: KeyCollector;
35
+ export class KeyStore<Collector extends KeyCollector = KeyCollector> {
36
+ /**
37
+ * @internal
38
+ */
39
+ collector: Collector;
37
40
 
38
- constructor(collector: KeyCollector) {
41
+ constructor(collector: Collector) {
39
42
  this.collector = collector;
40
43
  }
41
44
 
@@ -22,7 +22,10 @@ export type RemoteJWKSCollectorOptions = {
22
22
  export class RemoteJWKSCollector implements KeyCollector {
23
23
  private url: URL;
24
24
 
25
- constructor(url: string, protected options?: RemoteJWKSCollectorOptions) {
25
+ constructor(
26
+ url: string,
27
+ protected options?: RemoteJWKSCollectorOptions
28
+ ) {
26
29
  try {
27
30
  this.url = new URL(url);
28
31
  } catch (e) {
@@ -0,0 +1,31 @@
1
+ import * as jose from 'jose';
2
+ import { KeySpec, KeyOptions } from './KeySpec.js';
3
+ import { KeyCollector, KeyResult } from './KeyCollector.js';
4
+
5
+ const SUPABASE_KEY_OPTIONS: KeyOptions = {
6
+ requiresAudience: ['authenticated'],
7
+ maxLifetimeSeconds: 86400 * 7 + 1200 // 1 week + 20 minutes margin
8
+ };
9
+
10
+ /**
11
+ * Set of static keys for Supabase.
12
+ *
13
+ * Same as StaticKeyCollector, but with some configuration tweaks for Supabase.
14
+ *
15
+ * Similar to SupabaseKeyCollector, but using hardcoded keys instead of fetching
16
+ * from the database.
17
+ *
18
+ * A key can be added both with and without a kid, in case wildcard matching is desired.
19
+ */
20
+ export class StaticSupabaseKeyCollector implements KeyCollector {
21
+ static async importKeys(keys: jose.JWK[]) {
22
+ const parsedKeys = await Promise.all(keys.map((key) => KeySpec.importKey(key, SUPABASE_KEY_OPTIONS)));
23
+ return new StaticSupabaseKeyCollector(parsedKeys);
24
+ }
25
+
26
+ constructor(private keys: KeySpec[]) {}
27
+
28
+ async getKeys(): Promise<KeyResult> {
29
+ return { keys: this.keys, errors: [] };
30
+ }
31
+ }
@@ -7,4 +7,4 @@ export * from './KeyStore.js';
7
7
  export * from './LeakyBucket.js';
8
8
  export * from './RemoteJWKSCollector.js';
9
9
  export * from './StaticKeyCollector.js';
10
- export * from './SupabaseKeyCollector.js';
10
+ export * from './StaticSupabaseKeyCollector.js';
package/src/db/mongo.ts CHANGED
@@ -2,6 +2,7 @@ import * as mongo from 'mongodb';
2
2
  import * as timers from 'timers/promises';
3
3
 
4
4
  import { configFile } from '@powersync/service-types';
5
+ import { normalizeMongoConfig } from '../storage/storage-index.js';
5
6
 
6
7
  /**
7
8
  * Time for new connection to timeout.
@@ -30,10 +31,11 @@ export const MONGO_OPERATION_TIMEOUT_MS = 30_000;
30
31
  export const MONGO_CLEAR_OPERATION_TIMEOUT_MS = 5_000;
31
32
 
32
33
  export function createMongoClient(config: configFile.PowerSyncConfig['storage']) {
33
- return new mongo.MongoClient(config.uri, {
34
+ const normalized = normalizeMongoConfig(config);
35
+ return new mongo.MongoClient(normalized.uri, {
34
36
  auth: {
35
- username: config.username,
36
- password: config.password
37
+ username: normalized.username,
38
+ password: normalized.password
37
39
  },
38
40
  // Time for connection to timeout
39
41
  connectTimeoutMS: MONGO_CONNECT_TIMEOUT_MS,
@@ -1,10 +1,11 @@
1
1
  import { Command } from 'commander';
2
2
 
3
+ import { logger } from '@powersync/lib-services-framework';
3
4
  import * as utils from '../util/util-index.js';
5
+ import { registerCompactAction } from './commands/compact-action.js';
4
6
  import { registerMigrationAction } from './commands/migrate-action.js';
7
+ import { registerStartAction } from './commands/start-action.js';
5
8
  import { registerTearDownAction } from './commands/teardown-action.js';
6
- import { registerCompactAction, registerStartAction } from './entry-index.js';
7
- import { logger } from '@powersync/lib-services-framework';
8
9
 
9
10
  /**
10
11
  * Generates a Commander program which serves as the entry point