@powersync/service-core 0.0.0-dev-20240718134716 → 0.0.0-dev-20240918082156

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 (352) hide show
  1. package/CHANGELOG.md +89 -6
  2. package/dist/api/RouteAPI.d.ts +68 -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 +11 -65
  10. package/dist/api/diagnostics.js.map +1 -1
  11. package/dist/api/schema.d.ts +3 -5
  12. package/dist/api/schema.js +9 -79
  13. package/dist/api/schema.js.map +1 -1
  14. package/dist/auth/KeyStore.d.ts +7 -4
  15. package/dist/auth/KeyStore.js +1 -1
  16. package/dist/auth/KeyStore.js.map +1 -1
  17. package/dist/auth/auth-index.d.ts +0 -1
  18. package/dist/auth/auth-index.js +0 -1
  19. package/dist/auth/auth-index.js.map +1 -1
  20. package/dist/entry/cli-entry.js +4 -2
  21. package/dist/entry/cli-entry.js.map +1 -1
  22. package/dist/entry/commands/compact-action.d.ts +2 -0
  23. package/dist/entry/commands/compact-action.js +52 -0
  24. package/dist/entry/commands/compact-action.js.map +1 -0
  25. package/dist/entry/commands/migrate-action.js +4 -5
  26. package/dist/entry/commands/migrate-action.js.map +1 -1
  27. package/dist/entry/commands/teardown-action.js +2 -2
  28. package/dist/entry/commands/teardown-action.js.map +1 -1
  29. package/dist/entry/entry-index.d.ts +1 -0
  30. package/dist/entry/entry-index.js +1 -0
  31. package/dist/entry/entry-index.js.map +1 -1
  32. package/dist/index.d.ts +4 -2
  33. package/dist/index.js +4 -2
  34. package/dist/index.js.map +1 -1
  35. package/dist/metrics/Metrics.d.ts +6 -5
  36. package/dist/metrics/Metrics.js +53 -10
  37. package/dist/metrics/Metrics.js.map +1 -1
  38. package/dist/migrations/db/migrations/1684951997326-init.d.ts +2 -2
  39. package/dist/migrations/db/migrations/1684951997326-init.js +4 -2
  40. package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
  41. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +2 -2
  42. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +4 -2
  43. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
  44. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +2 -2
  45. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +4 -2
  46. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
  47. package/dist/migrations/migrations.d.ts +8 -0
  48. package/dist/migrations/migrations.js +19 -7
  49. package/dist/migrations/migrations.js.map +1 -1
  50. package/dist/modules/AbstractModule.d.ts +26 -0
  51. package/dist/modules/AbstractModule.js +11 -0
  52. package/dist/modules/AbstractModule.js.map +1 -0
  53. package/dist/modules/ModuleManager.d.ts +11 -0
  54. package/dist/modules/ModuleManager.js +32 -0
  55. package/dist/modules/ModuleManager.js.map +1 -0
  56. package/dist/modules/modules-index.d.ts +2 -0
  57. package/dist/modules/modules-index.js +3 -0
  58. package/dist/modules/modules-index.js.map +1 -0
  59. package/dist/replication/AbstractReplicationJob.d.ts +38 -0
  60. package/dist/replication/AbstractReplicationJob.js +51 -0
  61. package/dist/replication/AbstractReplicationJob.js.map +1 -0
  62. package/dist/replication/AbstractReplicator.d.ts +53 -0
  63. package/dist/replication/AbstractReplicator.js +187 -0
  64. package/dist/replication/AbstractReplicator.js.map +1 -0
  65. package/dist/replication/ErrorRateLimiter.d.ts +0 -9
  66. package/dist/replication/ErrorRateLimiter.js +1 -42
  67. package/dist/replication/ErrorRateLimiter.js.map +1 -1
  68. package/dist/replication/ReplicationEngine.d.ts +18 -0
  69. package/dist/replication/ReplicationEngine.js +41 -0
  70. package/dist/replication/ReplicationEngine.js.map +1 -0
  71. package/dist/replication/ReplicationModule.d.ts +39 -0
  72. package/dist/replication/ReplicationModule.js +65 -0
  73. package/dist/replication/ReplicationModule.js.map +1 -0
  74. package/dist/replication/replication-index.d.ts +4 -6
  75. package/dist/replication/replication-index.js +4 -6
  76. package/dist/replication/replication-index.js.map +1 -1
  77. package/dist/routes/RouterEngine.d.ts +42 -0
  78. package/dist/routes/RouterEngine.js +80 -0
  79. package/dist/routes/RouterEngine.js.map +1 -0
  80. package/dist/routes/auth.d.ts +2 -2
  81. package/dist/routes/auth.js +11 -11
  82. package/dist/routes/auth.js.map +1 -1
  83. package/dist/routes/configure-fastify.d.ts +737 -0
  84. package/dist/routes/configure-fastify.js +57 -0
  85. package/dist/routes/configure-fastify.js.map +1 -0
  86. package/dist/routes/configure-rsocket.d.ts +13 -0
  87. package/dist/routes/configure-rsocket.js +47 -0
  88. package/dist/routes/configure-rsocket.js.map +1 -0
  89. package/dist/routes/endpoints/admin.d.ts +0 -34
  90. package/dist/routes/endpoints/admin.js +48 -89
  91. package/dist/routes/endpoints/admin.js.map +1 -1
  92. package/dist/routes/endpoints/checkpointing.d.ts +56 -16
  93. package/dist/routes/endpoints/checkpointing.js +33 -12
  94. package/dist/routes/endpoints/checkpointing.js.map +1 -1
  95. package/dist/routes/endpoints/route-endpoints-index.d.ts +0 -1
  96. package/dist/routes/endpoints/route-endpoints-index.js +0 -1
  97. package/dist/routes/endpoints/route-endpoints-index.js.map +1 -1
  98. package/dist/routes/endpoints/socket-route.js +46 -39
  99. package/dist/routes/endpoints/socket-route.js.map +1 -1
  100. package/dist/routes/endpoints/sync-rules.d.ts +1 -1
  101. package/dist/routes/endpoints/sync-rules.js +32 -23
  102. package/dist/routes/endpoints/sync-rules.js.map +1 -1
  103. package/dist/routes/endpoints/sync-stream.d.ts +10 -0
  104. package/dist/routes/endpoints/sync-stream.js +17 -13
  105. package/dist/routes/endpoints/sync-stream.js.map +1 -1
  106. package/dist/routes/route-register.d.ts +1 -1
  107. package/dist/routes/route-register.js +1 -1
  108. package/dist/routes/route-register.js.map +1 -1
  109. package/dist/routes/router-socket.d.ts +5 -4
  110. package/dist/routes/router-socket.js +2 -1
  111. package/dist/routes/router-socket.js.map +1 -1
  112. package/dist/routes/router.d.ts +7 -2
  113. package/dist/routes/router.js.map +1 -1
  114. package/dist/routes/routes-index.d.ts +3 -0
  115. package/dist/routes/routes-index.js +3 -0
  116. package/dist/routes/routes-index.js.map +1 -1
  117. package/dist/runner/teardown.js +47 -76
  118. package/dist/runner/teardown.js.map +1 -1
  119. package/dist/storage/BucketStorage.d.ts +61 -20
  120. package/dist/storage/BucketStorage.js +0 -10
  121. package/dist/storage/BucketStorage.js.map +1 -1
  122. package/dist/storage/MongoBucketStorage.d.ts +4 -4
  123. package/dist/storage/MongoBucketStorage.js +19 -24
  124. package/dist/storage/MongoBucketStorage.js.map +1 -1
  125. package/dist/storage/SourceEntity.d.ts +20 -0
  126. package/dist/storage/SourceEntity.js +2 -0
  127. package/dist/storage/SourceEntity.js.map +1 -0
  128. package/dist/storage/SourceTable.d.ts +4 -5
  129. package/dist/storage/SourceTable.js +3 -4
  130. package/dist/storage/SourceTable.js.map +1 -1
  131. package/dist/storage/StorageEngine.d.ts +24 -0
  132. package/dist/storage/StorageEngine.js +43 -0
  133. package/dist/storage/StorageEngine.js.map +1 -0
  134. package/dist/storage/StorageProvider.d.ts +21 -0
  135. package/dist/storage/StorageProvider.js +2 -0
  136. package/dist/storage/StorageProvider.js.map +1 -0
  137. package/dist/storage/mongo/MongoBucketBatch.d.ts +1 -1
  138. package/dist/storage/mongo/MongoBucketBatch.js +6 -7
  139. package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
  140. package/dist/storage/mongo/MongoCompactor.d.ts +40 -0
  141. package/dist/storage/mongo/MongoCompactor.js +293 -0
  142. package/dist/storage/mongo/MongoCompactor.js.map +1 -0
  143. package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +2 -2
  144. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +2 -2
  145. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -1
  146. package/dist/storage/mongo/MongoStorageProvider.d.ts +5 -0
  147. package/dist/storage/mongo/MongoStorageProvider.js +26 -0
  148. package/dist/storage/mongo/MongoStorageProvider.js.map +1 -0
  149. package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +9 -7
  150. package/dist/storage/mongo/MongoSyncBucketStorage.js +43 -28
  151. package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
  152. package/dist/storage/mongo/MongoSyncRulesLock.js +1 -1
  153. package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -1
  154. package/dist/storage/mongo/OperationBatch.d.ts +7 -3
  155. package/dist/storage/mongo/OperationBatch.js +16 -7
  156. package/dist/storage/mongo/OperationBatch.js.map +1 -1
  157. package/dist/storage/mongo/PersistedBatch.d.ts +3 -3
  158. package/dist/storage/mongo/PersistedBatch.js +2 -2
  159. package/dist/storage/mongo/PersistedBatch.js.map +1 -1
  160. package/dist/storage/mongo/models.d.ts +17 -7
  161. package/dist/storage/mongo/models.js.map +1 -1
  162. package/dist/storage/mongo/util.d.ts +14 -0
  163. package/dist/storage/mongo/util.js +70 -0
  164. package/dist/storage/mongo/util.js.map +1 -1
  165. package/dist/storage/storage-index.d.ts +5 -2
  166. package/dist/storage/storage-index.js +5 -2
  167. package/dist/storage/storage-index.js.map +1 -1
  168. package/dist/sync/RequestTracker.js +2 -3
  169. package/dist/sync/RequestTracker.js.map +1 -1
  170. package/dist/sync/sync-index.d.ts +1 -0
  171. package/dist/sync/sync-index.js +1 -0
  172. package/dist/sync/sync-index.js.map +1 -1
  173. package/dist/sync/sync.d.ts +2 -1
  174. package/dist/sync/sync.js +56 -17
  175. package/dist/sync/sync.js.map +1 -1
  176. package/dist/system/ServiceContext.d.ts +37 -0
  177. package/dist/system/ServiceContext.js +48 -0
  178. package/dist/system/ServiceContext.js.map +1 -0
  179. package/dist/system/system-index.d.ts +1 -1
  180. package/dist/system/system-index.js +1 -1
  181. package/dist/system/system-index.js.map +1 -1
  182. package/dist/util/config/collectors/config-collector.d.ts +12 -0
  183. package/dist/util/config/collectors/config-collector.js +43 -0
  184. package/dist/util/config/collectors/config-collector.js.map +1 -1
  185. package/dist/util/config/compound-config-collector.d.ts +10 -29
  186. package/dist/util/config/compound-config-collector.js +28 -84
  187. package/dist/util/config/compound-config-collector.js.map +1 -1
  188. package/dist/util/config/sync-rules/sync-rules-provider.d.ts +9 -0
  189. package/dist/util/config/sync-rules/sync-rules-provider.js +15 -0
  190. package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -0
  191. package/dist/util/config/types.d.ts +6 -4
  192. package/dist/util/config/types.js.map +1 -1
  193. package/dist/util/config.d.ts +3 -4
  194. package/dist/util/config.js +5 -20
  195. package/dist/util/config.js.map +1 -1
  196. package/dist/util/protocol-types.d.ts +4 -0
  197. package/dist/util/protocol-types.js +5 -1
  198. package/dist/util/protocol-types.js.map +1 -1
  199. package/dist/util/util-index.d.ts +3 -6
  200. package/dist/util/util-index.js +3 -6
  201. package/dist/util/util-index.js.map +1 -1
  202. package/dist/util/utils.d.ts +10 -6
  203. package/dist/util/utils.js +45 -25
  204. package/dist/util/utils.js.map +1 -1
  205. package/package.json +7 -7
  206. package/src/api/RouteAPI.ts +78 -0
  207. package/src/api/api-index.ts +1 -0
  208. package/src/api/diagnostics.ts +16 -71
  209. package/src/api/schema.ts +13 -89
  210. package/src/auth/KeyStore.ts +9 -6
  211. package/src/auth/auth-index.ts +0 -1
  212. package/src/entry/cli-entry.ts +4 -2
  213. package/src/entry/commands/compact-action.ts +57 -0
  214. package/src/entry/commands/migrate-action.ts +5 -8
  215. package/src/entry/commands/teardown-action.ts +2 -2
  216. package/src/entry/entry-index.ts +1 -0
  217. package/src/index.ts +5 -2
  218. package/src/metrics/Metrics.ts +70 -15
  219. package/src/migrations/db/migrations/1684951997326-init.ts +9 -4
  220. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -4
  221. package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +6 -4
  222. package/src/migrations/migrations.ts +24 -8
  223. package/src/modules/AbstractModule.ts +37 -0
  224. package/src/modules/ModuleManager.ts +34 -0
  225. package/src/modules/modules-index.ts +2 -0
  226. package/src/replication/AbstractReplicationJob.ts +79 -0
  227. package/src/replication/AbstractReplicator.ts +227 -0
  228. package/src/replication/ErrorRateLimiter.ts +0 -44
  229. package/src/replication/ReplicationEngine.ts +43 -0
  230. package/src/replication/ReplicationModule.ts +101 -0
  231. package/src/replication/replication-index.ts +4 -6
  232. package/src/routes/RouterEngine.ts +120 -0
  233. package/src/routes/auth.ts +21 -12
  234. package/src/routes/configure-fastify.ts +101 -0
  235. package/src/routes/configure-rsocket.ts +60 -0
  236. package/src/routes/endpoints/admin.ts +74 -100
  237. package/src/routes/endpoints/checkpointing.ts +46 -12
  238. package/src/routes/endpoints/route-endpoints-index.ts +0 -1
  239. package/src/routes/endpoints/socket-route.ts +50 -42
  240. package/src/routes/endpoints/sync-rules.ts +41 -25
  241. package/src/routes/endpoints/sync-stream.ts +17 -13
  242. package/src/routes/route-register.ts +2 -2
  243. package/src/routes/router-socket.ts +6 -5
  244. package/src/routes/router.ts +7 -2
  245. package/src/routes/routes-index.ts +3 -0
  246. package/src/runner/teardown.ts +50 -88
  247. package/src/storage/BucketStorage.ts +74 -26
  248. package/src/storage/MongoBucketStorage.ts +23 -26
  249. package/src/storage/SourceEntity.ts +22 -0
  250. package/src/storage/SourceTable.ts +4 -6
  251. package/src/storage/StorageEngine.ts +55 -0
  252. package/src/storage/StorageProvider.ts +27 -0
  253. package/src/storage/mongo/MongoBucketBatch.ts +8 -8
  254. package/src/storage/mongo/MongoCompactor.ts +372 -0
  255. package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +3 -3
  256. package/src/storage/mongo/MongoStorageProvider.ts +31 -0
  257. package/src/storage/mongo/MongoSyncBucketStorage.ts +64 -34
  258. package/src/storage/mongo/MongoSyncRulesLock.ts +1 -1
  259. package/src/storage/mongo/OperationBatch.ts +18 -11
  260. package/src/storage/mongo/PersistedBatch.ts +6 -5
  261. package/src/storage/mongo/models.ts +17 -7
  262. package/src/storage/mongo/util.ts +71 -1
  263. package/src/storage/storage-index.ts +5 -2
  264. package/src/sync/RequestTracker.ts +3 -3
  265. package/src/sync/sync-index.ts +1 -0
  266. package/src/sync/sync.ts +66 -17
  267. package/src/system/ServiceContext.ts +68 -0
  268. package/src/system/system-index.ts +1 -1
  269. package/src/util/config/collectors/config-collector.ts +48 -0
  270. package/src/util/config/compound-config-collector.ts +45 -110
  271. package/src/util/config/sync-rules/sync-rules-provider.ts +18 -0
  272. package/src/util/config/types.ts +6 -5
  273. package/src/util/config.ts +6 -23
  274. package/src/util/protocol-types.ts +6 -1
  275. package/src/util/util-index.ts +3 -6
  276. package/src/util/utils.ts +55 -39
  277. package/test/src/__snapshots__/sync.test.ts.snap +90 -5
  278. package/test/src/auth.test.ts +7 -7
  279. package/test/src/broadcast_iterable.test.ts +1 -1
  280. package/test/src/bucket_validation.test.ts +142 -0
  281. package/test/src/bucket_validation.ts +116 -0
  282. package/test/src/checksum_cache.test.ts +3 -3
  283. package/test/src/compacting.test.ts +216 -0
  284. package/test/src/data_storage.test.ts +275 -204
  285. package/test/src/env.ts +1 -3
  286. package/test/src/merge_iterable.test.ts +1 -6
  287. package/test/src/setup.ts +1 -1
  288. package/test/src/stream_utils.ts +42 -0
  289. package/test/src/sync.test.ts +209 -48
  290. package/test/src/util.ts +110 -55
  291. package/test/tsconfig.json +1 -1
  292. package/tsconfig.tsbuildinfo +1 -1
  293. package/dist/auth/SupabaseKeyCollector.d.ts +0 -22
  294. package/dist/auth/SupabaseKeyCollector.js +0 -61
  295. package/dist/auth/SupabaseKeyCollector.js.map +0 -1
  296. package/dist/replication/PgRelation.d.ts +0 -16
  297. package/dist/replication/PgRelation.js +0 -26
  298. package/dist/replication/PgRelation.js.map +0 -1
  299. package/dist/replication/WalConnection.d.ts +0 -34
  300. package/dist/replication/WalConnection.js +0 -190
  301. package/dist/replication/WalConnection.js.map +0 -1
  302. package/dist/replication/WalStream.d.ts +0 -57
  303. package/dist/replication/WalStream.js +0 -517
  304. package/dist/replication/WalStream.js.map +0 -1
  305. package/dist/replication/WalStreamManager.d.ts +0 -30
  306. package/dist/replication/WalStreamManager.js +0 -198
  307. package/dist/replication/WalStreamManager.js.map +0 -1
  308. package/dist/replication/WalStreamRunner.d.ts +0 -38
  309. package/dist/replication/WalStreamRunner.js +0 -155
  310. package/dist/replication/WalStreamRunner.js.map +0 -1
  311. package/dist/replication/util.d.ts +0 -9
  312. package/dist/replication/util.js +0 -62
  313. package/dist/replication/util.js.map +0 -1
  314. package/dist/routes/endpoints/dev.d.ts +0 -312
  315. package/dist/routes/endpoints/dev.js +0 -172
  316. package/dist/routes/endpoints/dev.js.map +0 -1
  317. package/dist/system/CorePowerSyncSystem.d.ts +0 -23
  318. package/dist/system/CorePowerSyncSystem.js +0 -52
  319. package/dist/system/CorePowerSyncSystem.js.map +0 -1
  320. package/dist/util/PgManager.d.ts +0 -24
  321. package/dist/util/PgManager.js +0 -55
  322. package/dist/util/PgManager.js.map +0 -1
  323. package/dist/util/migration_lib.d.ts +0 -11
  324. package/dist/util/migration_lib.js +0 -64
  325. package/dist/util/migration_lib.js.map +0 -1
  326. package/dist/util/pgwire_utils.d.ts +0 -24
  327. package/dist/util/pgwire_utils.js +0 -117
  328. package/dist/util/pgwire_utils.js.map +0 -1
  329. package/dist/util/populate_test_data.d.ts +0 -8
  330. package/dist/util/populate_test_data.js +0 -65
  331. package/dist/util/populate_test_data.js.map +0 -1
  332. package/src/auth/SupabaseKeyCollector.ts +0 -67
  333. package/src/replication/PgRelation.ts +0 -42
  334. package/src/replication/WalConnection.ts +0 -227
  335. package/src/replication/WalStream.ts +0 -628
  336. package/src/replication/WalStreamManager.ts +0 -213
  337. package/src/replication/WalStreamRunner.ts +0 -180
  338. package/src/replication/util.ts +0 -76
  339. package/src/routes/endpoints/dev.ts +0 -199
  340. package/src/system/CorePowerSyncSystem.ts +0 -64
  341. package/src/util/PgManager.ts +0 -64
  342. package/src/util/migration_lib.ts +0 -79
  343. package/src/util/pgwire_utils.ts +0 -139
  344. package/src/util/populate_test_data.ts +0 -78
  345. package/test/src/__snapshots__/pg_test.test.ts.snap +0 -256
  346. package/test/src/large_batch.test.ts +0 -194
  347. package/test/src/pg_test.test.ts +0 -450
  348. package/test/src/schema_changes.test.ts +0 -545
  349. package/test/src/slow_tests.test.ts +0 -296
  350. package/test/src/validation.test.ts +0 -63
  351. package/test/src/wal_stream.test.ts +0 -314
  352. package/test/src/wal_stream_utils.ts +0 -147
