@powersync/service-core 0.0.0-dev-20240620165206

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 (454) hide show
  1. package/.probes/.gitkeep +0 -0
  2. package/CHANGELOG.md +82 -0
  3. package/LICENSE +67 -0
  4. package/README.md +3 -0
  5. package/dist/api/api-index.d.ts +2 -0
  6. package/dist/api/api-index.js +3 -0
  7. package/dist/api/api-index.js.map +1 -0
  8. package/dist/api/diagnostics.d.ts +21 -0
  9. package/dist/api/diagnostics.js +183 -0
  10. package/dist/api/diagnostics.js.map +1 -0
  11. package/dist/api/schema.d.ts +5 -0
  12. package/dist/api/schema.js +88 -0
  13. package/dist/api/schema.js.map +1 -0
  14. package/dist/auth/CachedKeyCollector.d.ts +46 -0
  15. package/dist/auth/CachedKeyCollector.js +116 -0
  16. package/dist/auth/CachedKeyCollector.js.map +1 -0
  17. package/dist/auth/CompoundKeyCollector.d.ts +8 -0
  18. package/dist/auth/CompoundKeyCollector.js +23 -0
  19. package/dist/auth/CompoundKeyCollector.js.map +1 -0
  20. package/dist/auth/JwtPayload.d.ts +10 -0
  21. package/dist/auth/JwtPayload.js +2 -0
  22. package/dist/auth/JwtPayload.js.map +1 -0
  23. package/dist/auth/KeyCollector.d.ts +24 -0
  24. package/dist/auth/KeyCollector.js +2 -0
  25. package/dist/auth/KeyCollector.js.map +1 -0
  26. package/dist/auth/KeySpec.d.ts +26 -0
  27. package/dist/auth/KeySpec.js +49 -0
  28. package/dist/auth/KeySpec.js.map +1 -0
  29. package/dist/auth/KeyStore.d.ts +39 -0
  30. package/dist/auth/KeyStore.js +131 -0
  31. package/dist/auth/KeyStore.js.map +1 -0
  32. package/dist/auth/LeakyBucket.d.ts +39 -0
  33. package/dist/auth/LeakyBucket.js +57 -0
  34. package/dist/auth/LeakyBucket.js.map +1 -0
  35. package/dist/auth/RemoteJWKSCollector.d.ts +24 -0
  36. package/dist/auth/RemoteJWKSCollector.js +106 -0
  37. package/dist/auth/RemoteJWKSCollector.js.map +1 -0
  38. package/dist/auth/StaticKeyCollector.d.ts +14 -0
  39. package/dist/auth/StaticKeyCollector.js +19 -0
  40. package/dist/auth/StaticKeyCollector.js.map +1 -0
  41. package/dist/auth/SupabaseKeyCollector.d.ts +22 -0
  42. package/dist/auth/SupabaseKeyCollector.js +61 -0
  43. package/dist/auth/SupabaseKeyCollector.js.map +1 -0
  44. package/dist/auth/auth-index.d.ts +10 -0
  45. package/dist/auth/auth-index.js +11 -0
  46. package/dist/auth/auth-index.js.map +1 -0
  47. package/dist/db/db-index.d.ts +1 -0
  48. package/dist/db/db-index.js +2 -0
  49. package/dist/db/db-index.js.map +1 -0
  50. package/dist/db/mongo.d.ts +29 -0
  51. package/dist/db/mongo.js +65 -0
  52. package/dist/db/mongo.js.map +1 -0
  53. package/dist/entry/cli-entry.d.ts +15 -0
  54. package/dist/entry/cli-entry.js +36 -0
  55. package/dist/entry/cli-entry.js.map +1 -0
  56. package/dist/entry/commands/config-command.d.ts +10 -0
  57. package/dist/entry/commands/config-command.js +21 -0
  58. package/dist/entry/commands/config-command.js.map +1 -0
  59. package/dist/entry/commands/migrate-action.d.ts +2 -0
  60. package/dist/entry/commands/migrate-action.js +18 -0
  61. package/dist/entry/commands/migrate-action.js.map +1 -0
  62. package/dist/entry/commands/start-action.d.ts +3 -0
  63. package/dist/entry/commands/start-action.js +15 -0
  64. package/dist/entry/commands/start-action.js.map +1 -0
  65. package/dist/entry/commands/teardown-action.d.ts +2 -0
  66. package/dist/entry/commands/teardown-action.js +17 -0
  67. package/dist/entry/commands/teardown-action.js.map +1 -0
  68. package/dist/entry/entry-index.d.ts +5 -0
  69. package/dist/entry/entry-index.js +6 -0
  70. package/dist/entry/entry-index.js.map +1 -0
  71. package/dist/index.d.ts +25 -0
  72. package/dist/index.js +28 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/locks/LockManager.d.ts +10 -0
  75. package/dist/locks/LockManager.js +7 -0
  76. package/dist/locks/LockManager.js.map +1 -0
  77. package/dist/locks/MongoLocks.d.ts +36 -0
  78. package/dist/locks/MongoLocks.js +81 -0
  79. package/dist/locks/MongoLocks.js.map +1 -0
  80. package/dist/locks/locks-index.d.ts +2 -0
  81. package/dist/locks/locks-index.js +3 -0
  82. package/dist/locks/locks-index.js.map +1 -0
  83. package/dist/metrics/Metrics.d.ts +30 -0
  84. package/dist/metrics/Metrics.js +176 -0
  85. package/dist/metrics/Metrics.js.map +1 -0
  86. package/dist/migrations/db/migrations/1684951997326-init.d.ts +3 -0
  87. package/dist/migrations/db/migrations/1684951997326-init.js +31 -0
  88. package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -0
  89. package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.d.ts +2 -0
  90. package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js +5 -0
  91. package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js.map +1 -0
  92. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +3 -0
  93. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +54 -0
  94. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -0
  95. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +3 -0
  96. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +27 -0
  97. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -0
  98. package/dist/migrations/definitions.d.ts +18 -0
  99. package/dist/migrations/definitions.js +6 -0
  100. package/dist/migrations/definitions.js.map +1 -0
  101. package/dist/migrations/executor.d.ts +16 -0
  102. package/dist/migrations/executor.js +64 -0
  103. package/dist/migrations/executor.js.map +1 -0
  104. package/dist/migrations/migrations-index.d.ts +3 -0
  105. package/dist/migrations/migrations-index.js +4 -0
  106. package/dist/migrations/migrations-index.js.map +1 -0
  107. package/dist/migrations/migrations.d.ts +10 -0
  108. package/dist/migrations/migrations.js +90 -0
  109. package/dist/migrations/migrations.js.map +1 -0
  110. package/dist/migrations/store/migration-store.d.ts +11 -0
  111. package/dist/migrations/store/migration-store.js +46 -0
  112. package/dist/migrations/store/migration-store.js.map +1 -0
  113. package/dist/replication/ErrorRateLimiter.d.ts +17 -0
  114. package/dist/replication/ErrorRateLimiter.js +43 -0
  115. package/dist/replication/ErrorRateLimiter.js.map +1 -0
  116. package/dist/replication/PgRelation.d.ts +16 -0
  117. package/dist/replication/PgRelation.js +26 -0
  118. package/dist/replication/PgRelation.js.map +1 -0
  119. package/dist/replication/WalConnection.d.ts +34 -0
  120. package/dist/replication/WalConnection.js +190 -0
  121. package/dist/replication/WalConnection.js.map +1 -0
  122. package/dist/replication/WalStream.d.ts +57 -0
  123. package/dist/replication/WalStream.js +515 -0
  124. package/dist/replication/WalStream.js.map +1 -0
  125. package/dist/replication/WalStreamManager.d.ts +30 -0
  126. package/dist/replication/WalStreamManager.js +198 -0
  127. package/dist/replication/WalStreamManager.js.map +1 -0
  128. package/dist/replication/WalStreamRunner.d.ts +38 -0
  129. package/dist/replication/WalStreamRunner.js +155 -0
  130. package/dist/replication/WalStreamRunner.js.map +1 -0
  131. package/dist/replication/replication-index.d.ts +7 -0
  132. package/dist/replication/replication-index.js +8 -0
  133. package/dist/replication/replication-index.js.map +1 -0
  134. package/dist/replication/util.d.ts +9 -0
  135. package/dist/replication/util.js +62 -0
  136. package/dist/replication/util.js.map +1 -0
  137. package/dist/routes/auth.d.ts +56 -0
  138. package/dist/routes/auth.js +182 -0
  139. package/dist/routes/auth.js.map +1 -0
  140. package/dist/routes/endpoints/admin.d.ts +1011 -0
  141. package/dist/routes/endpoints/admin.js +207 -0
  142. package/dist/routes/endpoints/admin.js.map +1 -0
  143. package/dist/routes/endpoints/checkpointing.d.ts +76 -0
  144. package/dist/routes/endpoints/checkpointing.js +36 -0
  145. package/dist/routes/endpoints/checkpointing.js.map +1 -0
  146. package/dist/routes/endpoints/dev.d.ts +312 -0
  147. package/dist/routes/endpoints/dev.js +172 -0
  148. package/dist/routes/endpoints/dev.js.map +1 -0
  149. package/dist/routes/endpoints/route-endpoints-index.d.ts +6 -0
  150. package/dist/routes/endpoints/route-endpoints-index.js +7 -0
  151. package/dist/routes/endpoints/route-endpoints-index.js.map +1 -0
  152. package/dist/routes/endpoints/socket-route.d.ts +2 -0
  153. package/dist/routes/endpoints/socket-route.js +119 -0
  154. package/dist/routes/endpoints/socket-route.js.map +1 -0
  155. package/dist/routes/endpoints/sync-rules.d.ts +174 -0
  156. package/dist/routes/endpoints/sync-rules.js +202 -0
  157. package/dist/routes/endpoints/sync-rules.js.map +1 -0
  158. package/dist/routes/endpoints/sync-stream.d.ts +132 -0
  159. package/dist/routes/endpoints/sync-stream.js +83 -0
  160. package/dist/routes/endpoints/sync-stream.js.map +1 -0
  161. package/dist/routes/hooks.d.ts +10 -0
  162. package/dist/routes/hooks.js +32 -0
  163. package/dist/routes/hooks.js.map +1 -0
  164. package/dist/routes/route-register.d.ts +10 -0
  165. package/dist/routes/route-register.js +87 -0
  166. package/dist/routes/route-register.js.map +1 -0
  167. package/dist/routes/router-socket.d.ts +10 -0
  168. package/dist/routes/router-socket.js +5 -0
  169. package/dist/routes/router-socket.js.map +1 -0
  170. package/dist/routes/router.d.ts +26 -0
  171. package/dist/routes/router.js +7 -0
  172. package/dist/routes/router.js.map +1 -0
  173. package/dist/routes/routes-index.d.ts +6 -0
  174. package/dist/routes/routes-index.js +7 -0
  175. package/dist/routes/routes-index.js.map +1 -0
  176. package/dist/runner/teardown.d.ts +2 -0
  177. package/dist/runner/teardown.js +94 -0
  178. package/dist/runner/teardown.js.map +1 -0
  179. package/dist/storage/BucketStorage.d.ts +307 -0
  180. package/dist/storage/BucketStorage.js +25 -0
  181. package/dist/storage/BucketStorage.js.map +1 -0
  182. package/dist/storage/ChecksumCache.d.ts +50 -0
  183. package/dist/storage/ChecksumCache.js +234 -0
  184. package/dist/storage/ChecksumCache.js.map +1 -0
  185. package/dist/storage/MongoBucketStorage.d.ts +52 -0
  186. package/dist/storage/MongoBucketStorage.js +409 -0
  187. package/dist/storage/MongoBucketStorage.js.map +1 -0
  188. package/dist/storage/SourceTable.d.ts +39 -0
  189. package/dist/storage/SourceTable.js +50 -0
  190. package/dist/storage/SourceTable.js.map +1 -0
  191. package/dist/storage/mongo/MongoBucketBatch.d.ts +48 -0
  192. package/dist/storage/mongo/MongoBucketBatch.js +581 -0
  193. package/dist/storage/mongo/MongoBucketBatch.js.map +1 -0
  194. package/dist/storage/mongo/MongoIdSequence.d.ts +12 -0
  195. package/dist/storage/mongo/MongoIdSequence.js +21 -0
  196. package/dist/storage/mongo/MongoIdSequence.js.map +1 -0
  197. package/dist/storage/mongo/MongoPersistedSyncRules.d.ts +9 -0
  198. package/dist/storage/mongo/MongoPersistedSyncRules.js +9 -0
  199. package/dist/storage/mongo/MongoPersistedSyncRules.js.map +1 -0
  200. package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +20 -0
  201. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +26 -0
  202. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -0
  203. package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +29 -0
  204. package/dist/storage/mongo/MongoSyncBucketStorage.js +391 -0
  205. package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -0
  206. package/dist/storage/mongo/MongoSyncRulesLock.d.ts +16 -0
  207. package/dist/storage/mongo/MongoSyncRulesLock.js +65 -0
  208. package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -0
  209. package/dist/storage/mongo/OperationBatch.d.ts +26 -0
  210. package/dist/storage/mongo/OperationBatch.js +101 -0
  211. package/dist/storage/mongo/OperationBatch.js.map +1 -0
  212. package/dist/storage/mongo/PersistedBatch.d.ts +46 -0
  213. package/dist/storage/mongo/PersistedBatch.js +213 -0
  214. package/dist/storage/mongo/PersistedBatch.js.map +1 -0
  215. package/dist/storage/mongo/db.d.ts +26 -0
  216. package/dist/storage/mongo/db.js +35 -0
  217. package/dist/storage/mongo/db.js.map +1 -0
  218. package/dist/storage/mongo/models.d.ts +140 -0
  219. package/dist/storage/mongo/models.js +27 -0
  220. package/dist/storage/mongo/models.js.map +1 -0
  221. package/dist/storage/mongo/util.d.ts +26 -0
  222. package/dist/storage/mongo/util.js +81 -0
  223. package/dist/storage/mongo/util.js.map +1 -0
  224. package/dist/storage/storage-index.d.ts +14 -0
  225. package/dist/storage/storage-index.js +15 -0
  226. package/dist/storage/storage-index.js.map +1 -0
  227. package/dist/sync/BroadcastIterable.d.ts +38 -0
  228. package/dist/sync/BroadcastIterable.js +153 -0
  229. package/dist/sync/BroadcastIterable.js.map +1 -0
  230. package/dist/sync/LastValueSink.d.ts +25 -0
  231. package/dist/sync/LastValueSink.js +84 -0
  232. package/dist/sync/LastValueSink.js.map +1 -0
  233. package/dist/sync/merge.d.ts +39 -0
  234. package/dist/sync/merge.js +175 -0
  235. package/dist/sync/merge.js.map +1 -0
  236. package/dist/sync/safeRace.d.ts +1 -0
  237. package/dist/sync/safeRace.js +91 -0
  238. package/dist/sync/safeRace.js.map +1 -0
  239. package/dist/sync/sync-index.d.ts +6 -0
  240. package/dist/sync/sync-index.js +7 -0
  241. package/dist/sync/sync-index.js.map +1 -0
  242. package/dist/sync/sync.d.ts +18 -0
  243. package/dist/sync/sync.js +259 -0
  244. package/dist/sync/sync.js.map +1 -0
  245. package/dist/sync/util.d.ts +26 -0
  246. package/dist/sync/util.js +73 -0
  247. package/dist/sync/util.js.map +1 -0
  248. package/dist/system/CorePowerSyncSystem.d.ts +23 -0
  249. package/dist/system/CorePowerSyncSystem.js +52 -0
  250. package/dist/system/CorePowerSyncSystem.js.map +1 -0
  251. package/dist/system/system-index.d.ts +1 -0
  252. package/dist/system/system-index.js +2 -0
  253. package/dist/system/system-index.js.map +1 -0
  254. package/dist/util/Mutex.d.ts +47 -0
  255. package/dist/util/Mutex.js +132 -0
  256. package/dist/util/Mutex.js.map +1 -0
  257. package/dist/util/PgManager.d.ts +24 -0
  258. package/dist/util/PgManager.js +55 -0
  259. package/dist/util/PgManager.js.map +1 -0
  260. package/dist/util/alerting.d.ts +2 -0
  261. package/dist/util/alerting.js +8 -0
  262. package/dist/util/alerting.js.map +1 -0
  263. package/dist/util/config/collectors/config-collector.d.ts +29 -0
  264. package/dist/util/config/collectors/config-collector.js +116 -0
  265. package/dist/util/config/collectors/config-collector.js.map +1 -0
  266. package/dist/util/config/collectors/impl/base64-config-collector.d.ts +6 -0
  267. package/dist/util/config/collectors/impl/base64-config-collector.js +15 -0
  268. package/dist/util/config/collectors/impl/base64-config-collector.js.map +1 -0
  269. package/dist/util/config/collectors/impl/fallback-config-collector.d.ts +11 -0
  270. package/dist/util/config/collectors/impl/fallback-config-collector.js +19 -0
  271. package/dist/util/config/collectors/impl/fallback-config-collector.js.map +1 -0
  272. package/dist/util/config/collectors/impl/filesystem-config-collector.d.ts +6 -0
  273. package/dist/util/config/collectors/impl/filesystem-config-collector.js +37 -0
  274. package/dist/util/config/collectors/impl/filesystem-config-collector.js.map +1 -0
  275. package/dist/util/config/compound-config-collector.d.ts +32 -0
  276. package/dist/util/config/compound-config-collector.js +130 -0
  277. package/dist/util/config/compound-config-collector.js.map +1 -0
  278. package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.d.ts +7 -0
  279. package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js +17 -0
  280. package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js.map +1 -0
  281. package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.d.ts +7 -0
  282. package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js +21 -0
  283. package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js.map +1 -0
  284. package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.d.ts +7 -0
  285. package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js +17 -0
  286. package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js.map +1 -0
  287. package/dist/util/config/sync-rules/sync-collector.d.ts +6 -0
  288. package/dist/util/config/sync-rules/sync-collector.js +3 -0
  289. package/dist/util/config/sync-rules/sync-collector.js.map +1 -0
  290. package/dist/util/config/types.d.ts +57 -0
  291. package/dist/util/config/types.js +7 -0
  292. package/dist/util/config/types.js.map +1 -0
  293. package/dist/util/config.d.ts +7 -0
  294. package/dist/util/config.js +35 -0
  295. package/dist/util/config.js.map +1 -0
  296. package/dist/util/env.d.ts +9 -0
  297. package/dist/util/env.js +26 -0
  298. package/dist/util/env.js.map +1 -0
  299. package/dist/util/memory-tracking.d.ts +7 -0
  300. package/dist/util/memory-tracking.js +58 -0
  301. package/dist/util/memory-tracking.js.map +1 -0
  302. package/dist/util/migration_lib.d.ts +11 -0
  303. package/dist/util/migration_lib.js +64 -0
  304. package/dist/util/migration_lib.js.map +1 -0
  305. package/dist/util/pgwire_utils.d.ts +24 -0
  306. package/dist/util/pgwire_utils.js +117 -0
  307. package/dist/util/pgwire_utils.js.map +1 -0
  308. package/dist/util/populate_test_data.d.ts +8 -0
  309. package/dist/util/populate_test_data.js +65 -0
  310. package/dist/util/populate_test_data.js.map +1 -0
  311. package/dist/util/protocol-types.d.ts +182 -0
  312. package/dist/util/protocol-types.js +42 -0
  313. package/dist/util/protocol-types.js.map +1 -0
  314. package/dist/util/secs.d.ts +2 -0
  315. package/dist/util/secs.js +49 -0
  316. package/dist/util/secs.js.map +1 -0
  317. package/dist/util/util-index.d.ts +22 -0
  318. package/dist/util/util-index.js +23 -0
  319. package/dist/util/util-index.js.map +1 -0
  320. package/dist/util/utils.d.ts +17 -0
  321. package/dist/util/utils.js +92 -0
  322. package/dist/util/utils.js.map +1 -0
  323. package/package.json +59 -0
  324. package/src/api/api-index.ts +2 -0
  325. package/src/api/diagnostics.ts +221 -0
  326. package/src/api/schema.ts +99 -0
  327. package/src/auth/CachedKeyCollector.ts +132 -0
  328. package/src/auth/CompoundKeyCollector.ts +33 -0
  329. package/src/auth/JwtPayload.ts +11 -0
  330. package/src/auth/KeyCollector.ts +27 -0
  331. package/src/auth/KeySpec.ts +67 -0
  332. package/src/auth/KeyStore.ts +156 -0
  333. package/src/auth/LeakyBucket.ts +66 -0
  334. package/src/auth/RemoteJWKSCollector.ts +130 -0
  335. package/src/auth/StaticKeyCollector.ts +21 -0
  336. package/src/auth/SupabaseKeyCollector.ts +67 -0
  337. package/src/auth/auth-index.ts +10 -0
  338. package/src/db/db-index.ts +1 -0
  339. package/src/db/mongo.ts +72 -0
  340. package/src/entry/cli-entry.ts +40 -0
  341. package/src/entry/commands/config-command.ts +36 -0
  342. package/src/entry/commands/migrate-action.ts +25 -0
  343. package/src/entry/commands/start-action.ts +24 -0
  344. package/src/entry/commands/teardown-action.ts +23 -0
  345. package/src/entry/entry-index.ts +5 -0
  346. package/src/index.ts +40 -0
  347. package/src/locks/LockManager.ts +16 -0
  348. package/src/locks/MongoLocks.ts +142 -0
  349. package/src/locks/locks-index.ts +2 -0
  350. package/src/metrics/Metrics.ts +265 -0
  351. package/src/migrations/db/migrations/1684951997326-init.ts +33 -0
  352. package/src/migrations/db/migrations/1688556755264-initial-sync-rules.ts +5 -0
  353. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +99 -0
  354. package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +32 -0
  355. package/src/migrations/definitions.ts +21 -0
  356. package/src/migrations/executor.ts +87 -0
  357. package/src/migrations/migrations-index.ts +3 -0
  358. package/src/migrations/migrations.ts +118 -0
  359. package/src/migrations/store/migration-store.ts +63 -0
  360. package/src/replication/ErrorRateLimiter.ts +50 -0
  361. package/src/replication/PgRelation.ts +42 -0
  362. package/src/replication/WalConnection.ts +227 -0
  363. package/src/replication/WalStream.ts +624 -0
  364. package/src/replication/WalStreamManager.ts +213 -0
  365. package/src/replication/WalStreamRunner.ts +180 -0
  366. package/src/replication/replication-index.ts +7 -0
  367. package/src/replication/util.ts +76 -0
  368. package/src/routes/auth.ts +215 -0
  369. package/src/routes/endpoints/admin.ts +237 -0
  370. package/src/routes/endpoints/checkpointing.ts +41 -0
  371. package/src/routes/endpoints/dev.ts +199 -0
  372. package/src/routes/endpoints/route-endpoints-index.ts +6 -0
  373. package/src/routes/endpoints/socket-route.ts +135 -0
  374. package/src/routes/endpoints/sync-rules.ts +227 -0
  375. package/src/routes/endpoints/sync-stream.ts +101 -0
  376. package/src/routes/hooks.ts +46 -0
  377. package/src/routes/route-register.ts +104 -0
  378. package/src/routes/router-socket.ts +13 -0
  379. package/src/routes/router.ts +46 -0
  380. package/src/routes/routes-index.ts +6 -0
  381. package/src/runner/teardown.ts +108 -0
  382. package/src/storage/BucketStorage.ts +396 -0
  383. package/src/storage/ChecksumCache.ts +294 -0
  384. package/src/storage/MongoBucketStorage.ts +519 -0
  385. package/src/storage/SourceTable.ts +60 -0
  386. package/src/storage/mongo/MongoBucketBatch.ts +752 -0
  387. package/src/storage/mongo/MongoIdSequence.ts +24 -0
  388. package/src/storage/mongo/MongoPersistedSyncRules.ts +16 -0
  389. package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +47 -0
  390. package/src/storage/mongo/MongoSyncBucketStorage.ts +533 -0
  391. package/src/storage/mongo/MongoSyncRulesLock.ts +81 -0
  392. package/src/storage/mongo/OperationBatch.ts +115 -0
  393. package/src/storage/mongo/PersistedBatch.ts +268 -0
  394. package/src/storage/mongo/db.ts +73 -0
  395. package/src/storage/mongo/models.ts +162 -0
  396. package/src/storage/mongo/util.ts +88 -0
  397. package/src/storage/storage-index.ts +15 -0
  398. package/src/sync/BroadcastIterable.ts +161 -0
  399. package/src/sync/LastValueSink.ts +100 -0
  400. package/src/sync/merge.ts +200 -0
  401. package/src/sync/safeRace.ts +99 -0
  402. package/src/sync/sync-index.ts +6 -0
  403. package/src/sync/sync.ts +319 -0
  404. package/src/sync/util.ts +98 -0
  405. package/src/system/CorePowerSyncSystem.ts +64 -0
  406. package/src/system/system-index.ts +1 -0
  407. package/src/util/Mutex.ts +159 -0
  408. package/src/util/PgManager.ts +64 -0
  409. package/src/util/alerting.ts +9 -0
  410. package/src/util/config/collectors/config-collector.ts +143 -0
  411. package/src/util/config/collectors/impl/base64-config-collector.ts +18 -0
  412. package/src/util/config/collectors/impl/fallback-config-collector.ts +22 -0
  413. package/src/util/config/collectors/impl/filesystem-config-collector.ts +43 -0
  414. package/src/util/config/compound-config-collector.ts +176 -0
  415. package/src/util/config/sync-rules/impl/base64-sync-rules-collector.ts +21 -0
  416. package/src/util/config/sync-rules/impl/filesystem-sync-rules-collector.ts +26 -0
  417. package/src/util/config/sync-rules/impl/inline-sync-rules-collector.ts +21 -0
  418. package/src/util/config/sync-rules/sync-collector.ts +8 -0
  419. package/src/util/config/types.ts +66 -0
  420. package/src/util/config.ts +39 -0
  421. package/src/util/env.ts +30 -0
  422. package/src/util/memory-tracking.ts +67 -0
  423. package/src/util/migration_lib.ts +79 -0
  424. package/src/util/pgwire_utils.ts +139 -0
  425. package/src/util/populate_test_data.ts +78 -0
  426. package/src/util/protocol-types.ts +228 -0
  427. package/src/util/secs.ts +54 -0
  428. package/src/util/util-index.ts +25 -0
  429. package/src/util/utils.ts +122 -0
  430. package/test/src/__snapshots__/pg_test.test.ts.snap +256 -0
  431. package/test/src/__snapshots__/sync.test.ts.snap +247 -0
  432. package/test/src/auth.test.ts +342 -0
  433. package/test/src/broadcast_iterable.test.ts +156 -0
  434. package/test/src/checksum_cache.test.ts +436 -0
  435. package/test/src/data_storage.test.ts +1176 -0
  436. package/test/src/env.ts +8 -0
  437. package/test/src/large_batch.test.ts +194 -0
  438. package/test/src/merge_iterable.test.ts +355 -0
  439. package/test/src/pg_test.test.ts +450 -0
  440. package/test/src/schema_changes.test.ts +545 -0
  441. package/test/src/setup.ts +7 -0
  442. package/test/src/slow_tests.test.ts +257 -0
  443. package/test/src/sql_functions.test.ts +254 -0
  444. package/test/src/sql_operators.test.ts +132 -0
  445. package/test/src/sync.test.ts +293 -0
  446. package/test/src/sync_rules.test.ts +1053 -0
  447. package/test/src/util.ts +76 -0
  448. package/test/src/validation.test.ts +63 -0
  449. package/test/src/wal_stream.test.ts +319 -0
  450. package/test/src/wal_stream_utils.ts +147 -0
  451. package/test/tsconfig.json +20 -0
  452. package/tsconfig.json +31 -0
  453. package/tsconfig.tsbuildinfo +1 -0
  454. package/vitest.config.ts +9 -0
