@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,3 +1,4 @@
1
+ import { DisposableListener, DisposableObserverClient } from '@powersync/lib-services-framework';
1
2
  import {
2
3
  EvaluatedParameters,
3
4
  EvaluatedRow,
@@ -7,12 +8,19 @@ import {
7
8
  SqliteRow,
8
9
  ToastableSqliteRow
9
10
  } from '@powersync/service-sync-rules';
10
-
11
- import * as replication from '../replication/replication-index.js';
12
11
  import * as util from '../util/util-index.js';
12
+ import { ReplicationEventPayload } from './ReplicationEventPayload.js';
13
+ import { SourceEntityDescriptor } from './SourceEntity.js';
13
14
  import { SourceTable } from './SourceTable.js';
15
+ import { BatchedCustomWriteCheckpointOptions, ReplicaId } from './storage-index.js';
16
+ import { SyncStorageWriteCheckpointAPI } from './WriteCheckpointAPI.js';
17
+
18
+ export interface BucketStorageFactoryListener extends DisposableListener {
19
+ syncStorageCreated: (storage: SyncRulesBucketStorage) => void;
20
+ replicationEvent: (event: ReplicationEventPayload) => void;
21
+ }
14
22
 
15
- export interface BucketStorageFactory {
23
+ export interface BucketStorageFactory extends DisposableObserverClient<BucketStorageFactoryListener> {
16
24
  /**
17
25
  * Update sync rules from configuration, if changed.
18
26
  */
@@ -24,7 +32,7 @@ export interface BucketStorageFactory {
24
32
  /**
25
33
  * Get a storage instance to query sync data for specific sync rules.
26
34
  */
27
- getInstance(options: PersistedSyncRules): SyncRulesBucketStorage;
35
+ getInstance(options: PersistedSyncRulesContent): SyncRulesBucketStorage;
28
36
 
29
37
  /**
30
38
  * Deploy new sync rules.
@@ -48,7 +56,7 @@ export interface BucketStorageFactory {
48
56
  /**
49
57
  * Get the sync rules used for querying.
50
58
  */
51
- getActiveSyncRules(): Promise<PersistedSyncRules | null>;
59
+ getActiveSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null>;
52
60
 
53
61
  /**
54
62
  * Get the sync rules used for querying.
@@ -58,7 +66,7 @@ export interface BucketStorageFactory {
58
66
  /**
59
67
  * Get the sync rules that will be active next once done with initial replicatino.
60
68
  */
61
- getNextSyncRules(): Promise<PersistedSyncRules | null>;
69
+ getNextSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null>;
62
70
 
63
71
  /**
64
72
  * Get the sync rules that will be active next once done with initial replicatino.
@@ -81,10 +89,9 @@ export interface BucketStorageFactory {
81
89
  */
82
90
  getActiveCheckpoint(): Promise<ActiveCheckpoint>;
83
91
 
84
- createWriteCheckpoint(user_id: string, lsns: Record<string, string>): Promise<bigint>;
85
-
86
- lastWriteCheckpoint(user_id: string, lsn: string): Promise<bigint | null>;
87
-
92
+ /**
93
+ * Yields the latest user write checkpoint whenever the sync checkpoint updates.
94
+ */
88
95
  watchWriteCheckpoint(user_id: string, signal: AbortSignal): AsyncIterable<WriteCheckpoint>;
89
96
 
90
97
  /**
@@ -98,20 +105,22 @@ export interface BucketStorageFactory {
98
105
  getPowerSyncInstanceId(): Promise<string>;
99
106
  }
100
107
 
101
- export interface WriteCheckpoint {
102
- base: ActiveCheckpoint;
103
- writeCheckpoint: bigint | null;
104
- }
105
-
106
- export interface ActiveCheckpoint {
108
+ export interface ReplicationCheckpoint {
107
109
  readonly checkpoint: util.OpId;
108
- readonly lsn: string;
110
+ readonly lsn: string | null;
111
+ }
109
112
 
113
+ export interface ActiveCheckpoint extends ReplicationCheckpoint {
110
114
  hasSyncRules(): boolean;
111
115
 
112
116
  getBucketStorage(): Promise<SyncRulesBucketStorage | null>;
113
117
  }
114
118
 
119
+ export interface WriteCheckpoint {
120
+ base: ActiveCheckpoint;
121
+ writeCheckpoint: bigint | null;
122
+ }
123
+
115
124
  export interface StorageMetrics {
116
125
  /**
117
126
  * Size of operations (bucket_data)
@@ -131,6 +140,10 @@ export interface StorageMetrics {
131
140
  replication_size_bytes: number;
132
141
  }
133
142
 
143
+ export interface ParseSyncRulesOptions {
144
+ defaultSchema: string;
145
+ }
146
+
134
147
  export interface PersistedSyncRulesContent {
135
148
  readonly id: number;
136
149
  readonly sync_rules_content: string;
@@ -140,7 +153,7 @@ export interface PersistedSyncRulesContent {
140
153
  readonly last_keepalive_ts?: Date | null;
141
154
  readonly last_checkpoint_ts?: Date | null;
142
155
 
143
- parsed(): PersistedSyncRules;
156
+ parsed(options: ParseSyncRulesOptions): PersistedSyncRules;
144
157
 
145
158
  lock(): Promise<ReplicationLock>;
146
159
  }
@@ -157,18 +170,6 @@ export interface PersistedSyncRules {
157
170
  readonly slot_name: string;
158
171
  }
159
172
 
160
- export class DefaultPersistedSyncRules implements PersistedSyncRules {
161
- public readonly checkpoint_lsn: string | null;
162
-
163
- constructor(public readonly id: number, public readonly sync_rules: SqlSyncRules, checkpoint_lsn: string | null) {
164
- this.checkpoint_lsn = checkpoint_lsn;
165
- }
166
-
167
- get slot_name(): string {
168
- return `powersync_${this.id}`;
169
- }
170
- }
171
-
172
173
  export interface UpdateSyncRulesOptions {
173
174
  content: string;
174
175
  lock?: boolean;
@@ -198,8 +199,27 @@ export interface BucketDataBatchOptions {
198
199
  chunkLimitBytes?: number;
199
200
  }
200
201
 
201
- export interface SyncRulesBucketStorage {
202
- readonly sync_rules: SqlSyncRules;
202
+ export interface StartBatchOptions extends ParseSyncRulesOptions {
203
+ zeroLSN: string;
204
+ /**
205
+ * Whether or not to store a copy of the current data.
206
+ *
207
+ * This is needed if we need to apply partial updates, for example
208
+ * when we get TOAST values from Postgres.
209
+ *
210
+ * This is not needed when we get the full document from the source
211
+ * database, for example from MongoDB.
212
+ */
213
+ storeCurrentData: boolean;
214
+ }
215
+
216
+ export interface SyncRulesBucketStorageListener extends DisposableListener {
217
+ batchStarted: (batch: BucketStorageBatch) => void;
218
+ }
219
+
220
+ export interface SyncRulesBucketStorage
221
+ extends DisposableObserverClient<SyncRulesBucketStorageListener>,
222
+ SyncStorageWriteCheckpointAPI {
203
223
  readonly group_id: number;
204
224
  readonly slot_name: string;
205
225
 
@@ -207,9 +227,14 @@ export interface SyncRulesBucketStorage {
207
227
 
208
228
  resolveTable(options: ResolveTableOptions): Promise<ResolveTableResult>;
209
229
 
210
- startBatch(options: {}, callback: (batch: BucketStorageBatch) => Promise<void>): Promise<FlushedResult | null>;
230
+ startBatch(
231
+ options: StartBatchOptions,
232
+ callback: (batch: BucketStorageBatch) => Promise<void>
233
+ ): Promise<FlushedResult | null>;
234
+
235
+ getCheckpoint(): Promise<ReplicationCheckpoint>;
211
236
 
212
- getCheckpoint(): Promise<{ checkpoint: util.OpId; lsn: string }>;
237
+ getParsedSyncRules(options: ParseSyncRulesOptions): SqlSyncRules;
213
238
 
214
239
  getParameterSets(checkpoint: util.OpId, lookups: SqliteJsonValue[][]): Promise<SqliteJsonRow[]>;
215
240
 
@@ -244,7 +269,7 @@ export interface SyncRulesBucketStorage {
244
269
  *
245
270
  * Must only be called on stopped sync rules.
246
271
  */
247
- terminate(): Promise<void>;
272
+ terminate(options?: TerminateOptions): Promise<void>;
248
273
 
249
274
  getStatus(): Promise<SyncRuleStatus>;
250
275
 
@@ -277,7 +302,7 @@ export interface ResolveTableOptions {
277
302
  group_id: number;
278
303
  connection_id: number;
279
304
  connection_tag: string;
280
- relation: replication.PgRelation;
305
+ entity_descriptor: SourceEntityDescriptor;
281
306
 
282
307
  sync_rules: SqlSyncRules;
283
308
  }
@@ -291,7 +316,11 @@ export interface FlushedResult {
291
316
  flushed_op: string;
292
317
  }
293
318
 
294
- export interface BucketStorageBatch {
319
+ export interface BucketBatchStorageListener extends DisposableListener {
320
+ replicationEvent: (payload: ReplicationEventPayload) => void;
321
+ }
322
+
323
+ export interface BucketStorageBatch extends DisposableObserverClient<BucketBatchStorageListener> {
295
324
  /**
296
325
  * Save an op, and potentially flush.
297
326
  *
@@ -337,7 +366,17 @@ export interface BucketStorageBatch {
337
366
  */
338
367
  keepalive(lsn: string): Promise<boolean>;
339
368
 
369
+ /**
370
+ * Get the last checkpoint LSN, from either commit or keepalive.
371
+ */
372
+ lastCheckpointLsn: string | null;
373
+
340
374
  markSnapshotDone(tables: SourceTable[], no_checkpoint_before_lsn: string): Promise<SourceTable[]>;
375
+
376
+ /**
377
+ * Queues the creation of a custom Write Checkpoint. This will be persisted after operations are flushed.
378
+ */
379
+ addCustomWriteCheckpoint(checkpoint: BatchedCustomWriteCheckpointOptions): void;
341
380
  }
342
381
 
343
382
  export interface SaveParameterData {
@@ -355,23 +394,34 @@ export interface SaveBucketData {
355
394
  evaluated: EvaluatedRow[];
356
395
  }
357
396
 
397
+ export type SaveOp = 'insert' | 'update' | 'delete';
398
+
358
399
  export type SaveOptions = SaveInsert | SaveUpdate | SaveDelete;
359
400
 
401
+ export enum SaveOperationTag {
402
+ INSERT = 'insert',
403
+ UPDATE = 'update',
404
+ DELETE = 'delete'
405
+ }
406
+
360
407
  export interface SaveInsert {
361
- tag: 'insert';
408
+ tag: SaveOperationTag.INSERT;
362
409
  sourceTable: SourceTable;
363
410
  before?: undefined;
411
+ beforeReplicaId?: undefined;
364
412
  after: SqliteRow;
413
+ afterReplicaId: ReplicaId;
365
414
  }
366
415
 
367
416
  export interface SaveUpdate {
368
- tag: 'update';
417
+ tag: SaveOperationTag.UPDATE;
369
418
  sourceTable: SourceTable;
370
419
 
371
420
  /**
372
421
  * This is only present when the id has changed, and will only contain replica identity columns.
373
422
  */
374
423
  before?: SqliteRow;
424
+ beforeReplicaId?: ReplicaId;
375
425
 
376
426
  /**
377
427
  * A null value means null column.
@@ -379,13 +429,16 @@ export interface SaveUpdate {
379
429
  * An undefined value means it's a TOAST value - must be copied from another record.
380
430
  */
381
431
  after: ToastableSqliteRow;
432
+ afterReplicaId: ReplicaId;
382
433
  }
383
434
 
384
435
  export interface SaveDelete {
385
- tag: 'delete';
436
+ tag: SaveOperationTag.DELETE;
386
437
  sourceTable: SourceTable;
387
- before: SqliteRow;
438
+ before?: SqliteRow;
439
+ beforeReplicaId: ReplicaId;
388
440
  after?: undefined;
441
+ afterReplicaId?: undefined;
389
442
  }
390
443
 
391
444
  export interface SyncBucketDataBatch {
@@ -429,6 +482,15 @@ export interface CompactOptions {
429
482
  * If specified, compact only the specific buckets.
430
483
  *
431
484
  * If not specified, compacts all buckets.
485
+ *
486
+ * These can be individual bucket names, or bucket definition names.
432
487
  */
433
488
  compactBuckets?: string[];
434
489
  }
490
+
491
+ export interface TerminateOptions {
492
+ /**
493
+ * If true, also clear the storage before terminating.
494
+ */
495
+ clearStorage: boolean;
496
+ }
@@ -1,36 +1,39 @@
1
- import * as mongo from 'mongodb';
2
- import * as timers from 'timers/promises';
3
- import { LRUCache } from 'lru-cache/min';
4
1
  import { SqlSyncRules } from '@powersync/service-sync-rules';
5
2
  import { wrapWithAbort } from 'ix/asynciterable/operators/withabort.js';
3
+ import { LRUCache } from 'lru-cache/min';
4
+ import * as mongo from 'mongodb';
5
+ import * as timers from 'timers/promises';
6
6
 
7
- import * as replication from '../replication/replication-index.js';
7
+ import * as locks from '../locks/locks-index.js';
8
8
  import * as sync from '../sync/sync-index.js';
9
9
  import * as util from '../util/util-index.js';
10
- import * as locks from '../locks/locks-index.js';
11
10
 
11
+ import { DisposableObserver, logger } from '@powersync/lib-services-framework';
12
+ import { v4 as uuid } from 'uuid';
12
13
  import {
13
14
  ActiveCheckpoint,
14
15
  BucketStorageFactory,
16
+ BucketStorageFactoryListener,
17
+ ParseSyncRulesOptions,
15
18
  PersistedSyncRules,
16
19
  PersistedSyncRulesContent,
17
20
  StorageMetrics,
18
21
  UpdateSyncRulesOptions,
19
22
  WriteCheckpoint
20
23
  } from './BucketStorage.js';
24
+ import { PowerSyncMongo } from './mongo/db.js';
25
+ import { SyncRuleDocument, SyncRuleState } from './mongo/models.js';
21
26
  import { MongoPersistedSyncRulesContent } from './mongo/MongoPersistedSyncRulesContent.js';
22
27
  import { MongoSyncBucketStorage } from './mongo/MongoSyncBucketStorage.js';
23
- import { PowerSyncMongo, PowerSyncMongoOptions } from './mongo/db.js';
24
- import { SyncRuleDocument, SyncRuleState } from './mongo/models.js';
25
28
  import { generateSlotName } from './mongo/util.js';
26
- import { v4 as uuid } from 'uuid';
27
- import { logger } from '@powersync/lib-services-framework';
28
-
29
- export interface MongoBucketStorageOptions extends PowerSyncMongoOptions {}
30
29
 
31
- export class MongoBucketStorage implements BucketStorageFactory {
30
+ export class MongoBucketStorage
31
+ extends DisposableObserver<BucketStorageFactoryListener>
32
+ implements BucketStorageFactory
33
+ {
32
34
  private readonly client: mongo.MongoClient;
33
35
  private readonly session: mongo.ClientSession;
36
+ // TODO: This is still Postgres specific and needs to be reworked
34
37
  public readonly slot_name_prefix: string;
35
38
 
36
39
  private readonly storageCache = new LRUCache<number, MongoSyncBucketStorage>({
@@ -47,26 +50,44 @@ export class MongoBucketStorage implements BucketStorageFactory {
47
50
  return undefined;
48
51
  }
49
52
  const rules = new MongoPersistedSyncRulesContent(this.db, doc2);
50
- const storage = this.getInstance(rules.parsed());
51
- return storage;
53
+ return this.getInstance(rules);
54
+ },
55
+ dispose: (storage) => {
56
+ storage[Symbol.dispose]();
52
57
  }
53
58
  });
54
59
 
55
60
  public readonly db: PowerSyncMongo;
56
61
 
57
- constructor(db: PowerSyncMongo, options: { slot_name_prefix: string }) {
62
+ constructor(
63
+ db: PowerSyncMongo,
64
+ options: {
65
+ slot_name_prefix: string;
66
+ }
67
+ ) {
68
+ super();
58
69
  this.client = db.client;
59
70
  this.db = db;
60
71
  this.session = this.client.startSession();
61
72
  this.slot_name_prefix = options.slot_name_prefix;
62
73
  }
63
74
 
64
- getInstance(options: PersistedSyncRules): MongoSyncBucketStorage {
65
- let { id, sync_rules, slot_name } = options;
75
+ getInstance(options: PersistedSyncRulesContent): MongoSyncBucketStorage {
76
+ let { id, slot_name } = options;
66
77
  if ((typeof id as any) == 'bigint') {
67
78
  id = Number(id);
68
79
  }
69
- return new MongoSyncBucketStorage(this, id, sync_rules, slot_name);
80
+ const storage = new MongoSyncBucketStorage(this, id, options, slot_name);
81
+ this.iterateListeners((cb) => cb.syncStorageCreated?.(storage));
82
+ storage.registerListener({
83
+ batchStarted: (batch) => {
84
+ // This nested listener will be automatically disposed when the storage is disposed
85
+ batch.registerManagedListener(storage, {
86
+ replicationEvent: (payload) => this.iterateListeners((cb) => cb.replicationEvent?.(payload))
87
+ });
88
+ }
89
+ });
90
+ return storage;
70
91
  }
71
92
 
72
93
  async configureSyncRules(sync_rules: string, options?: { lock?: boolean }) {
@@ -136,7 +157,12 @@ export class MongoBucketStorage implements BucketStorageFactory {
136
157
 
137
158
  async updateSyncRules(options: UpdateSyncRulesOptions): Promise<MongoPersistedSyncRulesContent> {
138
159
  // Parse and validate before applying any changes
139
- const parsed = SqlSyncRules.fromYaml(options.content);
160
+ const parsed = SqlSyncRules.fromYaml(options.content, {
161
+ // No schema-based validation at this point
162
+ schema: undefined,
163
+ defaultSchema: 'not_applicable', // Not needed for validation
164
+ throwOnError: true
165
+ });
140
166
 
141
167
  let rules: MongoPersistedSyncRulesContent | undefined = undefined;
142
168
 
@@ -204,9 +230,9 @@ export class MongoBucketStorage implements BucketStorageFactory {
204
230
  return new MongoPersistedSyncRulesContent(this.db, doc);
205
231
  }
206
232
 
207
- async getActiveSyncRules(): Promise<PersistedSyncRules | null> {
233
+ async getActiveSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null> {
208
234
  const content = await this.getActiveSyncRulesContent();
209
- return content?.parsed() ?? null;
235
+ return content?.parsed(options) ?? null;
210
236
  }
211
237
 
212
238
  async getNextSyncRulesContent(): Promise<MongoPersistedSyncRulesContent | null> {
@@ -223,9 +249,9 @@ export class MongoBucketStorage implements BucketStorageFactory {
223
249
  return new MongoPersistedSyncRulesContent(this.db, doc);
224
250
  }
225
251
 
226
- async getNextSyncRules(): Promise<PersistedSyncRules | null> {
252
+ async getNextSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null> {
227
253
  const content = await this.getNextSyncRulesContent();
228
- return content?.parsed() ?? null;
254
+ return content?.parsed(options) ?? null;
229
255
  }
230
256
 
231
257
  async getReplicatingSyncRules(): Promise<PersistedSyncRulesContent[]> {
@@ -252,32 +278,6 @@ export class MongoBucketStorage implements BucketStorageFactory {
252
278
  });
253
279
  }
254
280
 
255
- async createWriteCheckpoint(user_id: string, lsns: Record<string, string>): Promise<bigint> {
256
- const doc = await this.db.write_checkpoints.findOneAndUpdate(
257
- {
258
- user_id: user_id
259
- },
260
- {
261
- $set: {
262
- lsns: lsns
263
- },
264
- $inc: {
265
- client_id: 1n
266
- }
267
- },
268
- { upsert: true, returnDocument: 'after' }
269
- );
270
- return doc!.client_id;
271
- }
272
-
273
- async lastWriteCheckpoint(user_id: string, lsn: string): Promise<bigint | null> {
274
- const lastWriteCheckpoint = await this.db.write_checkpoints.findOne({
275
- user_id: user_id,
276
- 'lsns.1': { $lte: lsn }
277
- });
278
- return lastWriteCheckpoint?.client_id ?? null;
279
- }
280
-
281
281
  async getActiveCheckpoint(): Promise<ActiveCheckpoint> {
282
282
  const doc = await this.db.sync_rules.findOne(
283
283
  {
@@ -303,7 +303,7 @@ export class MongoBucketStorage implements BucketStorageFactory {
303
303
  }
304
304
  };
305
305
 
306
- const active_sync_rules = await this.getActiveSyncRules();
306
+ const active_sync_rules = await this.getActiveSyncRules({ defaultSchema: 'public' });
307
307
  if (active_sync_rules == null) {
308
308
  return {
309
309
  operations_size_bytes: 0,
@@ -379,7 +379,7 @@ export class MongoBucketStorage implements BucketStorageFactory {
379
379
  private makeActiveCheckpoint(doc: SyncRuleDocument | null) {
380
380
  return {
381
381
  checkpoint: util.timestampToOpId(doc?.last_checkpoint ?? 0n),
382
- lsn: doc?.last_checkpoint_lsn ?? replication.ZERO_LSN,
382
+ lsn: doc?.last_checkpoint_lsn ?? null,
383
383
  hasSyncRules() {
384
384
  return doc != null;
385
385
  },
@@ -389,7 +389,7 @@ export class MongoBucketStorage implements BucketStorageFactory {
389
389
  }
390
390
  return (await this.storageCache.fetch(doc._id)) ?? null;
391
391
  }
392
- };
392
+ } satisfies ActiveCheckpoint;
393
393
  }
394
394
 
395
395
  /**
@@ -479,6 +479,7 @@ export class MongoBucketStorage implements BucketStorageFactory {
479
479
  if (doc == null) {
480
480
  continue;
481
481
  }
482
+
482
483
  const op = this.makeActiveCheckpoint(doc);
483
484
  // Check for LSN / checkpoint changes - ignore other metadata changes
484
485
  if (lastOp == null || op.lsn != lastOp.lsn || op.checkpoint != lastOp.checkpoint) {
@@ -508,8 +509,19 @@ export class MongoBucketStorage implements BucketStorageFactory {
508
509
  // What is important is:
509
510
  // 1. checkpoint (op_id) changes.
510
511
  // 2. write checkpoint changes for the specific user
512
+ const bucketStorage = await cp.getBucketStorage();
513
+ if (!bucketStorage) {
514
+ continue;
515
+ }
516
+
517
+ const lsnFilters: Record<string, string> = lsn ? { 1: lsn } : {};
511
518
 
512
- const currentWriteCheckpoint = await this.lastWriteCheckpoint(user_id, lsn ?? '');
519
+ const currentWriteCheckpoint = await bucketStorage.lastWriteCheckpoint({
520
+ user_id,
521
+ heads: {
522
+ ...lsnFilters
523
+ }
524
+ });
513
525
 
514
526
  if (currentWriteCheckpoint == lastWriteCheckpoint && checkpoint == lastCheckpoint) {
515
527
  // No change - wait for next one
@@ -0,0 +1,16 @@
1
+ import * as sync_rules from '@powersync/service-sync-rules';
2
+ import { BucketStorageBatch, SaveOp } from './BucketStorage.js';
3
+ import { SourceTable } from './SourceTable.js';
4
+
5
+ export type EventData = {
6
+ op: SaveOp;
7
+ before?: sync_rules.SqliteRow;
8
+ after?: sync_rules.SqliteRow;
9
+ };
10
+
11
+ export type ReplicationEventPayload = {
12
+ batch: BucketStorageBatch;
13
+ data: EventData;
14
+ event: sync_rules.SqlEventDescriptor;
15
+ table: SourceTable;
16
+ };
@@ -0,0 +1,22 @@
1
+ export interface ColumnDescriptor {
2
+ name: string;
3
+ /**
4
+ * The type of the column ie VARCHAR, INT, etc
5
+ */
6
+ type?: string;
7
+ /**
8
+ * Some data sources have a type id that can be used to identify the type of the column
9
+ */
10
+ typeId?: number;
11
+ }
12
+
13
+ // TODO: This needs to be consolidated with SourceTable into something new.
14
+ export interface SourceEntityDescriptor {
15
+ /**
16
+ * The internal id of the data source structure in the database
17
+ */
18
+ objectId: number | string;
19
+ schema: string;
20
+ name: string;
21
+ replicationColumns: ColumnDescriptor[];
22
+ }
@@ -1,10 +1,8 @@
1
- import { DEFAULT_SCHEMA, DEFAULT_TAG } from '@powersync/service-sync-rules';
2
-
3
- import * as replication from '../replication/replication-index.js';
1
+ import { DEFAULT_TAG } from '@powersync/service-sync-rules';
4
2
  import * as util from '../util/util-index.js';
3
+ import { ColumnDescriptor } from './SourceEntity.js';
5
4
 
6
5
  export class SourceTable {
7
- static readonly DEFAULT_SCHEMA = DEFAULT_SCHEMA;
8
6
  static readonly DEFAULT_TAG = DEFAULT_TAG;
9
7
 
10
8
  /**
@@ -25,14 +23,23 @@ export class SourceTable {
25
23
  */
26
24
  public syncParameters = true;
27
25
 
26
+ /**
27
+ * True if the table is used in sync rules for events.
28
+ *
29
+ * This value is resolved externally, and cached here.
30
+ *
31
+ * Defaults to true for tests.
32
+ */
33
+ public syncEvent = true;
34
+
28
35
  constructor(
29
36
  public readonly id: any,
30
37
  public readonly connectionTag: string,
31
- public readonly relationId: number,
38
+ public readonly objectId: number | string,
32
39
  public readonly schema: string,
33
40
  public readonly table: string,
34
41
 
35
- public readonly replicaIdColumns: replication.ReplicationColumn[],
42
+ public readonly replicaIdColumns: ColumnDescriptor[],
36
43
  public readonly snapshotComplete: boolean
37
44
  ) {}
38
45
 
@@ -55,6 +62,6 @@ export class SourceTable {
55
62
  }
56
63
 
57
64
  get syncAny() {
58
- return this.syncData || this.syncParameters;
65
+ return this.syncData || this.syncParameters || this.syncEvent;
59
66
  }
60
67
  }
@@ -0,0 +1,62 @@
1
+ import { DisposableListener, DisposableObserver, logger } from '@powersync/lib-services-framework';
2
+ import { ResolvedPowerSyncConfig } from '../util/util-index.js';
3
+ import { BucketStorageFactory } from './BucketStorage.js';
4
+ import { ActiveStorage, BucketStorageProvider } from './StorageProvider.js';
5
+
6
+ export type StorageEngineOptions = {
7
+ configuration: ResolvedPowerSyncConfig;
8
+ };
9
+
10
+ export interface StorageEngineListener extends DisposableListener {
11
+ storageActivated: (storage: BucketStorageFactory) => void;
12
+ }
13
+
14
+ export class StorageEngine extends DisposableObserver<StorageEngineListener> {
15
+ // TODO: This will need to revisited when we actually support multiple storage providers.
16
+ private storageProviders: Map<string, BucketStorageProvider> = new Map();
17
+ private currentActiveStorage: ActiveStorage | null = null;
18
+
19
+ constructor(private options: StorageEngineOptions) {
20
+ super();
21
+ }
22
+
23
+ get activeBucketStorage(): BucketStorageFactory {
24
+ return this.activeStorage.storage;
25
+ }
26
+
27
+ get activeStorage(): ActiveStorage {
28
+ if (!this.currentActiveStorage) {
29
+ throw new Error(`No storage provider has been initialized yet.`);
30
+ }
31
+
32
+ return this.currentActiveStorage;
33
+ }
34
+
35
+ /**
36
+ * Register a provider which generates a {@link BucketStorageFactory}
37
+ * given the matching config specified in the loaded {@link ResolvedPowerSyncConfig}
38
+ */
39
+ registerProvider(provider: BucketStorageProvider) {
40
+ this.storageProviders.set(provider.type, provider);
41
+ }
42
+
43
+ public async start(): Promise<void> {
44
+ logger.info('Starting Storage Engine...');
45
+ const { configuration } = this.options;
46
+ this.currentActiveStorage = await this.storageProviders.get(configuration.storage.type)!.getStorage({
47
+ resolvedConfig: configuration
48
+ });
49
+ this.iterateListeners((cb) => cb.storageActivated?.(this.activeBucketStorage));
50
+ logger.info(`Successfully activated storage: ${configuration.storage.type}.`);
51
+ logger.info('Successfully started Storage Engine.');
52
+ }
53
+
54
+ /**
55
+ * Shutdown the storage engine, safely shutting down any activated storage providers.
56
+ */
57
+ public async shutDown(): Promise<void> {
58
+ logger.info('Shutting down Storage Engine...');
59
+ await this.currentActiveStorage?.shutDown();
60
+ logger.info('Successfully shut down Storage Engine.');
61
+ }
62
+ }