@@ -7,10 +7,10 @@ import {
7
7
  SqliteRow,
8
8
  ToastableSqliteRow
9
9
  } from '@powersync/service-sync-rules';
10
-
11
- import * as replication from '../replication/replication-index.js';
12
10
  import * as util from '../util/util-index.js';
13
11
  import { SourceTable } from './SourceTable.js';
12
+ import { SourceEntityDescriptor } from './SourceEntity.js';
13
+ import { ReplicaId } from './storage-index.js';
14
14
 
15
15
  export interface BucketStorageFactory {
16
16
  /**
@@ -24,7 +24,7 @@ export interface BucketStorageFactory {
24
24
  /**
25
25
  * Get a storage instance to query sync data for specific sync rules.
26
26
  */
27
- getInstance(options: PersistedSyncRules): SyncRulesBucketStorage;
27
+ getInstance(options: PersistedSyncRulesContent): SyncRulesBucketStorage;
28
28
 
29
29
  /**
30
30
  * Deploy new sync rules.
@@ -48,7 +48,7 @@ export interface BucketStorageFactory {
48
48
  /**
49
49
  * Get the sync rules used for querying.
50
50
  */
51
- getActiveSyncRules(): Promise<PersistedSyncRules | null>;
51
+ getActiveSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null>;
52
52
 
53
53
  /**
54
54
  * Get the sync rules used for querying.
@@ -58,7 +58,7 @@ export interface BucketStorageFactory {
58
58
  /**
59
59
  * Get the sync rules that will be active next once done with initial replicatino.
60
60
  */
61
- getNextSyncRules(): Promise<PersistedSyncRules | null>;
61
+ getNextSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null>;
62
62
 
63
63
  /**
64
64
  * Get the sync rules that will be active next once done with initial replicatino.
@@ -105,7 +105,7 @@ export interface WriteCheckpoint {
105
105
 
106
106
  export interface ActiveCheckpoint {
107
107
  readonly checkpoint: util.OpId;
108
- readonly lsn: string;
108
+ readonly lsn: string | null;
109
109
 
110
110
  hasSyncRules(): boolean;
111
111
 
@@ -131,6 +131,10 @@ export interface StorageMetrics {
131
131
  replication_size_bytes: number;
132
132
  }
133
133
 
134
+ export interface ParseSyncRulesOptions {
135
+ defaultSchema: string;
136
+ }
137
+
134
138
  export interface PersistedSyncRulesContent {
135
139
  readonly id: number;
136
140
  readonly sync_rules_content: string;
@@ -140,7 +144,7 @@ export interface PersistedSyncRulesContent {
140
144
  readonly last_keepalive_ts?: Date | null;
141
145
  readonly last_checkpoint_ts?: Date | null;
142
146
 
143
- parsed(): PersistedSyncRules;
147
+ parsed(options: ParseSyncRulesOptions): PersistedSyncRules;
144
148
 
145
149
  lock(): Promise<ReplicationLock>;
146
150
  }
@@ -157,18 +161,6 @@ export interface PersistedSyncRules {
157
161
  readonly slot_name: string;
158
162
  }
159
163
 
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
164
  export interface UpdateSyncRulesOptions {
173
165
  content: string;
174
166
  lock?: boolean;
@@ -198,8 +190,11 @@ export interface BucketDataBatchOptions {
198
190
  chunkLimitBytes?: number;
199
191
  }
200
192
 
193
+ export interface StartBatchOptions extends ParseSyncRulesOptions {
194
+ zeroLSN: string;
195
+ }
196
+
201
197
  export interface SyncRulesBucketStorage {
202
- readonly sync_rules: SqlSyncRules;
203
198
  readonly group_id: number;
204
199
  readonly slot_name: string;
205
200
 
@@ -207,9 +202,14 @@ export interface SyncRulesBucketStorage {
207
202
 
208
203
  resolveTable(options: ResolveTableOptions): Promise<ResolveTableResult>;
209
204
 
210
- startBatch(options: {}, callback: (batch: BucketStorageBatch) => Promise<void>): Promise<FlushedResult | null>;
205
+ startBatch(
206
+ options: StartBatchOptions,
207
+ callback: (batch: BucketStorageBatch) => Promise<void>
208
+ ): Promise<FlushedResult | null>;
211
209
 
212
- getCheckpoint(): Promise<{ checkpoint: util.OpId; lsn: string }>;
210
+ getCheckpoint(): Promise<{ checkpoint: util.OpId }>;
211
+
212
+ getParsedSyncRules(options: ParseSyncRulesOptions): SqlSyncRules;
213
213
 
214
214
  getParameterSets(checkpoint: util.OpId, lookups: SqliteJsonValue[][]): Promise<SqliteJsonRow[]>;
215
215
 
@@ -228,7 +228,7 @@ export interface SyncRulesBucketStorage {
228
228
  checkpoint: util.OpId,
229
229
  dataBuckets: Map<string, string>,
230
230
  options?: BucketDataBatchOptions
231
- ): AsyncIterable<util.SyncBucketData>;
231
+ ): AsyncIterable<SyncBucketDataBatch>;
232
232
 
233
233
  /**
234
234
  * Compute checksums for a given list of buckets.
@@ -244,7 +244,7 @@ export interface SyncRulesBucketStorage {
244
244
  *
245
245
  * Must only be called on stopped sync rules.
246
246
  */
247
- terminate(): Promise<void>;
247
+ terminate(options?: TerminateOptions): Promise<void>;
248
248
 
249
249
  getStatus(): Promise<SyncRuleStatus>;
250
250
 
@@ -266,6 +266,8 @@ export interface SyncRulesBucketStorage {
266
266
  * Errors are cleared on commit.
267
267
  */
268
268
  reportError(e: any): Promise<void>;
269
+
270
+ compact(options?: CompactOptions): Promise<void>;
269
271
  }
270
272
 
271
273
  export interface SyncRuleStatus {
@@ -277,7 +279,7 @@ export interface ResolveTableOptions {
277
279
  group_id: number;
278
280
  connection_id: number;
279
281
  connection_tag: string;
280
- relation: replication.PgRelation;
282
+ entity_descriptor: SourceEntityDescriptor;
281
283
 
282
284
  sync_rules: SqlSyncRules;
283
285
  }
@@ -361,7 +363,9 @@ export interface SaveInsert {
361
363
  tag: 'insert';
362
364
  sourceTable: SourceTable;
363
365
  before?: undefined;
366
+ beforeReplicaId?: undefined;
364
367
  after: SqliteRow;
368
+ afterReplicaId: ReplicaId;
365
369
  }
366
370
 
367
371
  export interface SaveUpdate {
@@ -372,6 +376,7 @@ export interface SaveUpdate {
372
376
  * This is only present when the id has changed, and will only contain replica identity columns.
373
377
  */
374
378
  before?: SqliteRow;
379
+ beforeReplicaId?: ReplicaId;
375
380
 
376
381
  /**
377
382
  * A null value means null column.
@@ -379,13 +384,21 @@ export interface SaveUpdate {
379
384
  * An undefined value means it's a TOAST value - must be copied from another record.
380
385
  */
381
386
  after: ToastableSqliteRow;
387
+ afterReplicaId: ReplicaId;
382
388
  }
383
389
 
384
390
  export interface SaveDelete {
385
391
  tag: 'delete';
386
392
  sourceTable: SourceTable;
387
- before: SqliteRow;
393
+ before?: SqliteRow;
394
+ beforeReplicaId: ReplicaId;
388
395
  after?: undefined;
396
+ afterReplicaId?: undefined;
397
+ }
398
+
399
+ export interface SyncBucketDataBatch {
400
+ batch: util.SyncBucketData;
401
+ targetOp: bigint | null;
389
402
  }
390
403
 
391
404
  export function mergeToast(record: ToastableSqliteRow, persisted: ToastableSqliteRow): ToastableSqliteRow {
@@ -399,3 +412,38 @@ export function mergeToast(record: ToastableSqliteRow, persisted: ToastableSqlit
399
412
  }
400
413
  return newRecord;
401
414
  }
415
+
416
+ export interface CompactOptions {
417
+ /**
418
+ * Heap memory limit for the compact process.
419
+ *
420
+ * Add around 64MB to this to determine the "--max-old-space-size" argument.
421
+ * Add another 80MB to get RSS usage / memory limits.
422
+ */
423
+ memoryLimitMB?: number;
424
+
425
+ /**
426
+ * If specified, ignore any operations newer than this when compacting.
427
+ *
428
+ * This is primarily for tests, where we want to test compacting at a specific
429
+ * point.
430
+ *
431
+ * This can also be used to create a "safe buffer" of recent operations that should
432
+ * not be compacted, to avoid invalidating checkpoints in use.
433
+ */
434
+ maxOpId?: bigint;
435
+
436
+ /**
437
+ * If specified, compact only the specific buckets.
438
+ *
439
+ * If not specified, compacts all buckets.
440
+ */
441
+ compactBuckets?: string[];
442
+ }
443
+
444
+ export interface TerminateOptions {
445
+ /**
446
+ * If true, also clear the storage before terminating.
447
+ */
448
+ clearStorage: boolean;
449
+ }
@@ -1,17 +1,19 @@
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 { logger } from '@powersync/lib-services-framework';
12
+ import { v4 as uuid } from 'uuid';
12
13
  import {
13
14
  ActiveCheckpoint,
14
15
  BucketStorageFactory,
16
+ ParseSyncRulesOptions,
15
17
  PersistedSyncRules,
16
18
  PersistedSyncRulesContent,
17
19
  StorageMetrics,
@@ -23,14 +25,13 @@ import { MongoSyncBucketStorage } from './mongo/MongoSyncBucketStorage.js';
23
25
  import { PowerSyncMongo, PowerSyncMongoOptions } from './mongo/db.js';
24
26
  import { SyncRuleDocument, SyncRuleState } from './mongo/models.js';
25
27
  import { generateSlotName } from './mongo/util.js';
26
- import { v4 as uuid } from 'uuid';
27
- import { logger } from '@powersync/lib-services-framework';
28
28
 
29
29
  export interface MongoBucketStorageOptions extends PowerSyncMongoOptions {}
30
30
 
31
31
  export class MongoBucketStorage implements BucketStorageFactory {
32
32
  private readonly client: mongo.MongoClient;
33
33
  private readonly session: mongo.ClientSession;
34
+ // TODO: This is still Postgres specific and needs to be reworked
34
35
  public readonly slot_name_prefix: string;
35
36
 
36
37
  private readonly storageCache = new LRUCache<number, MongoSyncBucketStorage>({
@@ -47,8 +48,7 @@ export class MongoBucketStorage implements BucketStorageFactory {
47
48
  return undefined;
48
49
  }
49
50
  const rules = new MongoPersistedSyncRulesContent(this.db, doc2);
50
- const storage = this.getInstance(rules.parsed());
51
- return storage;
51
+ return this.getInstance(rules);
52
52
  }
53
53
  });
54
54
 
@@ -61,12 +61,12 @@ export class MongoBucketStorage implements BucketStorageFactory {
61
61
  this.slot_name_prefix = options.slot_name_prefix;
62
62
  }
63
63
 
64
- getInstance(options: PersistedSyncRules): MongoSyncBucketStorage {
65
- let { id, sync_rules, slot_name } = options;
64
+ getInstance(options: PersistedSyncRulesContent): MongoSyncBucketStorage {
65
+ let { id, slot_name } = options;
66
66
  if ((typeof id as any) == 'bigint') {
67
67
  id = Number(id);
68
68
  }
69
- return new MongoSyncBucketStorage(this, id, sync_rules, slot_name);
69
+ return new MongoSyncBucketStorage(this, id, options, slot_name);
70
70
  }
71
71
 
72
72
  async configureSyncRules(sync_rules: string, options?: { lock?: boolean }) {
@@ -136,7 +136,12 @@ export class MongoBucketStorage implements BucketStorageFactory {
136
136
 
137
137
  async updateSyncRules(options: UpdateSyncRulesOptions): Promise<MongoPersistedSyncRulesContent> {
138
138
  // Parse and validate before applying any changes
139
- const parsed = SqlSyncRules.fromYaml(options.content);
139
+ const parsed = SqlSyncRules.fromYaml(options.content, {
140
+ // No schema-based validation at this point
141
+ schema: undefined,
142
+ defaultSchema: 'not_applicable', // Not needed for validation
143
+ throwOnError: true
144
+ });
140
145
 
141
146
  let rules: MongoPersistedSyncRulesContent | undefined = undefined;
142
147
 
@@ -204,9 +209,9 @@ export class MongoBucketStorage implements BucketStorageFactory {
204
209
  return new MongoPersistedSyncRulesContent(this.db, doc);
205
210
  }
206
211
 
207
- async getActiveSyncRules(): Promise<PersistedSyncRules | null> {
212
+ async getActiveSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null> {
208
213
  const content = await this.getActiveSyncRulesContent();
209
- return content?.parsed() ?? null;
214
+ return content?.parsed(options) ?? null;
210
215
  }
211
216
 
212
217
  async getNextSyncRulesContent(): Promise<MongoPersistedSyncRulesContent | null> {
@@ -223,9 +228,9 @@ export class MongoBucketStorage implements BucketStorageFactory {
223
228
  return new MongoPersistedSyncRulesContent(this.db, doc);
224
229
  }
225
230
 
226
- async getNextSyncRules(): Promise<PersistedSyncRules | null> {
231
+ async getNextSyncRules(options: ParseSyncRulesOptions): Promise<PersistedSyncRules | null> {
227
232
  const content = await this.getNextSyncRulesContent();
228
- return content?.parsed() ?? null;
233
+ return content?.parsed(options) ?? null;
229
234
  }
230
235
 
231
236
  async getReplicatingSyncRules(): Promise<PersistedSyncRulesContent[]> {
@@ -294,14 +299,6 @@ export class MongoBucketStorage implements BucketStorageFactory {
294
299
  }
295
300
 
296
301
  async getStorageMetrics(): Promise<StorageMetrics> {
297
- const active_sync_rules = await this.getActiveSyncRules();
298
- if (active_sync_rules == null) {
299
- return {
300
- operations_size_bytes: 0,
301
- parameters_size_bytes: 0,
302
- replication_size_bytes: 0
303
- };
304
- }
305
302
  const operations_aggregate = await this.db.bucket_data
306
303
 
307
304
  .aggregate([
@@ -370,7 +367,7 @@ export class MongoBucketStorage implements BucketStorageFactory {
370
367
  private makeActiveCheckpoint(doc: SyncRuleDocument | null) {
371
368
  return {
372
369
  checkpoint: util.timestampToOpId(doc?.last_checkpoint ?? 0n),
373
- lsn: doc?.last_checkpoint_lsn ?? replication.ZERO_LSN,
370
+ lsn: doc?.last_checkpoint_lsn ?? null,
374
371
  hasSyncRules() {
375
372
  return doc != null;
376
373
  },
@@ -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
  /**
@@ -28,11 +26,11 @@ export class SourceTable {
28
26
  constructor(
29
27
  public readonly id: any,
30
28
  public readonly connectionTag: string,
31
- public readonly relationId: number,
29
+ public readonly objectId: number | string,
32
30
  public readonly schema: string,
33
31
  public readonly table: string,
34
32
 
35
- public readonly replicaIdColumns: replication.ReplicationColumn[],
33
+ public readonly replicaIdColumns: ColumnDescriptor[],
36
34
  public readonly snapshotComplete: boolean
37
35
  ) {}
38
36
 
@@ -0,0 +1,55 @@
1
+ import { ResolvedPowerSyncConfig } from '../util/util-index.js';
2
+ import { BucketStorageFactory } from './BucketStorage.js';
3
+ import { BucketStorageProvider, ActiveStorage } from './StorageProvider.js';
4
+ import { logger } from '@powersync/lib-services-framework';
5
+
6
+ export type StorageEngineOptions = {
7
+ configuration: ResolvedPowerSyncConfig;
8
+ };
9
+
10
+ export class StorageEngine {
11
+ // TODO: This will need to revisited when we actually support multiple storage providers.
12
+ private storageProviders: Map<string, BucketStorageProvider> = new Map();
13
+ private currentActiveStorage: ActiveStorage | null = null;
14
+
15
+ constructor(private options: StorageEngineOptions) {}
16
+
17
+ get activeBucketStorage(): BucketStorageFactory {
18
+ return this.activeStorage.storage;
19
+ }
20
+
21
+ get activeStorage(): ActiveStorage {
22
+ if (!this.currentActiveStorage) {
23
+ throw new Error(`No storage provider has been initialized yet.`);
24
+ }
25
+
26
+ return this.currentActiveStorage;
27
+ }
28
+
29
+ /**
30
+ * Register a provider which generates a {@link BucketStorageFactory}
31
+ * given the matching config specified in the loaded {@link ResolvedPowerSyncConfig}
32
+ */
33
+ registerProvider(provider: BucketStorageProvider) {
34
+ this.storageProviders.set(provider.type, provider);
35
+ }
36
+
37
+ public async start(): Promise<void> {
38
+ logger.info('Starting Storage Engine...');
39
+ const { configuration } = this.options;
40
+ this.currentActiveStorage = await this.storageProviders.get(configuration.storage.type)!.getStorage({
41
+ resolvedConfig: configuration
42
+ });
43
+ logger.info(`Successfully activated storage: ${configuration.storage.type}.`);
44
+ logger.info('Successfully started Storage Engine.');
45
+ }
46
+
47
+ /**
48
+ * Shutdown the storage engine, safely shutting down any activated storage providers.
49
+ */
50
+ public async shutDown(): Promise<void> {
51
+ logger.info('Shutting down Storage Engine...');
52
+ await this.currentActiveStorage?.shutDown();
53
+ logger.info('Successfully shut down Storage Engine.');
54
+ }
55
+ }
@@ -0,0 +1,27 @@
1
+ import { BucketStorageFactory } from './BucketStorage.js';
2
+ import * as util from '../util/util-index.js';
3
+
4
+ export interface ActiveStorage {
5
+ storage: BucketStorageFactory;
6
+ shutDown(): Promise<void>;
7
+
8
+ /**
9
+ * Tear down / drop the storage permanently
10
+ */
11
+ tearDown(): Promise<boolean>;
12
+ }
13
+
14
+ export interface GetStorageOptions {
15
+ // TODO: This should just be the storage config. Update once the slot name prefix coupling has been removed from the storage
16
+ resolvedConfig: util.ResolvedPowerSyncConfig;
17
+ }
18
+
19
+ export interface BucketStorageProvider {
20
+ /**
21
+ * The storage type that this provider provides.
22
+ * The type should match the `type` field in the config.
23
+ */
24
+ type: string;
25
+
26
+ getStorage(options: GetStorageOptions): Promise<ActiveStorage>;
27
+ }
@@ -2,9 +2,8 @@ import { SqliteRow, SqlSyncRules } from '@powersync/service-sync-rules';
2
2
  import * as bson from 'bson';
3
3
  import * as mongo from 'mongodb';
4
4
 
5
- import * as util from '../../util/util-index.js';
6
- import * as replication from '../../replication/replication-index.js';
7
5
  import { container, errors, logger } from '@powersync/lib-services-framework';
6
+ import * as util from '../../util/util-index.js';
8
7
  import { BucketStorageBatch, FlushedResult, mergeToast, SaveOptions } from '../BucketStorage.js';
9
8
  import { SourceTable } from '../SourceTable.js';
10
9
  import { PowerSyncMongo } from './db.js';
@@ -12,7 +11,7 @@ import { CurrentBucket, CurrentDataDocument, SourceKey } from './models.js';
12
11
  import { MongoIdSequence } from './MongoIdSequence.js';
13
12
  import { cacheKey, OperationBatch, RecordOperation } from './OperationBatch.js';
14
13
  import { PersistedBatch } from './PersistedBatch.js';
15
- import { BSON_DESERIALIZE_OPTIONS, idPrefixFilter, serializeLookup } from './util.js';
14
+ import { BSON_DESERIALIZE_OPTIONS, idPrefixFilter, replicaIdEquals, serializeLookup } from './util.js';
16
15
 
17
16
  /**
18
17
  * 15MB
@@ -25,6 +24,7 @@ const MAX_ROW_SIZE = 15 * 1024 * 1024;
25
24
  //
26
25
  // In the future, we can investigate allowing multiple replication streams operating independently.
27
26
  const replicationMutex = new util.Mutex();
27
+
28
28
  export class MongoBucketBatch implements BucketStorageBatch {
29
29
  private readonly client: mongo.MongoClient;
30
30
  public readonly db: PowerSyncMongo;
@@ -61,7 +61,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
61
61
  group_id: number,
62
62
  slot_name: string,
63
63
  last_checkpoint_lsn: string | null,
64
- no_checkpoint_before_lsn: string | null
64
+ no_checkpoint_before_lsn: string
65
65
  ) {
66
66
  this.db = db;
67
67
  this.client = db.client;
@@ -70,7 +70,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
70
70
  this.slot_name = slot_name;
71
71
  this.session = this.client.startSession();
72
72
  this.last_checkpoint_lsn = last_checkpoint_lsn;
73
- this.no_checkpoint_before_lsn = no_checkpoint_before_lsn ?? replication.ZERO_LSN;
73
+ this.no_checkpoint_before_lsn = no_checkpoint_before_lsn;
74
74
  }
75
75
 
76
76
  async flush(): Promise<FlushedResult | null> {
@@ -301,7 +301,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
301
301
  }
302
302
 
303
303
  // 2. Save bucket data
304
- if (beforeId != null && (afterId == null || !beforeId.equals(afterId))) {
304
+ if (beforeId != null && (afterId == null || !replicaIdEquals(beforeId, afterId))) {
305
305
  // Source ID updated
306
306
  if (sourceTable.syncData) {
307
307
  // Delete old record
@@ -431,7 +431,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
431
431
  };
432
432
  }
433
433
 
434
- if (afterId == null || !beforeId.equals(afterId)) {
434
+ if (afterId == null || !replicaIdEquals(beforeId, afterId)) {
435
435
  // Either a delete (afterId == null), or replaced the old replication id
436
436
  batch.deleteCurrentData(before_key);
437
437
  }
@@ -743,7 +743,7 @@ export class MongoBucketBatch implements BucketStorageBatch {
743
743
  const copy = new SourceTable(
744
744
  table.id,
745
745
  table.connectionTag,
746
- table.relationId,
746
+ table.objectId,
747
747
  table.schema,
748
748
  table.table,
749
749
  table.replicaIdColumns,