package/src/index.ts ADDED
@@ -0,0 +1,40 @@
1
+ // Provides global and namespaced exports
2
+
3
+ export * from './api/api-index.js';
4
+ export * as api from './api/api-index.js';
5
+
6
+ export * from './auth/auth-index.js';
7
+ export * as auth from './auth/auth-index.js';
8
+
9
+ export * from './db/db-index.js';
10
+ export * as db from './db/db-index.js';
11
+
12
+ export * from './entry/entry-index.js';
13
+ export * as entry from './entry/entry-index.js';
14
+
15
+ // Re-export framework for easy use of Container API
16
+ export * as framework from '@powersync/lib-services-framework';
17
+
18
+ export * from './metrics/Metrics.js';
19
+ export * as metrics from './metrics/Metrics.js';
20
+
21
+ export * from './migrations/migrations.js';
22
+ export * as migrations from './migrations/migrations-index.js';
23
+
24
+ export * from './replication/replication-index.js';
25
+ export * as replication from './replication/replication-index.js';
26
+
27
+ export * from './routes/routes-index.js';
28
+ export * as routes from './routes/routes-index.js';
29
+
30
+ export * from './storage/storage-index.js';
31
+ export * as storage from './storage/storage-index.js';
32
+
33
+ export * from './sync/sync-index.js';
34
+ export * as sync from './sync/sync-index.js';
35
+
36
+ export * from './system/CorePowerSyncSystem.js';
37
+ export * as system from './system/system-index.js';
38
+
39
+ export * from './util/util-index.js';
40
+ export * as utils from './util/util-index.js';
@@ -0,0 +1,16 @@
1
+ import * as bson from 'bson';
2
+
3
+ export class LockActiveError extends Error {
4
+ constructor() {
5
+ super('Lock is already active');
6
+ this.name = this.constructor.name;
7
+ }
8
+ }
9
+
10
+ export type LockManager = {
11
+ acquire: () => Promise<bson.ObjectId | null>;
12
+ refresh: (lock_id: bson.ObjectId) => Promise<void>;
13
+ release: (lock_id: bson.ObjectId) => Promise<void>;
14
+
15
+ lock: (handler: (refresh: () => Promise<void>) => Promise<void>) => Promise<void>;
16
+ };
@@ -0,0 +1,142 @@
1
+ import * as mongo from 'mongodb';
2
+ import * as bson from 'bson';
3
+ import { LockActiveError, LockManager } from './LockManager.js';
4
+
5
+ /**
6
+ * Lock Document Schema
7
+ */
8
+ export type Lock = {
9
+ name: string;
10
+ active_lock?: {
11
+ lock_id: bson.ObjectId;
12
+ ts: Date;
13
+ };
14
+ };
15
+
16
+ export type Collection = mongo.Collection<Lock>;
17
+
18
+ export type AcquireLockParams = {
19
+ /**
20
+ * Name of the process/user trying to acquire the lock.
21
+ */
22
+ name: string;
23
+ /**
24
+ * The TTL of the lock (ms). Default: 60000 ms (1 min)
25
+ */
26
+ timeout?: number;
27
+ };
28
+
29
+ const DEFAULT_LOCK_TIMEOUT = 60 * 1000; // 1 minute
30
+
31
+ const acquireLock = async (collection: Collection, params: AcquireLockParams) => {
32
+ const now = new Date();
33
+ const lock_timeout = params.timeout ?? DEFAULT_LOCK_TIMEOUT;
34
+ const lock_id = new bson.ObjectId();
35
+
36
+ await collection.updateOne(
37
+ {
38
+ name: params.name
39
+ },
40
+ {
41
+ $setOnInsert: {
42
+ name: params.name
43
+ }
44
+ },
45
+ {
46
+ upsert: true
47
+ }
48
+ );
49
+
50
+ const expired_ts = now.getTime() - lock_timeout;
51
+
52
+ const res = await collection.updateOne(
53
+ {
54
+ $and: [
55
+ { name: params.name },
56
+ {
57
+ $or: [{ active_lock: { $exists: false } }, { 'active_lock.ts': { $lte: new Date(expired_ts) } }]
58
+ }
59
+ ]
60
+ },
61
+ {
62
+ $set: {
63
+ active_lock: {
64
+ lock_id: lock_id,
65
+ ts: now
66
+ }
67
+ }
68
+ }
69
+ );
70
+
71
+ if (res.modifiedCount === 0) {
72
+ return null;
73
+ }
74
+
75
+ return lock_id;
76
+ };
77
+
78
+ const refreshLock = async (collection: Collection, lock_id: bson.ObjectId) => {
79
+ const res = await collection.updateOne(
80
+ {
81
+ 'active_lock.lock_id': lock_id
82
+ },
83
+ {
84
+ $set: {
85
+ 'active_lock.ts': new Date()
86
+ }
87
+ }
88
+ );
89
+
90
+ if (res.modifiedCount === 0) {
91
+ throw new Error('Lock not found, could not refresh');
92
+ }
93
+ };
94
+
95
+ export const releaseLock = async (collection: Collection, lock_id: bson.ObjectId) => {
96
+ const res = await collection.updateOne(
97
+ {
98
+ 'active_lock.lock_id': lock_id
99
+ },
100
+ {
101
+ $unset: {
102
+ active_lock: true
103
+ }
104
+ }
105
+ );
106
+
107
+ if (res.modifiedCount === 0) {
108
+ throw new Error('Lock not found, could not release');
109
+ }
110
+ };
111
+
112
+ export type CreateLockManagerParams = {
113
+ /**
114
+ * Name of the process/user trying to acquire the lock.
115
+ */
116
+ name: string;
117
+ /**
118
+ * The TTL for each lock (ms). Default: 60000 ms (1 min)
119
+ */
120
+ timeout?: number;
121
+ };
122
+
123
+ export const createMongoLockManager = (collection: Collection, params: CreateLockManagerParams): LockManager => {
124
+ return {
125
+ acquire: () => acquireLock(collection, params),
126
+ refresh: (lock_id: bson.ObjectId) => refreshLock(collection, lock_id),
127
+ release: (lock_id: bson.ObjectId) => releaseLock(collection, lock_id),
128
+
129
+ lock: async (handler) => {
130
+ const lock_id = await acquireLock(collection, params);
131
+ if (!lock_id) {
132
+ throw new LockActiveError();
133
+ }
134
+
135
+ try {
136
+ await handler(() => refreshLock(collection, lock_id));
137
+ } finally {
138
+ await releaseLock(collection, lock_id);
139
+ }
140
+ }
141
+ };
142
+ };
@@ -0,0 +1,2 @@
1
+ export * from './LockManager.js';
2
+ export * from './MongoLocks.js';
@@ -0,0 +1,265 @@
1
+ import { Attributes, Counter, ObservableGauge, UpDownCounter, ValueType } from '@opentelemetry/api';
2
+ import { PrometheusExporter } from '@opentelemetry/exporter-prometheus';
3
+ import { MeterProvider, MetricReader, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
4
+ import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
5
+ import * as jpgwire from '@powersync/service-jpgwire';
6
+ import * as util from '../util/util-index.js';
7
+ import * as storage from '../storage/storage-index.js';
8
+ import { CorePowerSyncSystem } from '../system/CorePowerSyncSystem.js';
9
+ import { Resource } from '@opentelemetry/resources';
10
+ import { logger } from '@powersync/lib-services-framework';
11
+
12
+ export interface MetricsOptions {
13
+ disable_telemetry_sharing: boolean;
14
+ powersync_instance_id: string;
15
+ internal_metrics_endpoint: string;
16
+ }
17
+
18
+ export class Metrics {
19
+ private static instance: Metrics;
20
+
21
+ private prometheusExporter: PrometheusExporter;
22
+ private meterProvider: MeterProvider;
23
+
24
+ // Metrics
25
+ // 1. Data processing / month
26
+
27
+ // 1a. Postgres -> PowerSync
28
+ // Record on replication pod
29
+ public data_replicated_bytes: Counter<Attributes>;
30
+ // 1b. PowerSync -> clients
31
+ // Record on API pod
32
+ public data_synced_bytes: Counter<Attributes>;
33
+ // Unused for pricing
34
+ // Record on replication pod
35
+ public rows_replicated_total: Counter<Attributes>;
36
+ // Unused for pricing
37
+ // Record on replication pod
38
+ public transactions_replicated_total: Counter<Attributes>;
39
+ // Unused for pricing
40
+ // Record on replication pod
41
+ public chunks_replicated_total: Counter<Attributes>;
42
+
43
+ // 2. Sync operations / month
44
+
45
+ // Record on API pod
46
+ public operations_synced_total: Counter<Attributes>;
47
+
48
+ // 3. Data hosted on PowerSync sync service
49
+
50
+ // Record on replication pod
51
+ // 3a. Replication storage -> raw data as received from Postgres.
52
+ public replication_storage_size_bytes: ObservableGauge<Attributes>;
53
+ // 3b. Operations storage -> transformed history, as will be synced to clients
54
+ public operation_storage_size_bytes: ObservableGauge<Attributes>;
55
+ // 3c. Parameter storage -> used for parameter queries
56
+ public parameter_storage_size_bytes: ObservableGauge<Attributes>;
57
+
58
+ // 4. Peak concurrent connections
59
+
60
+ // Record on API pod
61
+ public concurrent_connections: UpDownCounter<Attributes>;
62
+
63
+ private constructor(meterProvider: MeterProvider, prometheusExporter: PrometheusExporter) {
64
+ this.meterProvider = meterProvider;
65
+ this.prometheusExporter = prometheusExporter;
66
+ const meter = meterProvider.getMeter('powersync');
67
+
68
+ this.data_replicated_bytes = meter.createCounter('powersync_data_replicated_bytes_total', {
69
+ description: 'Uncompressed size of replicated data',
70
+ unit: 'bytes',
71
+ valueType: ValueType.INT
72
+ });
73
+
74
+ this.data_synced_bytes = meter.createCounter('powersync_data_synced_bytes_total', {
75
+ description: 'Uncompressed size of synced data',
76
+ unit: 'bytes',
77
+ valueType: ValueType.INT
78
+ });
79
+
80
+ this.rows_replicated_total = meter.createCounter('powersync_rows_replicated_total', {
81
+ description: 'Total number of replicated rows',
82
+ valueType: ValueType.INT
83
+ });
84
+
85
+ this.transactions_replicated_total = meter.createCounter('powersync_transactions_replicated_total', {
86
+ description: 'Total number of replicated transactions',
87
+ valueType: ValueType.INT
88
+ });
89
+
90
+ this.chunks_replicated_total = meter.createCounter('powersync_chunks_replicated_total', {
91
+ description: 'Total number of replication chunks',
92
+ valueType: ValueType.INT
93
+ });
94
+
95
+ this.operations_synced_total = meter.createCounter('powersync_operations_synced_total', {
96
+ description: 'Number of operations synced',
97
+ valueType: ValueType.INT
98
+ });
99
+
100
+ this.replication_storage_size_bytes = meter.createObservableGauge('powersync_replication_storage_size_bytes', {
101
+ description: 'Size of current data stored in PowerSync',
102
+ unit: 'bytes',
103
+ valueType: ValueType.INT
104
+ });
105
+
106
+ this.operation_storage_size_bytes = meter.createObservableGauge('powersync_operation_storage_size_bytes', {
107
+ description: 'Size of operations stored in PowerSync',
108
+ unit: 'bytes',
109
+ valueType: ValueType.INT
110
+ });
111
+
112
+ this.parameter_storage_size_bytes = meter.createObservableGauge('powersync_parameter_storage_size_bytes', {
113
+ description: 'Size of parameter data stored in PowerSync',
114
+ unit: 'bytes',
115
+ valueType: ValueType.INT
116
+ });
117
+
118
+ this.concurrent_connections = meter.createUpDownCounter('powersync_concurrent_connections', {
119
+ description: 'Number of concurrent sync connections',
120
+ valueType: ValueType.INT
121
+ });
122
+ }
123
+
124
+ // Generally only useful for tests. Note: gauges are ignored here.
125
+ resetCounters() {
126
+ this.data_replicated_bytes.add(0);
127
+ this.data_synced_bytes.add(0);
128
+ this.rows_replicated_total.add(0);
129
+ this.transactions_replicated_total.add(0);
130
+ this.chunks_replicated_total.add(0);
131
+ this.operations_synced_total.add(0);
132
+ this.concurrent_connections.add(0);
133
+ }
134
+
135
+ public static getInstance(): Metrics {
136
+ if (!Metrics.instance) {
137
+ throw new Error('Metrics have not been initialised');
138
+ }
139
+
140
+ return Metrics.instance;
141
+ }
142
+
143
+ public static async initialise(options: MetricsOptions): Promise<void> {
144
+ if (Metrics.instance) {
145
+ return;
146
+ }
147
+ logger.info('Configuring telemetry.');
148
+
149
+ logger.info(
150
+ `
151
+ Attention:
152
+ PowerSync collects completely anonymous telemetry regarding usage.
153
+ This information is used to shape our roadmap to better serve our customers.
154
+ You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
155
+ https://docs.powersync.com/self-hosting/telemetry
156
+ Anonymous telemetry is currently: ${options.disable_telemetry_sharing ? 'disabled' : 'enabled'}
157
+ `.trim()
158
+ );
159
+
160
+ const configuredExporters: MetricReader[] = [];
161
+
162
+ const port: number = util.env.METRICS_PORT ?? 0;
163
+ const prometheusExporter = new PrometheusExporter({ port: port, preventServerStart: true });
164
+ configuredExporters.push(prometheusExporter);
165
+
166
+ if (!options.disable_telemetry_sharing) {
167
+ logger.info('Sharing anonymous telemetry');
168
+ const periodicExporter = new PeriodicExportingMetricReader({
169
+ exporter: new OTLPMetricExporter({
170
+ url: options.internal_metrics_endpoint
171
+ }),
172
+ exportIntervalMillis: 1000 * 60 * 5 // 5 minutes
173
+ });
174
+
175
+ configuredExporters.push(periodicExporter);
176
+ }
177
+
178
+ const meterProvider = new MeterProvider({
179
+ resource: new Resource({
180
+ ['service']: 'PowerSync',
181
+ ['instance_id']: options.powersync_instance_id
182
+ }),
183
+ readers: configuredExporters
184
+ });
185
+
186
+ if (port > 0) {
187
+ await prometheusExporter.startServer();
188
+ }
189
+
190
+ Metrics.instance = new Metrics(meterProvider, prometheusExporter);
191
+
192
+ logger.info('Telemetry configuration complete.');
193
+ }
194
+
195
+ public async shutdown(): Promise<void> {
196
+ await this.meterProvider.shutdown();
197
+ }
198
+
199
+ public configureApiMetrics() {
200
+ // Initialize the metric, so that it reports a value before connections
201
+ // have been opened.
202
+ this.concurrent_connections.add(0);
203
+ }
204
+
205
+ public configureReplicationMetrics(system: CorePowerSyncSystem) {
206
+ // Rate limit collection of these stats, since it may be an expensive query
207
+ const MINIMUM_INTERVAL = 60_000;
208
+
209
+ let cachedRequest: Promise<storage.StorageMetrics | null> | undefined = undefined;
210
+ let cacheTimestamp = 0;
211
+
212
+ function getMetrics() {
213
+ if (cachedRequest == null || Date.now() - cacheTimestamp > MINIMUM_INTERVAL) {
214
+ cachedRequest = system.storage.getStorageMetrics().catch((e) => {
215
+ logger.error(`Failed to get storage metrics`, e);
216
+ return null;
217
+ });
218
+ cacheTimestamp = Date.now();
219
+ }
220
+ return cachedRequest;
221
+ }
222
+
223
+ this.operation_storage_size_bytes.addCallback(async (result) => {
224
+ const metrics = await getMetrics();
225
+ if (metrics) {
226
+ result.observe(metrics.operations_size_bytes);
227
+ }
228
+ });
229
+
230
+ this.parameter_storage_size_bytes.addCallback(async (result) => {
231
+ const metrics = await getMetrics();
232
+ if (metrics) {
233
+ result.observe(metrics.parameters_size_bytes);
234
+ }
235
+ });
236
+
237
+ this.replication_storage_size_bytes.addCallback(async (result) => {
238
+ const metrics = await getMetrics();
239
+ if (metrics) {
240
+ result.observe(metrics.replication_size_bytes);
241
+ }
242
+ });
243
+
244
+ const class_scoped_data_replicated_bytes = this.data_replicated_bytes;
245
+ // Record replicated bytes using global jpgwire metrics.
246
+ jpgwire.setMetricsRecorder({
247
+ addBytesRead(bytes) {
248
+ class_scoped_data_replicated_bytes.add(bytes);
249
+ }
250
+ });
251
+ }
252
+
253
+ public async getMetricValueForTests(name: string): Promise<number | undefined> {
254
+ const metrics = await this.prometheusExporter.collect();
255
+ const scoped = metrics.resourceMetrics.scopeMetrics[0].metrics;
256
+ const metric = scoped.find((metric) => metric.descriptor.name == name);
257
+ if (metric == null) {
258
+ throw new Error(
259
+ `Cannot find metric ${name}. Options: ${scoped.map((metric) => metric.descriptor.name).join(',')}`
260
+ );
261
+ }
262
+ const point = metric.dataPoints[metric.dataPoints.length - 1];
263
+ return point?.value as number;
264
+ }
265
+ }
@@ -0,0 +1,33 @@
1
+ import * as mongo from '../../../db/mongo.js';
2
+ import * as storage from '../../../storage/storage-index.js';
3
+ import * as utils from '../../../util/util-index.js';
4
+
5
+ export const up = async (context?: utils.MigrationContext) => {
6
+ const config = await utils.loadConfig(context?.runner_config);
7
+ const database = storage.createPowerSyncMongo(config.storage);
8
+ await mongo.waitForAuth(database.db);
9
+ try {
10
+ await database.bucket_parameters.createIndex(
11
+ {
12
+ 'key.g': 1,
13
+ lookup: 1,
14
+ _id: 1
15
+ },
16
+ { name: 'lookup1' }
17
+ );
18
+ } finally {
19
+ await database.client.close();
20
+ }
21
+ };
22
+
23
+ export const down = async (context?: utils.MigrationContext) => {
24
+ const config = await utils.loadConfig(context?.runner_config);
25
+ const database = storage.createPowerSyncMongo(config.storage);
26
+ try {
27
+ if (await database.bucket_parameters.indexExists('lookup')) {
28
+ await database.bucket_parameters.dropIndex('lookup1');
29
+ }
30
+ } finally {
31
+ await database.client.close();
32
+ }
33
+ };
@@ -0,0 +1,5 @@
1
+ export const up = async () => {
2
+ // No-op - we don't auto-create sync rules anymore
3
+ };
4
+
5
+ export const down = async () => {};
@@ -0,0 +1,99 @@
1
+ import * as mongo from '../../../db/mongo.js';
2
+ import * as storage from '../../../storage/storage-index.js';
3
+ import * as utils from '../../../util/util-index.js';
4
+
5
+ interface LegacySyncRulesDocument extends storage.SyncRuleDocument {
6
+ /**
7
+ * True if this is the active sync rules.
8
+ * requires `snapshot_done == true` and `replicating == true`.
9
+ */
10
+ active?: boolean;
11
+
12
+ /**
13
+ * True if this sync rules should be used for replication.
14
+ *
15
+ * During reprocessing, there is one sync rules with `replicating = true, active = true`,
16
+ * and one with `replicating = true, active = false, auto_activate = true`.
17
+ */
18
+ replicating?: boolean;
19
+
20
+ /**
21
+ * True if the sync rules should set `active = true` when `snapshot_done` = true.
22
+ */
23
+ auto_activate?: boolean;
24
+ }
25
+
26
+ export const up = async (context?: utils.MigrationContext) => {
27
+ const config = await utils.loadConfig(context?.runner_config);
28
+ const db = storage.createPowerSyncMongo(config.storage);
29
+ await mongo.waitForAuth(db.db);
30
+ try {
31
+ // We keep the old flags for existing deployments still shutting down.
32
+
33
+ // 1. New sync rules: `active = false, snapshot_done = false, replicating = true, auto_activate = true`
34
+ await db.sync_rules.updateMany(
35
+ {
36
+ active: { $ne: true },
37
+ replicating: true,
38
+ auto_activate: true
39
+ },
40
+ { $set: { state: storage.SyncRuleState.PROCESSING } }
41
+ );
42
+
43
+ // 2. Snapshot done: `active = true, snapshot_done = true, replicating = true, auto_activate = false`
44
+ await db.sync_rules.updateMany(
45
+ {
46
+ active: true
47
+ },
48
+ { $set: { state: storage.SyncRuleState.ACTIVE } }
49
+ );
50
+
51
+ // 3. Stopped: `active = false, snapshot_done = true, replicating = false, auto_activate = false`.
52
+ await db.sync_rules.updateMany(
53
+ {
54
+ active: { $ne: true },
55
+ replicating: { $ne: true },
56
+ auto_activate: { $ne: true }
57
+ },
58
+ { $set: { state: storage.SyncRuleState.STOP } }
59
+ );
60
+
61
+ const remaining = await db.sync_rules.find({ state: null as any }).toArray();
62
+ if (remaining.length > 0) {
63
+ const slots = remaining.map((doc) => doc.slot_name).join(', ');
64
+ throw new Error(`Invalid state for sync rules: ${slots}`);
65
+ }
66
+ } finally {
67
+ await db.client.close();
68
+ }
69
+ };
70
+
71
+ export const down = async (context?: utils.MigrationContext) => {
72
+ const config = await utils.loadConfig(context?.runner_config);
73
+
74
+ const db = storage.createPowerSyncMongo(config.storage);
75
+ try {
76
+ await db.sync_rules.updateMany(
77
+ {
78
+ state: storage.SyncRuleState.ACTIVE
79
+ },
80
+ { $set: { active: true, replicating: true } }
81
+ );
82
+
83
+ await db.sync_rules.updateMany(
84
+ {
85
+ state: storage.SyncRuleState.PROCESSING
86
+ },
87
+ { $set: { active: false, replicating: true, auto_activate: true } }
88
+ );
89
+
90
+ await db.sync_rules.updateMany(
91
+ {
92
+ $or: [{ state: storage.SyncRuleState.STOP }, { state: storage.SyncRuleState.TERMINATED }]
93
+ },
94
+ { $set: { active: false, replicating: false, auto_activate: false } }
95
+ );
96
+ } finally {
97
+ await db.client.close();
98
+ }
99
+ };
@@ -0,0 +1,32 @@
1
+ import * as storage from '../../../storage/storage-index.js';
2
+ import * as utils from '../../../util/util-index.js';
3
+
4
+ export const up = async (context?: utils.MigrationContext) => {
5
+ const config = await utils.loadConfig(context?.runner_config);
6
+ const db = storage.createPowerSyncMongo(config.storage);
7
+
8
+ try {
9
+ await db.write_checkpoints.createIndex(
10
+ {
11
+ user_id: 1
12
+ },
13
+ { name: 'user_id' }
14
+ );
15
+ } finally {
16
+ await db.client.close();
17
+ }
18
+ };
19
+
20
+ export const down = async (context?: utils.MigrationContext) => {
21
+ const config = await utils.loadConfig(context?.runner_config);
22
+
23
+ const db = storage.createPowerSyncMongo(config.storage);
24
+
25
+ try {
26
+ if (await db.write_checkpoints.indexExists('user_id')) {
27
+ await db.write_checkpoints.dropIndex('user_id');
28
+ }
29
+ } finally {
30
+ await db.client.close();
31
+ }
32
+ };
@@ -0,0 +1,21 @@
1
+ export type Migration = {
2
+ name: string;
3
+ up: () => Promise<void>;
4
+ down: () => Promise<void>;
5
+ };
6
+
7
+ export enum Direction {
8
+ Up = 'up',
9
+ Down = 'down'
10
+ }
11
+
12
+ export type ExecutedMigration = {
13
+ name: string;
14
+ direction: Direction;
15
+ timestamp: Date;
16
+ };
17
+
18
+ export type MigrationState = {
19
+ last_run: string;
20
+ log: ExecutedMigration[];
21
+ };