@powersync/service-core 0.8.7 → 0.9.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 (377) hide show
  1. package/CHANGELOG.md +37 -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/auth-index.d.ts +0 -1
  23. package/dist/auth/auth-index.js +0 -1
  24. package/dist/auth/auth-index.js.map +1 -1
  25. package/dist/db/mongo.js +5 -3
  26. package/dist/db/mongo.js.map +1 -1
  27. package/dist/entry/cli-entry.js +3 -2
  28. package/dist/entry/cli-entry.js.map +1 -1
  29. package/dist/entry/commands/compact-action.js +90 -14
  30. package/dist/entry/commands/compact-action.js.map +1 -1
  31. package/dist/entry/commands/migrate-action.js +4 -5
  32. package/dist/entry/commands/migrate-action.js.map +1 -1
  33. package/dist/entry/commands/teardown-action.js +2 -2
  34. package/dist/entry/commands/teardown-action.js.map +1 -1
  35. package/dist/index.d.ts +4 -2
  36. package/dist/index.js +4 -2
  37. package/dist/index.js.map +1 -1
  38. package/dist/locks/MongoLocks.js.map +1 -1
  39. package/dist/metrics/Metrics.d.ts +2 -2
  40. package/dist/metrics/Metrics.js +5 -13
  41. package/dist/metrics/Metrics.js.map +1 -1
  42. package/dist/migrations/db/migrations/1684951997326-init.d.ts +2 -2
  43. package/dist/migrations/db/migrations/1684951997326-init.js +4 -2
  44. package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
  45. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +2 -2
  46. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +4 -2
  47. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
  48. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +2 -2
  49. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +4 -2
  50. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
  51. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.d.ts +3 -0
  52. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js +31 -0
  53. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js.map +1 -0
  54. package/dist/migrations/executor.js.map +1 -1
  55. package/dist/migrations/migrations.d.ts +8 -0
  56. package/dist/migrations/migrations.js +19 -7
  57. package/dist/migrations/migrations.js.map +1 -1
  58. package/dist/migrations/store/migration-store.js.map +1 -1
  59. package/dist/modules/AbstractModule.d.ts +26 -0
  60. package/dist/modules/AbstractModule.js +11 -0
  61. package/dist/modules/AbstractModule.js.map +1 -0
  62. package/dist/modules/ModuleManager.d.ts +11 -0
  63. package/dist/modules/ModuleManager.js +32 -0
  64. package/dist/modules/ModuleManager.js.map +1 -0
  65. package/dist/modules/modules-index.d.ts +2 -0
  66. package/dist/modules/modules-index.js +3 -0
  67. package/dist/modules/modules-index.js.map +1 -0
  68. package/dist/replication/AbstractReplicationJob.d.ts +37 -0
  69. package/dist/replication/AbstractReplicationJob.js +51 -0
  70. package/dist/replication/AbstractReplicationJob.js.map +1 -0
  71. package/dist/replication/AbstractReplicator.d.ts +53 -0
  72. package/dist/replication/AbstractReplicator.js +250 -0
  73. package/dist/replication/AbstractReplicator.js.map +1 -0
  74. package/dist/replication/ErrorRateLimiter.d.ts +0 -10
  75. package/dist/replication/ErrorRateLimiter.js +1 -42
  76. package/dist/replication/ErrorRateLimiter.js.map +1 -1
  77. package/dist/replication/ReplicationEngine.d.ts +18 -0
  78. package/dist/replication/ReplicationEngine.js +41 -0
  79. package/dist/replication/ReplicationEngine.js.map +1 -0
  80. package/dist/replication/ReplicationModule.d.ts +51 -0
  81. package/dist/replication/ReplicationModule.js +68 -0
  82. package/dist/replication/ReplicationModule.js.map +1 -0
  83. package/dist/replication/replication-index.d.ts +4 -6
  84. package/dist/replication/replication-index.js +4 -6
  85. package/dist/replication/replication-index.js.map +1 -1
  86. package/dist/routes/RouterEngine.d.ts +42 -0
  87. package/dist/routes/RouterEngine.js +80 -0
  88. package/dist/routes/RouterEngine.js.map +1 -0
  89. package/dist/routes/auth.d.ts +2 -2
  90. package/dist/routes/auth.js +11 -11
  91. package/dist/routes/auth.js.map +1 -1
  92. package/dist/routes/configure-fastify.d.ts +37 -7
  93. package/dist/routes/configure-fastify.js +20 -19
  94. package/dist/routes/configure-fastify.js.map +1 -1
  95. package/dist/routes/configure-rsocket.d.ts +3 -4
  96. package/dist/routes/configure-rsocket.js +7 -4
  97. package/dist/routes/configure-rsocket.js.map +1 -1
  98. package/dist/routes/endpoints/admin.d.ts +30 -0
  99. package/dist/routes/endpoints/admin.js +46 -67
  100. package/dist/routes/endpoints/admin.js.map +1 -1
  101. package/dist/routes/endpoints/checkpointing.js +103 -15
  102. package/dist/routes/endpoints/checkpointing.js.map +1 -1
  103. package/dist/routes/endpoints/probes.d.ts +74 -0
  104. package/dist/routes/endpoints/probes.js +51 -0
  105. package/dist/routes/endpoints/probes.js.map +1 -0
  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 +11 -4
  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 +16 -24
  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/auth-index.ts +0 -1
  240. package/src/db/mongo.ts +5 -3
  241. package/src/entry/cli-entry.ts +3 -2
  242. package/src/entry/commands/compact-action.ts +24 -12
  243. package/src/entry/commands/migrate-action.ts +5 -8
  244. package/src/entry/commands/teardown-action.ts +2 -2
  245. package/src/index.ts +5 -2
  246. package/src/metrics/Metrics.ts +6 -16
  247. package/src/migrations/db/migrations/1684951997326-init.ts +9 -4
  248. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -4
  249. package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +6 -4
  250. package/src/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.ts +37 -0
  251. package/src/migrations/migrations.ts +24 -8
  252. package/src/modules/AbstractModule.ts +37 -0
  253. package/src/modules/ModuleManager.ts +34 -0
  254. package/src/modules/modules-index.ts +2 -0
  255. package/src/replication/AbstractReplicationJob.ts +79 -0
  256. package/src/replication/AbstractReplicator.ts +228 -0
  257. package/src/replication/ErrorRateLimiter.ts +0 -44
  258. package/src/replication/ReplicationEngine.ts +43 -0
  259. package/src/replication/ReplicationModule.ts +122 -0
  260. package/src/replication/replication-index.ts +4 -6
  261. package/src/routes/RouterEngine.ts +120 -0
  262. package/src/routes/auth.ts +21 -12
  263. package/src/routes/configure-fastify.ts +28 -28
  264. package/src/routes/configure-rsocket.ts +13 -8
  265. package/src/routes/endpoints/admin.ts +72 -76
  266. package/src/routes/endpoints/checkpointing.ts +51 -11
  267. package/src/routes/endpoints/probes.ts +58 -0
  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 +10 -5
  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 +31 -31
  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 +235 -0
  314. package/test/src/routes/probes.test.ts +153 -0
  315. package/test/src/setup.ts +1 -1
  316. package/test/src/stream_utils.ts +42 -0
  317. package/test/src/sync.test.ts +115 -39
  318. package/test/src/util.ts +48 -51
  319. package/test/tsconfig.json +1 -1
  320. package/tsconfig.tsbuildinfo +1 -1
  321. package/vitest.config.ts +7 -1
  322. package/dist/auth/SupabaseKeyCollector.d.ts +0 -22
  323. package/dist/auth/SupabaseKeyCollector.js +0 -61
  324. package/dist/auth/SupabaseKeyCollector.js.map +0 -1
  325. package/dist/replication/PgRelation.d.ts +0 -16
  326. package/dist/replication/PgRelation.js +0 -26
  327. package/dist/replication/PgRelation.js.map +0 -1
  328. package/dist/replication/WalConnection.d.ts +0 -34
  329. package/dist/replication/WalConnection.js +0 -190
  330. package/dist/replication/WalConnection.js.map +0 -1
  331. package/dist/replication/WalStream.d.ts +0 -57
  332. package/dist/replication/WalStream.js +0 -519
  333. package/dist/replication/WalStream.js.map +0 -1
  334. package/dist/replication/WalStreamManager.d.ts +0 -30
  335. package/dist/replication/WalStreamManager.js +0 -198
  336. package/dist/replication/WalStreamManager.js.map +0 -1
  337. package/dist/replication/WalStreamRunner.d.ts +0 -38
  338. package/dist/replication/WalStreamRunner.js +0 -155
  339. package/dist/replication/WalStreamRunner.js.map +0 -1
  340. package/dist/replication/util.d.ts +0 -9
  341. package/dist/replication/util.js +0 -62
  342. package/dist/replication/util.js.map +0 -1
  343. package/dist/system/CorePowerSyncSystem.d.ts +0 -23
  344. package/dist/system/CorePowerSyncSystem.js +0 -52
  345. package/dist/system/CorePowerSyncSystem.js.map +0 -1
  346. package/dist/util/PgManager.d.ts +0 -24
  347. package/dist/util/PgManager.js +0 -55
  348. package/dist/util/PgManager.js.map +0 -1
  349. package/dist/util/migration_lib.d.ts +0 -11
  350. package/dist/util/migration_lib.js +0 -64
  351. package/dist/util/migration_lib.js.map +0 -1
  352. package/dist/util/pgwire_utils.d.ts +0 -24
  353. package/dist/util/pgwire_utils.js +0 -117
  354. package/dist/util/pgwire_utils.js.map +0 -1
  355. package/dist/util/populate_test_data.d.ts +0 -8
  356. package/dist/util/populate_test_data.js +0 -65
  357. package/dist/util/populate_test_data.js.map +0 -1
  358. package/src/auth/SupabaseKeyCollector.ts +0 -67
  359. package/src/replication/PgRelation.ts +0 -42
  360. package/src/replication/WalConnection.ts +0 -227
  361. package/src/replication/WalStream.ts +0 -631
  362. package/src/replication/WalStreamManager.ts +0 -213
  363. package/src/replication/WalStreamRunner.ts +0 -180
  364. package/src/replication/util.ts +0 -76
  365. package/src/system/CorePowerSyncSystem.ts +0 -64
  366. package/src/util/PgManager.ts +0 -64
  367. package/src/util/migration_lib.ts +0 -79
  368. package/src/util/pgwire_utils.ts +0 -139
  369. package/src/util/populate_test_data.ts +0 -78
  370. package/test/src/__snapshots__/pg_test.test.ts.snap +0 -256
  371. package/test/src/large_batch.test.ts +0 -194
  372. package/test/src/pg_test.test.ts +0 -450
  373. package/test/src/schema_changes.test.ts +0 -545
  374. package/test/src/slow_tests.test.ts +0 -338
  375. package/test/src/validation.test.ts +0 -63
  376. package/test/src/wal_stream.test.ts +0 -319
  377. package/test/src/wal_stream_utils.ts +0 -156
@@ -1,11 +1,9 @@
1
1
  import { errors, router, schema } from '@powersync/lib-services-framework';
2
- import { SqlSyncRules, SqliteValue, StaticSchema, isJsonValue, toSyncRulesValue } from '@powersync/service-sync-rules';
2
+ import { SqlSyncRules, StaticSchema } from '@powersync/service-sync-rules';
3
3
  import { internal_routes } from '@powersync/service-types';
4
4
 
5
5
  import * as api from '../../api/api-index.js';
6
- import * as util from '../../util/util-index.js';
7
-
8
- import { PersistedSyncRulesContent } from '../../storage/BucketStorage.js';
6
+ import * as storage from '../../storage/storage-index.js';
9
7
  import { authApi } from '../auth.js';
10
8
  import { routeDefinition } from '../router.js';
11
9
 
@@ -15,47 +13,27 @@ export const executeSql = routeDefinition({
15
13
  authorize: authApi,
16
14
  validator: schema.createTsCodecValidator(internal_routes.ExecuteSqlRequest, { allowAdditional: true }),
17
15
  handler: async (payload) => {
18
- const connection = payload.context.system.config.connection;
19
- if (connection == null || !connection.debug_api) {
20
- return internal_routes.ExecuteSqlResponse.encode({
21
- results: {
22
- columns: [],
23
- rows: []
24
- },
25
- success: false,
26
- error: 'SQL querying is not enabled'
27
- });
28
- }
29
-
30
- const pool = payload.context.system.requirePgPool();
31
-
32
- const { query, args } = payload.params.sql;
16
+ const {
17
+ params: {
18
+ sql: { query, args }
19
+ }
20
+ } = payload;
33
21
 
34
- try {
35
- const result = await pool.query({
36
- statement: query,
37
- params: args.map(util.autoParameter)
38
- });
22
+ const apiHandler = payload.context.service_context.routerEngine!.getAPI();
39
23
 
40
- return internal_routes.ExecuteSqlResponse.encode({
41
- success: true,
42
- results: {
43
- columns: result.columns.map((c) => c.name),
44
- rows: result.rows.map((row) => {
45
- return row.map((value) => mapColumnValue(toSyncRulesValue(value)));
46
- })
47
- }
48
- });
49
- } catch (e) {
24
+ const sourceConfig = await apiHandler.getSourceConfig();
25
+ if (!sourceConfig.debug_api) {
50
26
  return internal_routes.ExecuteSqlResponse.encode({
51
27
  results: {
52
28
  columns: [],
53
29
  rows: []
54
30
  },
55
31
  success: false,
56
- error: e.message
32
+ error: 'SQL querying is not enabled'
57
33
  });
58
34
  }
35
+
36
+ return internal_routes.ExecuteSqlResponse.encode(await apiHandler.executeQuery(query, args));
59
37
  }
60
38
  });
61
39
 
@@ -65,34 +43,45 @@ export const diagnostics = routeDefinition({
65
43
  authorize: authApi,
66
44
  validator: schema.createTsCodecValidator(internal_routes.DiagnosticsRequest, { allowAdditional: true }),
67
45
  handler: async (payload) => {
46
+ const { context } = payload;
47
+ const { service_context } = context;
68
48
  const include_content = payload.params.sync_rules_content ?? false;
69
- const system = payload.context.system;
70
49
 
71
- const status = await api.getConnectionStatus(system);
72
- if (status == null) {
50
+ const apiHandler = service_context.routerEngine!.getAPI();
51
+
52
+ const status = await apiHandler.getConnectionStatus();
53
+ if (!status) {
73
54
  return internal_routes.DiagnosticsResponse.encode({
74
55
  connections: []
75
56
  });
76
57
  }
77
58
 
78
- const { storage } = system;
79
- const active = await storage.getActiveSyncRulesContent();
80
- const next = await storage.getNextSyncRulesContent();
59
+ const {
60
+ storageEngine: { activeBucketStorage }
61
+ } = service_context;
62
+ const active = await activeBucketStorage.getActiveSyncRulesContent();
63
+ const next = await activeBucketStorage.getNextSyncRulesContent();
81
64
 
82
- const active_status = await api.getSyncRulesStatus(active, system, {
65
+ const active_status = await api.getSyncRulesStatus(activeBucketStorage, apiHandler, active, {
83
66
  include_content,
84
67
  check_connection: status.connected,
85
68
  live_status: true
86
69
  });
87
70
 
88
- const next_status = await api.getSyncRulesStatus(next, system, {
71
+ const next_status = await api.getSyncRulesStatus(activeBucketStorage, apiHandler, next, {
89
72
  include_content,
90
73
  check_connection: status.connected,
91
74
  live_status: true
92
75
  });
93
76
 
94
77
  return internal_routes.DiagnosticsResponse.encode({
95
- connections: [status],
78
+ connections: [
79
+ {
80
+ ...status,
81
+ // TODO update this in future
82
+ postgres_uri: status.uri
83
+ }
84
+ ],
96
85
  active_sync_rules: active_status,
97
86
  deploying_sync_rules: next_status
98
87
  });
@@ -105,9 +94,9 @@ export const getSchema = routeDefinition({
105
94
  authorize: authApi,
106
95
  validator: schema.createTsCodecValidator(internal_routes.GetSchemaRequest, { allowAdditional: true }),
107
96
  handler: async (payload) => {
108
- const system = payload.context.system;
97
+ const apiHandler = payload.context.service_context.routerEngine!.getAPI();
109
98
 
110
- return internal_routes.GetSchemaResponse.encode(await api.getConnectionsSchema(system));
99
+ return internal_routes.GetSchemaResponse.encode(await api.getConnectionsSchema(apiHandler));
111
100
  }
112
101
  });
113
102
 
@@ -117,15 +106,19 @@ export const reprocess = routeDefinition({
117
106
  authorize: authApi,
118
107
  validator: schema.createTsCodecValidator(internal_routes.ReprocessRequest, { allowAdditional: true }),
119
108
  handler: async (payload) => {
120
- const system = payload.context.system;
121
-
122
- const storage = system.storage;
123
- const next = await storage.getNextSyncRules();
109
+ const {
110
+ context: { service_context }
111
+ } = payload;
112
+ const {
113
+ storageEngine: { activeBucketStorage }
114
+ } = service_context;
115
+ const apiHandler = service_context.routerEngine!.getAPI();
116
+ const next = await activeBucketStorage.getNextSyncRules(apiHandler.getParseSyncRulesOptions());
124
117
  if (next != null) {
125
118
  throw new Error(`Busy processing sync rules - cannot reprocess`);
126
119
  }
127
120
 
128
- const active = await storage.getActiveSyncRules();
121
+ const active = await activeBucketStorage.getActiveSyncRules(apiHandler.getParseSyncRulesOptions());
129
122
  if (active == null) {
130
123
  throw new errors.JourneyError({
131
124
  status: 422,
@@ -134,15 +127,18 @@ export const reprocess = routeDefinition({
134
127
  });
135
128
  }
136
129
 
137
- const new_rules = await storage.updateSyncRules({
130
+ const new_rules = await activeBucketStorage.updateSyncRules({
138
131
  content: active.sync_rules.content
139
132
  });
140
133
 
134
+ const baseConfig = await apiHandler.getSourceConfig();
135
+
141
136
  return internal_routes.ReprocessResponse.encode({
142
137
  connections: [
143
138
  {
144
- tag: system.config.connection!.tag,
145
- id: system.config.connection!.id,
139
+ // Previously the connection was asserted with `!`
140
+ tag: baseConfig.tag,
141
+ id: baseConfig.id,
146
142
  slot_name: new_rules.slot_name
147
143
  }
148
144
  ]
@@ -156,14 +152,16 @@ export const validate = routeDefinition({
156
152
  authorize: authApi,
157
153
  validator: schema.createTsCodecValidator(internal_routes.ValidateRequest, { allowAdditional: true }),
158
154
  handler: async (payload) => {
159
- const system = payload.context.system;
160
-
155
+ const {
156
+ context: { service_context }
157
+ } = payload;
161
158
  const content = payload.params.sync_rules;
159
+ const apiHandler = service_context.routerEngine!.getAPI();
162
160
 
163
- const schemaData = await api.getConnectionsSchema(system);
161
+ const schemaData = await api.getConnectionsSchema(apiHandler);
164
162
  const schema = new StaticSchema(schemaData.connections);
165
163
 
166
- const sync_rules: PersistedSyncRulesContent = {
164
+ const sync_rules: storage.PersistedSyncRulesContent = {
167
165
  // Dummy values
168
166
  id: 0,
169
167
  slot_name: '',
@@ -171,7 +169,10 @@ export const validate = routeDefinition({
171
169
  parsed() {
172
170
  return {
173
171
  ...this,
174
- sync_rules: SqlSyncRules.fromYaml(content, { throwOnError: false, schema })
172
+ sync_rules: SqlSyncRules.fromYaml(content, {
173
+ ...apiHandler.getParseSyncRulesOptions(),
174
+ schema
175
+ })
175
176
  };
176
177
  },
177
178
  sync_rules_content: content,
@@ -180,19 +181,24 @@ export const validate = routeDefinition({
180
181
  }
181
182
  };
182
183
 
183
- const connectionStatus = await api.getConnectionStatus(system);
184
- if (connectionStatus == null) {
184
+ const connectionStatus = await apiHandler.getConnectionStatus();
185
+ if (!connectionStatus) {
185
186
  return internal_routes.ValidateResponse.encode({
186
187
  errors: [{ level: 'fatal', message: 'No connection configured' }],
187
188
  connections: []
188
189
  });
189
190
  }
190
191
 
191
- const status = (await api.getSyncRulesStatus(sync_rules, system, {
192
- include_content: false,
193
- check_connection: connectionStatus?.connected,
194
- live_status: false
195
- }))!;
192
+ const status = (await api.getSyncRulesStatus(
193
+ service_context.storageEngine.activeBucketStorage,
194
+ apiHandler,
195
+ sync_rules,
196
+ {
197
+ include_content: false,
198
+ check_connection: connectionStatus.connected,
199
+ live_status: false
200
+ }
201
+ ))!;
196
202
 
197
203
  if (connectionStatus == null) {
198
204
  status.errors.push({ level: 'fatal', message: 'No connection configured' });
@@ -202,14 +208,4 @@ export const validate = routeDefinition({
202
208
  }
203
209
  });
204
210
 
205
- function mapColumnValue(value: SqliteValue) {
206
- if (typeof value == 'bigint') {
207
- return Number(value);
208
- } else if (isJsonValue(value)) {
209
- return value;
210
- } else {
211
- return null;
212
- }
213
- }
214
-
215
211
  export const ADMIN_ROUTES = [executeSql, diagnostics, getSchema, reprocess, validate];
@@ -1,6 +1,7 @@
1
+ import { logger, router, schema } from '@powersync/lib-services-framework';
1
2
  import * as t from 'ts-codec';
2
- import { router, schema } from '@powersync/lib-services-framework';
3
3
 
4
+ import * as framework from '@powersync/lib-services-framework';
4
5
  import * as util from '../../util/util-index.js';
5
6
  import { authUser } from '../auth.js';
6
7
  import { routeDefinition } from '../router.js';
@@ -15,13 +16,33 @@ export const writeCheckpoint = routeDefinition({
15
16
  authorize: authUser,
16
17
  validator: schema.createTsCodecValidator(WriteCheckpointRequest, { allowAdditional: true }),
17
18
  handler: async (payload) => {
18
- const system = payload.context.system;
19
- const storage = system.storage;
19
+ const {
20
+ context: { service_context }
21
+ } = payload;
22
+ const apiHandler = service_context.routerEngine!.getAPI();
20
23
 
21
- const checkpoint = await util.getClientCheckpoint(system.requirePgPool(), storage);
22
- return {
23
- checkpoint
24
- };
24
+ // This old API needs a persisted checkpoint id.
25
+ // Since we don't use LSNs anymore, the only way to get that is to wait.
26
+ const start = Date.now();
27
+
28
+ const head = await apiHandler.getReplicationHead();
29
+
30
+ const timeout = 50_000;
31
+
32
+ logger.info(`Waiting for LSN checkpoint: ${head}`);
33
+ while (Date.now() - start < timeout) {
34
+ const cp = await service_context.storageEngine.activeBucketStorage.getActiveCheckpoint();
35
+ if (!cp.hasSyncRules()) {
36
+ throw new Error('No sync rules available');
37
+ }
38
+ if (cp.lsn && cp.lsn >= head) {
39
+ logger.info(`Got write checkpoint: ${head} : ${cp.checkpoint}`);
40
+ return { checkpoint: cp.checkpoint };
41
+ }
42
+
43
+ await new Promise((resolve) => setTimeout(resolve, 30));
44
+ }
45
+ throw new Error('Timeout while waiting for checkpoint');
25
46
  }
26
47
  });
27
48
 
@@ -31,13 +52,32 @@ export const writeCheckpoint2 = routeDefinition({
31
52
  authorize: authUser,
32
53
  validator: schema.createTsCodecValidator(WriteCheckpointRequest, { allowAdditional: true }),
33
54
  handler: async (payload) => {
34
- const { user_id, system } = payload.context;
55
+ const { user_id, service_context } = payload.context;
56
+
57
+ const apiHandler = service_context.routerEngine!.getAPI();
58
+
35
59
  const client_id = payload.params.client_id;
36
60
  const full_user_id = util.checkpointUserId(user_id, client_id);
37
- const storage = system.storage;
38
- const write_checkpoint = await util.createWriteCheckpoint(system.requirePgPool(), storage, full_user_id);
61
+
62
+ const currentCheckpoint = await apiHandler.getReplicationHead();
63
+ const {
64
+ storageEngine: { activeBucketStorage }
65
+ } = service_context;
66
+
67
+ const activeSyncRules = await activeBucketStorage.getActiveSyncRulesContent();
68
+ if (!activeSyncRules) {
69
+ throw new framework.errors.ValidationError(`Cannot create Write Checkpoint since no sync rules are active.`);
70
+ }
71
+
72
+ using syncBucketStorage = activeBucketStorage.getInstance(activeSyncRules);
73
+ const writeCheckpoint = await syncBucketStorage.createManagedWriteCheckpoint({
74
+ user_id: full_user_id,
75
+ heads: { '1': currentCheckpoint }
76
+ });
77
+ logger.info(`Write checkpoint 2: ${JSON.stringify({ currentCheckpoint, id: String(full_user_id) })}`);
78
+
39
79
  return {
40
- write_checkpoint: String(write_checkpoint)
80
+ write_checkpoint: String(writeCheckpoint)
41
81
  };
42
82
  }
43
83
  });
@@ -0,0 +1,58 @@
1
+ import { container, router } from "@powersync/lib-services-framework";
2
+ import { routeDefinition } from "../router.js";
3
+
4
+ export enum ProbeRoutes {
5
+ STARTUP = '/probes/startup',
6
+ LIVENESS = '/probes/liveness',
7
+ READINESS = '/probes/readiness'
8
+ }
9
+
10
+ export const startupCheck = routeDefinition({
11
+ path: ProbeRoutes.STARTUP,
12
+ method: router.HTTPMethod.GET,
13
+ handler: async () => {
14
+ const state = container.probes.state();
15
+
16
+ return new router.RouterResponse({
17
+ status: state.started ? 200 : 400,
18
+ data: {
19
+ ...state,
20
+ }
21
+ });
22
+ }
23
+ });
24
+
25
+ export const livenessCheck = routeDefinition({
26
+ path: ProbeRoutes.LIVENESS,
27
+ method: router.HTTPMethod.GET,
28
+ handler: async () => {
29
+ const state = container.probes.state();
30
+
31
+ const timeDifference = Date.now() - state.touched_at.getTime()
32
+ const status = timeDifference < 10000 ? 200 : 400;
33
+
34
+ return new router.RouterResponse({
35
+ status,
36
+ data: {
37
+ ...state,
38
+ }
39
+ });
40
+ }
41
+ });
42
+
43
+ export const readinessCheck = routeDefinition({
44
+ path: ProbeRoutes.READINESS,
45
+ method: router.HTTPMethod.GET,
46
+ handler: async () => {
47
+ const state = container.probes.state();
48
+
49
+ return new router.RouterResponse({
50
+ status: state.ready ? 200 : 400,
51
+ data: {
52
+ ...state,
53
+ }
54
+ });
55
+ }
56
+ });
57
+
58
+ export const PROBES_ROUTES = [startupCheck, livenessCheck, readinessCheck];
@@ -12,7 +12,8 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
12
12
  router.reactiveStream<util.StreamingSyncRequest, any>(SyncRoutes.STREAM, {
13
13
  validator: schema.createTsCodecValidator(util.StreamingSyncRequest, { allowAdditional: true }),
14
14
  handler: async ({ context, params, responder, observer, initialN, signal: upstreamSignal }) => {
15
- const { system } = context;
15
+ const { service_context } = context;
16
+ const { routerEngine } = service_context;
16
17
 
17
18
  // Create our own controller that we can abort directly
18
19
  const controller = new AbortController();
@@ -31,7 +32,7 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
31
32
  }
32
33
  });
33
34
 
34
- if (system.closed) {
35
+ if (routerEngine!.closed) {
35
36
  responder.onError(
36
37
  new errors.JourneyError({
37
38
  status: 503,
@@ -45,9 +46,11 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
45
46
 
46
47
  const syncParams = new RequestParameters(context.token_payload!, params.parameters ?? {});
47
48
 
48
- const storage = system.storage;
49
+ const {
50
+ storageEngine: { activeBucketStorage }
51
+ } = service_context;
49
52
  // Sanity check before we start the stream
50
- const cp = await storage.getActiveCheckpoint();
53
+ const cp = await activeBucketStorage.getActiveCheckpoint();
51
54
  if (!cp.hasSyncRules()) {
52
55
  responder.onError(
53
56
  new errors.JourneyError({
@@ -60,7 +63,7 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
60
63
  return;
61
64
  }
62
65
 
63
- const removeStopHandler = system.addStopHandler(() => {
66
+ const removeStopHandler = routerEngine!.addStopHandler(() => {
64
67
  controller.abort();
65
68
  });
66
69
 
@@ -68,7 +71,8 @@ export const syncStreamReactive: SocketRouteGenerator = (router) =>
68
71
  const tracker = new sync.RequestTracker();
69
72
  try {
70
73
  for await (const data of sync.streamResponse({
71
- storage,
74
+ storage: activeBucketStorage,
75
+ parseOptions: routerEngine!.getAPI().getParseSyncRulesOptions(),
72
76
  params: {
73
77
  ...params,
74
78
  binary_data: true // always true for web sockets
@@ -1,10 +1,9 @@
1
- import * as t from 'ts-codec';
2
- import type { FastifyPluginAsync } from 'fastify';
3
- import * as pgwire from '@powersync/service-jpgwire';
4
1
  import { errors, router, schema } from '@powersync/lib-services-framework';
5
2
  import { SqlSyncRules, SyncRulesErrors } from '@powersync/service-sync-rules';
3
+ import type { FastifyPluginAsync } from 'fastify';
4
+ import * as t from 'ts-codec';
6
5
 
7
- import * as replication from '../../replication/replication-index.js';
6
+ import { RouteAPI } from '../../api/RouteAPI.js';
8
7
  import { authApi } from '../auth.js';
9
8
  import { routeDefinition } from '../router.js';
10
9
 
@@ -39,7 +38,10 @@ export const deploySyncRules = routeDefinition({
39
38
  plugins: [yamlPlugin],
40
39
  validator: schema.createTsCodecValidator(DeploySyncRulesRequest, { allowAdditional: true }),
41
40
  handler: async (payload) => {
42
- if (payload.context.system.config.sync_rules.present) {
41
+ const { service_context } = payload.context;
42
+ const { storageEngine } = service_context;
43
+
44
+ if (service_context.configuration.sync_rules.present) {
43
45
  // If sync rules are configured via the config, disable deploy via the API.
44
46
  throw new errors.JourneyError({
45
47
  status: 422,
@@ -51,7 +53,12 @@ export const deploySyncRules = routeDefinition({
51
53
  const content = payload.params.content;
52
54
 
53
55
  try {
54
- SqlSyncRules.fromYaml(payload.params.content);
56
+ const apiHandler = service_context.routerEngine!.getAPI();
57
+ SqlSyncRules.fromYaml(payload.params.content, {
58
+ ...apiHandler.getParseSyncRulesOptions(),
59
+ // We don't do any schema-level validation at this point
60
+ schema: undefined
61
+ });
55
62
  } catch (e) {
56
63
  throw new errors.JourneyError({
57
64
  status: 422,
@@ -61,7 +68,7 @@ export const deploySyncRules = routeDefinition({
61
68
  });
62
69
  }
63
70
 
64
- const sync_rules = await payload.context.system.storage.updateSyncRules({
71
+ const sync_rules = await storageEngine.activeBucketStorage.updateSyncRules({
65
72
  content: content
66
73
  });
67
74
 
@@ -84,8 +91,10 @@ export const validateSyncRules = routeDefinition({
84
91
  validator: schema.createTsCodecValidator(ValidateSyncRulesRequest, { allowAdditional: true }),
85
92
  handler: async (payload) => {
86
93
  const content = payload.params.content;
94
+ const { service_context } = payload.context;
95
+ const apiHandler = service_context.routerEngine!.getAPI();
87
96
 
88
- const info = await debugSyncRules(payload.context.system.requirePgPool(), content);
97
+ const info = await debugSyncRules(apiHandler, content);
89
98
 
90
99
  return replyPrettyJson(info);
91
100
  }
@@ -96,8 +105,12 @@ export const currentSyncRules = routeDefinition({
96
105
  method: router.HTTPMethod.GET,
97
106
  authorize: authApi,
98
107
  handler: async (payload) => {
99
- const storage = payload.context.system.storage;
100
- const sync_rules = await storage.getActiveSyncRulesContent();
108
+ const { service_context } = payload.context;
109
+ const {
110
+ storageEngine: { activeBucketStorage }
111
+ } = service_context;
112
+
113
+ const sync_rules = await activeBucketStorage.getActiveSyncRulesContent();
101
114
  if (!sync_rules) {
102
115
  throw new errors.JourneyError({
103
116
  status: 422,
@@ -105,12 +118,12 @@ export const currentSyncRules = routeDefinition({
105
118
  description: 'No active sync rules'
106
119
  });
107
120
  }
108
- const info = await debugSyncRules(payload.context.system.requirePgPool(), sync_rules.sync_rules_content);
109
- const next = await storage.getNextSyncRulesContent();
110
121
 
111
- const next_info = next
112
- ? await debugSyncRules(payload.context.system.requirePgPool(), next.sync_rules_content)
113
- : null;
122
+ const apiHandler = service_context.routerEngine!.getAPI();
123
+ const info = await debugSyncRules(apiHandler, sync_rules.sync_rules_content);
124
+ const next = await activeBucketStorage.getNextSyncRulesContent();
125
+
126
+ const next_info = next ? await debugSyncRules(apiHandler, next.sync_rules_content) : null;
114
127
 
115
128
  const response = {
116
129
  current: {
@@ -140,8 +153,11 @@ export const reprocessSyncRules = routeDefinition({
140
153
  authorize: authApi,
141
154
  validator: schema.createTsCodecValidator(ReprocessSyncRulesRequest),
142
155
  handler: async (payload) => {
143
- const storage = payload.context.system.storage;
144
- const sync_rules = await storage.getActiveSyncRules();
156
+ const {
157
+ storageEngine: { activeBucketStorage }
158
+ } = payload.context.service_context;
159
+ const apiHandler = payload.context.service_context.routerEngine!.getAPI();
160
+ const sync_rules = await activeBucketStorage.getActiveSyncRules(apiHandler.getParseSyncRulesOptions());
145
161
  if (sync_rules == null) {
146
162
  throw new errors.JourneyError({
147
163
  status: 422,
@@ -150,7 +166,7 @@ export const reprocessSyncRules = routeDefinition({
150
166
  });
151
167
  }
152
168
 
153
- const new_rules = await storage.updateSyncRules({
169
+ const new_rules = await activeBucketStorage.updateSyncRules({
154
170
  content: sync_rules.sync_rules.content
155
171
  });
156
172
  return {
@@ -169,15 +185,15 @@ function replyPrettyJson(payload: any) {
169
185
  });
170
186
  }
171
187
 
172
- async function debugSyncRules(db: pgwire.PgClient, sync_rules: string) {
188
+ async function debugSyncRules(apiHandler: RouteAPI, sync_rules: string) {
173
189
  try {
174
- const rules = SqlSyncRules.fromYaml(sync_rules);
175
- const source_table_patterns = rules.getSourceTables();
176
- const wc = new replication.WalConnection({
177
- db: db,
178
- sync_rules: rules
190
+ const rules = SqlSyncRules.fromYaml(sync_rules, {
191
+ ...apiHandler.getParseSyncRulesOptions(),
192
+ // No schema-based validation at this point
193
+ schema: undefined
179
194
  });
180
- const resolved_tables = await wc.getDebugTablesInfo(source_table_patterns);
195
+ const source_table_patterns = rules.getSourceTables();
196
+ const resolved_tables = await apiHandler.getDebugTablesInfo(source_table_patterns, rules);
181
197
 
182
198
  return {
183
199
  valid: true,
@@ -8,7 +8,6 @@ import * as util from '../../util/util-index.js';
8
8
  import { Metrics } from '../../metrics/Metrics.js';
9
9
  import { authUser } from '../auth.js';
10
10
  import { routeDefinition } from '../router.js';
11
- import { RequestTracker } from '../../sync/RequestTracker.js';
12
11
 
13
12
  export enum SyncRoutes {
14
13
  STREAM = '/sync/stream'
@@ -20,12 +19,13 @@ export const syncStreamed = routeDefinition({
20
19
  authorize: authUser,
21
20
  validator: schema.createTsCodecValidator(util.StreamingSyncRequest, { allowAdditional: true }),
22
21
  handler: async (payload) => {
23
- const system = payload.context.system;
22
+ const { service_context } = payload.context;
23
+ const { routerEngine, storageEngine } = service_context;
24
24
  const headers = payload.request.headers;
25
25
  const userAgent = headers['x-user-agent'] ?? headers['user-agent'];
26
26
  const clientId = payload.params.client_id;
27
27
 
28
- if (system.closed) {
28
+ if (routerEngine!.closed) {
29
29
  throw new errors.JourneyError({
30
30
  status: 503,
31
31
  code: 'SERVICE_UNAVAILABLE',
@@ -36,9 +36,8 @@ export const syncStreamed = routeDefinition({
36
36
  const params: util.StreamingSyncRequest = payload.params;
37
37
  const syncParams = new RequestParameters(payload.context.token_payload!, payload.params.parameters ?? {});
38
38
 
39
- const storage = system.storage;
40
39
  // Sanity check before we start the stream
41
- const cp = await storage.getActiveCheckpoint();
40
+ const cp = await storageEngine.activeBucketStorage.getActiveCheckpoint();
42
41
  if (!cp.hasSyncRules()) {
43
42
  throw new errors.JourneyError({
44
43
  status: 500,
@@ -47,14 +46,15 @@ export const syncStreamed = routeDefinition({
47
46
  });
48
47
  }
49
48
  const controller = new AbortController();
50
- const tracker = new RequestTracker();
49
+ const tracker = new sync.RequestTracker();
51
50
  try {
52
51
  Metrics.getInstance().concurrent_connections.add(1);
53
52
  const stream = Readable.from(
54
53
  sync.transformToBytesTracked(
55
54
  sync.ndjson(
56
55
  sync.streamResponse({
57
- storage,
56
+ storage: storageEngine.activeBucketStorage,
57
+ parseOptions: routerEngine!.getAPI().getParseSyncRulesOptions(),
58
58
  params,
59
59
  syncParams,
60
60
  token: payload.context.token_payload!,
@@ -67,7 +67,7 @@ export const syncStreamed = routeDefinition({
67
67
  { objectMode: false, highWaterMark: 16 * 1024 }
68
68
  );
69
69
 
70
- const deregister = system.addStopHandler(() => {
70
+ const deregister = routerEngine!.addStopHandler(() => {
71
71
  // This error is not currently propagated to the client
72
72
  controller.abort();
73
73
  stream.destroy(new Error('Shutting down system'));