@powersync/service-core 0.8.8 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/api/RouteAPI.d.ts +67 -0
  3. package/dist/api/RouteAPI.js +2 -0
  4. package/dist/api/RouteAPI.js.map +1 -0
  5. package/dist/api/api-index.d.ts +1 -0
  6. package/dist/api/api-index.js +1 -0
  7. package/dist/api/api-index.js.map +1 -1
  8. package/dist/api/diagnostics.d.ts +4 -4
  9. package/dist/api/diagnostics.js +170 -158
  10. package/dist/api/diagnostics.js.map +1 -1
  11. package/dist/api/schema.d.ts +3 -5
  12. package/dist/api/schema.js +14 -80
  13. package/dist/api/schema.js.map +1 -1
  14. package/dist/auth/CachedKeyCollector.js.map +1 -1
  15. package/dist/auth/KeySpec.js.map +1 -1
  16. package/dist/auth/KeyStore.d.ts +7 -4
  17. package/dist/auth/KeyStore.js +1 -1
  18. package/dist/auth/KeyStore.js.map +1 -1
  19. package/dist/auth/LeakyBucket.js.map +1 -1
  20. package/dist/auth/RemoteJWKSCollector.d.ts +0 -2
  21. package/dist/auth/RemoteJWKSCollector.js.map +1 -1
  22. package/dist/auth/StaticSupabaseKeyCollector.d.ts +19 -0
  23. package/dist/auth/StaticSupabaseKeyCollector.js +28 -0
  24. package/dist/auth/StaticSupabaseKeyCollector.js.map +1 -0
  25. package/dist/auth/auth-index.d.ts +1 -1
  26. package/dist/auth/auth-index.js +1 -1
  27. package/dist/auth/auth-index.js.map +1 -1
  28. package/dist/db/mongo.js +5 -3
  29. package/dist/db/mongo.js.map +1 -1
  30. package/dist/entry/cli-entry.js +3 -2
  31. package/dist/entry/cli-entry.js.map +1 -1
  32. package/dist/entry/commands/compact-action.js +90 -14
  33. package/dist/entry/commands/compact-action.js.map +1 -1
  34. package/dist/entry/commands/migrate-action.js +4 -5
  35. package/dist/entry/commands/migrate-action.js.map +1 -1
  36. package/dist/entry/commands/teardown-action.js +2 -2
  37. package/dist/entry/commands/teardown-action.js.map +1 -1
  38. package/dist/index.d.ts +4 -2
  39. package/dist/index.js +4 -2
  40. package/dist/index.js.map +1 -1
  41. package/dist/locks/MongoLocks.js.map +1 -1
  42. package/dist/metrics/Metrics.d.ts +2 -2
  43. package/dist/metrics/Metrics.js +5 -13
  44. package/dist/metrics/Metrics.js.map +1 -1
  45. package/dist/migrations/db/migrations/1684951997326-init.d.ts +2 -2
  46. package/dist/migrations/db/migrations/1684951997326-init.js +4 -2
  47. package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
  48. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +2 -2
  49. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +4 -2
  50. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
  51. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +2 -2
  52. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +4 -2
  53. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
  54. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.d.ts +3 -0
  55. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js +31 -0
  56. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js.map +1 -0
  57. package/dist/migrations/executor.js.map +1 -1
  58. package/dist/migrations/migrations.d.ts +8 -0
  59. package/dist/migrations/migrations.js +19 -7
  60. package/dist/migrations/migrations.js.map +1 -1
  61. package/dist/migrations/store/migration-store.js.map +1 -1
  62. package/dist/modules/AbstractModule.d.ts +26 -0
  63. package/dist/modules/AbstractModule.js +11 -0
  64. package/dist/modules/AbstractModule.js.map +1 -0
  65. package/dist/modules/ModuleManager.d.ts +11 -0
  66. package/dist/modules/ModuleManager.js +32 -0
  67. package/dist/modules/ModuleManager.js.map +1 -0
  68. package/dist/modules/modules-index.d.ts +2 -0
  69. package/dist/modules/modules-index.js +3 -0
  70. package/dist/modules/modules-index.js.map +1 -0
  71. package/dist/replication/AbstractReplicationJob.d.ts +37 -0
  72. package/dist/replication/AbstractReplicationJob.js +51 -0
  73. package/dist/replication/AbstractReplicationJob.js.map +1 -0
  74. package/dist/replication/AbstractReplicator.d.ts +53 -0
  75. package/dist/replication/AbstractReplicator.js +250 -0
  76. package/dist/replication/AbstractReplicator.js.map +1 -0
  77. package/dist/replication/ErrorRateLimiter.d.ts +0 -10
  78. package/dist/replication/ErrorRateLimiter.js +1 -42
  79. package/dist/replication/ErrorRateLimiter.js.map +1 -1
  80. package/dist/replication/ReplicationEngine.d.ts +18 -0
  81. package/dist/replication/ReplicationEngine.js +41 -0
  82. package/dist/replication/ReplicationEngine.js.map +1 -0
  83. package/dist/replication/ReplicationModule.d.ts +51 -0
  84. package/dist/replication/ReplicationModule.js +68 -0
  85. package/dist/replication/ReplicationModule.js.map +1 -0
  86. package/dist/replication/replication-index.d.ts +4 -6
  87. package/dist/replication/replication-index.js +4 -6
  88. package/dist/replication/replication-index.js.map +1 -1
  89. package/dist/routes/RouterEngine.d.ts +42 -0
  90. package/dist/routes/RouterEngine.js +80 -0
  91. package/dist/routes/RouterEngine.js.map +1 -0
  92. package/dist/routes/auth.d.ts +2 -2
  93. package/dist/routes/auth.js +11 -11
  94. package/dist/routes/auth.js.map +1 -1
  95. package/dist/routes/configure-fastify.d.ts +37 -23
  96. package/dist/routes/configure-fastify.js +18 -18
  97. package/dist/routes/configure-fastify.js.map +1 -1
  98. package/dist/routes/configure-rsocket.d.ts +3 -4
  99. package/dist/routes/configure-rsocket.js +7 -4
  100. package/dist/routes/configure-rsocket.js.map +1 -1
  101. package/dist/routes/endpoints/admin.d.ts +30 -0
  102. package/dist/routes/endpoints/admin.js +46 -67
  103. package/dist/routes/endpoints/admin.js.map +1 -1
  104. package/dist/routes/endpoints/checkpointing.js +103 -15
  105. package/dist/routes/endpoints/checkpointing.js.map +1 -1
  106. package/dist/routes/endpoints/socket-route.js +8 -6
  107. package/dist/routes/endpoints/socket-route.js.map +1 -1
  108. package/dist/routes/endpoints/sync-rules.d.ts +1 -1
  109. package/dist/routes/endpoints/sync-rules.js +32 -23
  110. package/dist/routes/endpoints/sync-rules.js.map +1 -1
  111. package/dist/routes/endpoints/sync-stream.d.ts +0 -1
  112. package/dist/routes/endpoints/sync-stream.js +8 -8
  113. package/dist/routes/endpoints/sync-stream.js.map +1 -1
  114. package/dist/routes/hooks.js.map +1 -1
  115. package/dist/routes/route-register.js.map +1 -1
  116. package/dist/routes/router.d.ts +9 -2
  117. package/dist/routes/router.js.map +1 -1
  118. package/dist/routes/routes-index.d.ts +1 -0
  119. package/dist/routes/routes-index.js +1 -0
  120. package/dist/routes/routes-index.js.map +1 -1
  121. package/dist/runner/teardown.js +109 -76
  122. package/dist/runner/teardown.js.map +1 -1
  123. package/dist/storage/BucketStorage.d.ts +86 -36
  124. package/dist/storage/BucketStorage.js +6 -10
  125. package/dist/storage/BucketStorage.js.map +1 -1
  126. package/dist/storage/ChecksumCache.js.map +1 -1
  127. package/dist/storage/MongoBucketStorage.d.ts +7 -11
  128. package/dist/storage/MongoBucketStorage.js +48 -41
  129. package/dist/storage/MongoBucketStorage.js.map +1 -1
  130. package/dist/storage/ReplicationEventPayload.d.ts +14 -0
  131. package/dist/storage/ReplicationEventPayload.js +2 -0
  132. package/dist/storage/ReplicationEventPayload.js.map +1 -0
  133. package/dist/storage/SourceEntity.d.ts +20 -0
  134. package/dist/storage/SourceEntity.js +2 -0
  135. package/dist/storage/SourceEntity.js.map +1 -0
  136. package/dist/storage/SourceTable.d.ts +12 -5
  137. package/dist/storage/SourceTable.js +12 -5
  138. package/dist/storage/SourceTable.js.map +1 -1
  139. package/dist/storage/StorageEngine.d.ts +28 -0
  140. package/dist/storage/StorageEngine.js +45 -0
  141. package/dist/storage/StorageEngine.js.map +1 -0
  142. package/dist/storage/StorageProvider.d.ts +21 -0
  143. package/dist/storage/StorageProvider.js +2 -0
  144. package/dist/storage/StorageProvider.js.map +1 -0
  145. package/dist/storage/WriteCheckpointAPI.d.ts +74 -0
  146. package/dist/storage/WriteCheckpointAPI.js +16 -0
  147. package/dist/storage/WriteCheckpointAPI.js.map +1 -0
  148. package/dist/storage/mongo/MongoBucketBatch.d.ts +24 -5
  149. package/dist/storage/mongo/MongoBucketBatch.js +119 -62
  150. package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
  151. package/dist/storage/mongo/MongoCompactor.js +20 -3
  152. package/dist/storage/mongo/MongoCompactor.js.map +1 -1
  153. package/dist/storage/mongo/MongoIdSequence.js.map +1 -1
  154. package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +2 -2
  155. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +2 -2
  156. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -1
  157. package/dist/storage/mongo/MongoStorageProvider.d.ts +5 -0
  158. package/dist/storage/mongo/MongoStorageProvider.js +26 -0
  159. package/dist/storage/mongo/MongoStorageProvider.js.map +1 -0
  160. package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +18 -10
  161. package/dist/storage/mongo/MongoSyncBucketStorage.js +140 -25
  162. package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
  163. package/dist/storage/mongo/MongoSyncRulesLock.js +1 -1
  164. package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -1
  165. package/dist/storage/mongo/MongoWriteCheckpointAPI.d.ts +20 -0
  166. package/dist/storage/mongo/MongoWriteCheckpointAPI.js +103 -0
  167. package/dist/storage/mongo/MongoWriteCheckpointAPI.js.map +1 -0
  168. package/dist/storage/mongo/OperationBatch.d.ts +13 -4
  169. package/dist/storage/mongo/OperationBatch.js +25 -7
  170. package/dist/storage/mongo/OperationBatch.js.map +1 -1
  171. package/dist/storage/mongo/PersistedBatch.d.ts +3 -3
  172. package/dist/storage/mongo/PersistedBatch.js +2 -2
  173. package/dist/storage/mongo/PersistedBatch.js.map +1 -1
  174. package/dist/storage/mongo/config.d.ts +19 -0
  175. package/dist/storage/mongo/config.js +26 -0
  176. package/dist/storage/mongo/config.js.map +1 -0
  177. package/dist/storage/mongo/db.d.ts +3 -2
  178. package/dist/storage/mongo/db.js +1 -0
  179. package/dist/storage/mongo/db.js.map +1 -1
  180. package/dist/storage/mongo/models.d.ts +20 -5
  181. package/dist/storage/mongo/models.js.map +1 -1
  182. package/dist/storage/mongo/util.d.ts +12 -1
  183. package/dist/storage/mongo/util.js +50 -2
  184. package/dist/storage/mongo/util.js.map +1 -1
  185. package/dist/storage/storage-index.d.ts +8 -2
  186. package/dist/storage/storage-index.js +8 -2
  187. package/dist/storage/storage-index.js.map +1 -1
  188. package/dist/sync/BroadcastIterable.d.ts +0 -1
  189. package/dist/sync/BroadcastIterable.js.map +1 -1
  190. package/dist/sync/LastValueSink.d.ts +0 -1
  191. package/dist/sync/LastValueSink.js.map +1 -1
  192. package/dist/sync/merge.d.ts +0 -1
  193. package/dist/sync/merge.js.map +1 -1
  194. package/dist/sync/safeRace.js.map +1 -1
  195. package/dist/sync/sync.d.ts +1 -1
  196. package/dist/sync/sync.js +5 -5
  197. package/dist/sync/sync.js.map +1 -1
  198. package/dist/sync/util.d.ts +0 -2
  199. package/dist/sync/util.js.map +1 -1
  200. package/dist/system/ServiceContext.d.ts +37 -0
  201. package/dist/system/ServiceContext.js +48 -0
  202. package/dist/system/ServiceContext.js.map +1 -0
  203. package/dist/system/system-index.d.ts +1 -1
  204. package/dist/system/system-index.js +1 -1
  205. package/dist/system/system-index.js.map +1 -1
  206. package/dist/util/Mutex.js.map +1 -1
  207. package/dist/util/config/collectors/config-collector.js.map +1 -1
  208. package/dist/util/config/collectors/impl/base64-config-collector.js.map +1 -1
  209. package/dist/util/config/collectors/impl/filesystem-config-collector.js.map +1 -1
  210. package/dist/util/config/compound-config-collector.d.ts +9 -2
  211. package/dist/util/config/compound-config-collector.js +31 -23
  212. package/dist/util/config/compound-config-collector.js.map +1 -1
  213. package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js.map +1 -1
  214. package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js.map +1 -1
  215. package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js.map +1 -1
  216. package/dist/util/config/sync-rules/sync-rules-provider.d.ts +9 -0
  217. package/dist/util/config/sync-rules/sync-rules-provider.js +15 -0
  218. package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -0
  219. package/dist/util/config/types.d.ts +7 -4
  220. package/dist/util/config/types.js.map +1 -1
  221. package/dist/util/config.d.ts +3 -4
  222. package/dist/util/config.js +5 -20
  223. package/dist/util/config.js.map +1 -1
  224. package/dist/util/memory-tracking.js.map +1 -1
  225. package/dist/util/secs.js.map +1 -1
  226. package/dist/util/util-index.d.ts +3 -6
  227. package/dist/util/util-index.js +3 -6
  228. package/dist/util/util-index.js.map +1 -1
  229. package/dist/util/utils.d.ts +10 -7
  230. package/dist/util/utils.js +36 -25
  231. package/dist/util/utils.js.map +1 -1
  232. package/package.json +8 -12
  233. package/src/api/RouteAPI.ts +78 -0
  234. package/src/api/api-index.ts +1 -0
  235. package/src/api/diagnostics.ts +18 -70
  236. package/src/api/schema.ts +18 -90
  237. package/src/auth/KeyStore.ts +9 -6
  238. package/src/auth/RemoteJWKSCollector.ts +4 -1
  239. package/src/auth/StaticSupabaseKeyCollector.ts +31 -0
  240. package/src/auth/auth-index.ts +1 -1
  241. package/src/db/mongo.ts +5 -3
  242. package/src/entry/cli-entry.ts +3 -2
  243. package/src/entry/commands/compact-action.ts +24 -12
  244. package/src/entry/commands/migrate-action.ts +5 -8
  245. package/src/entry/commands/teardown-action.ts +2 -2
  246. package/src/index.ts +5 -2
  247. package/src/metrics/Metrics.ts +6 -16
  248. package/src/migrations/db/migrations/1684951997326-init.ts +9 -4
  249. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -4
  250. package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +6 -4
  251. package/src/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.ts +37 -0
  252. package/src/migrations/migrations.ts +24 -8
  253. package/src/modules/AbstractModule.ts +37 -0
  254. package/src/modules/ModuleManager.ts +34 -0
  255. package/src/modules/modules-index.ts +2 -0
  256. package/src/replication/AbstractReplicationJob.ts +79 -0
  257. package/src/replication/AbstractReplicator.ts +228 -0
  258. package/src/replication/ErrorRateLimiter.ts +0 -44
  259. package/src/replication/ReplicationEngine.ts +43 -0
  260. package/src/replication/ReplicationModule.ts +122 -0
  261. package/src/replication/replication-index.ts +4 -6
  262. package/src/routes/RouterEngine.ts +120 -0
  263. package/src/routes/auth.ts +21 -12
  264. package/src/routes/configure-fastify.ts +26 -27
  265. package/src/routes/configure-rsocket.ts +13 -8
  266. package/src/routes/endpoints/admin.ts +72 -76
  267. package/src/routes/endpoints/checkpointing.ts +51 -11
  268. package/src/routes/endpoints/socket-route.ts +10 -6
  269. package/src/routes/endpoints/sync-rules.ts +41 -25
  270. package/src/routes/endpoints/sync-stream.ts +8 -8
  271. package/src/routes/router.ts +8 -3
  272. package/src/routes/routes-index.ts +1 -0
  273. package/src/runner/teardown.ts +50 -88
  274. package/src/storage/BucketStorage.ts +103 -41
  275. package/src/storage/MongoBucketStorage.ts +65 -53
  276. package/src/storage/ReplicationEventPayload.ts +16 -0
  277. package/src/storage/SourceEntity.ts +22 -0
  278. package/src/storage/SourceTable.ts +14 -7
  279. package/src/storage/StorageEngine.ts +62 -0
  280. package/src/storage/StorageProvider.ts +27 -0
  281. package/src/storage/WriteCheckpointAPI.ts +85 -0
  282. package/src/storage/mongo/MongoBucketBatch.ts +164 -84
  283. package/src/storage/mongo/MongoCompactor.ts +25 -4
  284. package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +7 -4
  285. package/src/storage/mongo/MongoStorageProvider.ts +31 -0
  286. package/src/storage/mongo/MongoSyncBucketStorage.ts +118 -41
  287. package/src/storage/mongo/MongoSyncRulesLock.ts +7 -3
  288. package/src/storage/mongo/MongoWriteCheckpointAPI.ts +151 -0
  289. package/src/storage/mongo/OperationBatch.ts +28 -12
  290. package/src/storage/mongo/PersistedBatch.ts +10 -6
  291. package/src/storage/mongo/config.ts +40 -0
  292. package/src/storage/mongo/db.ts +4 -1
  293. package/src/storage/mongo/models.ts +21 -5
  294. package/src/storage/mongo/util.ts +48 -3
  295. package/src/storage/storage-index.ts +8 -2
  296. package/src/sync/sync.ts +7 -4
  297. package/src/sync/util.ts +0 -1
  298. package/src/system/ServiceContext.ts +68 -0
  299. package/src/system/system-index.ts +1 -1
  300. package/src/util/config/compound-config-collector.ts +48 -30
  301. package/src/util/config/sync-rules/sync-rules-provider.ts +18 -0
  302. package/src/util/config/types.ts +7 -5
  303. package/src/util/config.ts +6 -23
  304. package/src/util/util-index.ts +3 -6
  305. package/src/util/utils.ts +48 -41
  306. package/test/src/__snapshots__/sync.test.ts.snap +14 -14
  307. package/test/src/auth.test.ts +7 -7
  308. package/test/src/broadcast_iterable.test.ts +1 -1
  309. package/test/src/compacting.test.ts +50 -40
  310. package/test/src/data_storage.test.ts +382 -202
  311. package/test/src/env.ts +1 -3
  312. package/test/src/merge_iterable.test.ts +1 -6
  313. package/test/src/routes/probes.integration.test.ts +34 -30
  314. package/test/src/setup.ts +1 -1
  315. package/test/src/stream_utils.ts +42 -0
  316. package/test/src/sync.test.ts +115 -39
  317. package/test/src/util.ts +48 -51
  318. package/test/tsconfig.json +1 -1
  319. package/tsconfig.tsbuildinfo +1 -1
  320. package/vitest.config.ts +7 -1
  321. package/dist/auth/SupabaseKeyCollector.d.ts +0 -22
  322. package/dist/auth/SupabaseKeyCollector.js +0 -61
  323. package/dist/auth/SupabaseKeyCollector.js.map +0 -1
  324. package/dist/replication/PgRelation.d.ts +0 -16
  325. package/dist/replication/PgRelation.js +0 -26
  326. package/dist/replication/PgRelation.js.map +0 -1
  327. package/dist/replication/WalConnection.d.ts +0 -34
  328. package/dist/replication/WalConnection.js +0 -190
  329. package/dist/replication/WalConnection.js.map +0 -1
  330. package/dist/replication/WalStream.d.ts +0 -57
  331. package/dist/replication/WalStream.js +0 -519
  332. package/dist/replication/WalStream.js.map +0 -1
  333. package/dist/replication/WalStreamManager.d.ts +0 -30
  334. package/dist/replication/WalStreamManager.js +0 -198
  335. package/dist/replication/WalStreamManager.js.map +0 -1
  336. package/dist/replication/WalStreamRunner.d.ts +0 -38
  337. package/dist/replication/WalStreamRunner.js +0 -155
  338. package/dist/replication/WalStreamRunner.js.map +0 -1
  339. package/dist/replication/util.d.ts +0 -9
  340. package/dist/replication/util.js +0 -62
  341. package/dist/replication/util.js.map +0 -1
  342. package/dist/system/CorePowerSyncSystem.d.ts +0 -23
  343. package/dist/system/CorePowerSyncSystem.js +0 -52
  344. package/dist/system/CorePowerSyncSystem.js.map +0 -1
  345. package/dist/util/PgManager.d.ts +0 -24
  346. package/dist/util/PgManager.js +0 -55
  347. package/dist/util/PgManager.js.map +0 -1
  348. package/dist/util/migration_lib.d.ts +0 -11
  349. package/dist/util/migration_lib.js +0 -64
  350. package/dist/util/migration_lib.js.map +0 -1
  351. package/dist/util/pgwire_utils.d.ts +0 -24
  352. package/dist/util/pgwire_utils.js +0 -117
  353. package/dist/util/pgwire_utils.js.map +0 -1
  354. package/dist/util/populate_test_data.d.ts +0 -8
  355. package/dist/util/populate_test_data.js +0 -65
  356. package/dist/util/populate_test_data.js.map +0 -1
  357. package/src/auth/SupabaseKeyCollector.ts +0 -67
  358. package/src/replication/PgRelation.ts +0 -42
  359. package/src/replication/WalConnection.ts +0 -227
  360. package/src/replication/WalStream.ts +0 -631
  361. package/src/replication/WalStreamManager.ts +0 -213
  362. package/src/replication/WalStreamRunner.ts +0 -180
  363. package/src/replication/util.ts +0 -76
  364. package/src/system/CorePowerSyncSystem.ts +0 -64
  365. package/src/util/PgManager.ts +0 -64
  366. package/src/util/migration_lib.ts +0 -79
  367. package/src/util/pgwire_utils.ts +0 -139
  368. package/src/util/populate_test_data.ts +0 -78
  369. package/test/src/__snapshots__/pg_test.test.ts.snap +0 -256
  370. package/test/src/large_batch.test.ts +0 -194
  371. package/test/src/pg_test.test.ts +0 -450
  372. package/test/src/schema_changes.test.ts +0 -545
  373. package/test/src/slow_tests.test.ts +0 -338
  374. package/test/src/validation.test.ts +0 -63
  375. package/test/src/wal_stream.test.ts +0 -319
  376. package/test/src/wal_stream_utils.ts +0 -156
@@ -1,450 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
- import { WalStream } from '../../src/replication/WalStream.js';
3
- import * as pgwire from '@powersync/service-jpgwire';
4
- import { clearTestDb, connectPgPool, connectPgWire, TEST_URI } from './util.js';
5
- import { constructAfterRecord } from '../../src/util/pgwire_utils.js';
6
- import { SqliteRow } from '@powersync/service-sync-rules';
7
- import { getConnectionSchema } from '../../src/api/schema.js';
8
-
9
- describe('pg data types', () => {
10
- async function setupTable(db: pgwire.PgClient) {
11
- await clearTestDb(db);
12
- await db.query(`CREATE TABLE test_data(
13
- id serial primary key,
14
- text text,
15
- uuid uuid,
16
- varchar varchar(255),
17
- bool bool,
18
- bytea bytea,
19
- int2 int2,
20
- int4 int4,
21
- int8 int8,
22
- float4 float4,
23
- float8 float8,
24
- numeric numeric, -- same as decimal
25
- json json,
26
- jsonb jsonb,
27
- pg_lsn pg_lsn,
28
- date date,
29
- time time,
30
- timestamp timestamp,
31
- timestamptz timestamptz,
32
- interval interval,
33
- macaddr macaddr,
34
- inet inet,
35
- oid oid
36
- )`);
37
-
38
- await db.query(`DROP TABLE IF EXISTS test_data_arrays`);
39
- await db.query(`CREATE TABLE test_data_arrays(
40
- id serial primary key,
41
- text text[],
42
- uuid uuid[],
43
- varchar varchar(255)[],
44
- bool bool[],
45
- bytea bytea[],
46
- int2 int2[],
47
- int4 int4[],
48
- int8 int8[],
49
- float4 float4[],
50
- float8 float8[],
51
- numeric numeric[], -- same as decimal
52
- json json[],
53
- jsonb jsonb[],
54
- pg_lsn pg_lsn[],
55
- date date[],
56
- time time[],
57
- timestamp timestamp[],
58
- timestamptz timestamptz[],
59
- interval interval[],
60
- macaddr macaddr[],
61
- inet inet[],
62
- oid oid[],
63
- multidimensional text[][] -- same as text[]
64
- )`);
65
- }
66
-
67
- async function insert(db: pgwire.PgClient) {
68
- await db.query(`
69
- INSERT INTO test_data(id, text, uuid, varchar, bool, bytea, int2, int4, int8, numeric, float4, float8)
70
- VALUES(1, 'text', 'baeb2514-4c57-436d-b3cc-c1256211656d', 'varchar', true, 'test', 1000, 1000000, 9007199254740993, 18014398509481982123, 3.14, 314);
71
-
72
- INSERT INTO test_data(id, json, jsonb)
73
- VALUES(2, '{"test": "thing" }', '{"test": "thing" }');
74
-
75
- INSERT INTO test_data(id, date, time, timestamp, timestamptz)
76
- VALUES(3, '2023-03-06', '15:47', '2023-03-06 15:47', '2023-03-06 15:47+02');
77
-
78
- INSERT INTO test_data(id, pg_lsn, interval, macaddr, inet, oid)
79
- VALUES(4, '016/B374D848', '1 hour', '00:00:5e:00:53:af', '127.0.0.1', 1007);
80
-
81
- INSERT INTO test_data(id, date, time, timestamp, timestamptz)
82
- VALUES(5, '-infinity'::date, 'allballs'::time, '-infinity'::timestamp, '-infinity'::timestamptz);
83
-
84
- INSERT INTO test_data(id, timestamp, timestamptz)
85
- VALUES(6, 'epoch'::timestamp, 'epoch'::timestamptz);
86
-
87
- INSERT INTO test_data(id, timestamp, timestamptz)
88
- VALUES(7, 'infinity'::timestamp, 'infinity'::timestamptz);
89
-
90
- INSERT INTO test_data(id, timestamptz)
91
- VALUES(8, '0022-02-03 12:13:14+03'::timestamptz);
92
-
93
- INSERT INTO test_data(id, timestamptz)
94
- VALUES(9, '10022-02-03 12:13:14+03'::timestamptz);
95
- `);
96
- }
97
-
98
- async function insertArrays(db: pgwire.PgClient) {
99
- await db.query(`
100
- INSERT INTO test_data_arrays(id, text, uuid, varchar, bool, bytea, int2, int4, int8, numeric)
101
- VALUES(1, ARRAY['text', '}te][xt{"'], '{"baeb2514-4c57-436d-b3cc-c1256211656d"}', '{"varchar"}', '{true}', '{"test"}', '{1000}', '{1000000}', '{9007199254740993}', '{18014398509481982123}');
102
-
103
- INSERT INTO test_data_arrays(id, json, jsonb)
104
- VALUES(2, ARRAY['{"test": "thing"}' :: json, '{"test": "}te][xt{"}' :: json], ARRAY['{"test": "thing", "foo": 5.0, "bignum": 18014398509481982123, "bool":true}' :: jsonb]);
105
-
106
- INSERT INTO test_data_arrays(id, date, time, timestamp, timestamptz)
107
- VALUES(3, ARRAY['2023-03-06'::date], ARRAY['15:47'::time], ARRAY['2023-03-06 15:47'::timestamp], ARRAY['2023-03-06 15:47+02'::timestamptz, '2023-03-06 15:47:00.123450+02'::timestamptz]);
108
-
109
- INSERT INTO test_data_arrays(id, pg_lsn, interval, macaddr, inet, oid)
110
- VALUES(4, ARRAY['016/B374D848'::pg_lsn], ARRAY['1 hour'::interval], ARRAY['00:00:5e:00:53:af'::macaddr], ARRAY['127.0.0.1'::inet], ARRAY[1007::oid]);
111
-
112
- -- Empty arrays
113
- INSERT INTO test_data_arrays(id, text, uuid, varchar, bool, bytea, int2, int4, int8, numeric)
114
- VALUES(5, ARRAY[]::text[], ARRAY[]::uuid[], ARRAY[]::varchar[], ARRAY[]::bool[], ARRAY[]::bytea[], ARRAY[]::int2[], ARRAY[]::int4[], ARRAY[]::int8[], ARRAY[]::numeric[]);
115
-
116
- -- Two-dimentional array
117
- INSERT INTO test_data_arrays(id, multidimensional)
118
- VALUES(6, ARRAY[['one', 1], ['two', 2], ['three', Null]]::TEXT[]);
119
-
120
- -- Empty array
121
- INSERT INTO test_data_arrays(id, multidimensional)
122
- VALUES(7, ARRAY[[], [], []]::TEXT[]);
123
-
124
- -- Empty array
125
- INSERT INTO test_data_arrays(id, multidimensional)
126
- VALUES(8, ARRAY[]::TEXT[]);
127
-
128
- -- Array with only null
129
- INSERT INTO test_data_arrays(id, multidimensional)
130
- VALUES(9, ARRAY[NULL]::TEXT[]);
131
-
132
- -- Array with 'null'
133
- INSERT INTO test_data_arrays(id, multidimensional)
134
- VALUES(10, ARRAY['null']::TEXT[]);
135
- `);
136
- }
137
-
138
- function checkResults(transformed: Record<string, any>[]) {
139
- expect(transformed[0]).toMatchObject({
140
- id: 1n,
141
- text: 'text',
142
- uuid: 'baeb2514-4c57-436d-b3cc-c1256211656d',
143
- varchar: 'varchar',
144
- bool: 1n,
145
- bytea: new Uint8Array([116, 101, 115, 116]),
146
- int2: 1000n,
147
- int4: 1000000n,
148
- int8: 9007199254740993n,
149
- float4: 3.14,
150
- float8: 314,
151
- numeric: '18014398509481982123'
152
- });
153
- expect(transformed[1]).toMatchObject({
154
- id: 2n,
155
- json: '{"test": "thing" }', // Whitespace preserved
156
- jsonb: '{"test": "thing"}' // Whitespace according to pg JSON conventions
157
- });
158
-
159
- expect(transformed[2]).toMatchObject({
160
- id: 3n,
161
- date: '2023-03-06',
162
- time: '15:47:00',
163
- timestamp: '2023-03-06 15:47:00',
164
- timestamptz: '2023-03-06 13:47:00Z'
165
- });
166
-
167
- expect(transformed[3]).toMatchObject({
168
- id: 4n,
169
- pg_lsn: '00000016/B374D848',
170
- interval: '01:00:00',
171
- macaddr: '00:00:5e:00:53:af',
172
- inet: '127.0.0.1',
173
- oid: 1007n
174
- });
175
-
176
- expect(transformed[4]).toMatchObject({
177
- id: 5n,
178
- date: '0000-01-01',
179
- time: '00:00:00',
180
- timestamp: '0000-01-01 00:00:00',
181
- timestamptz: '0000-01-01 00:00:00Z'
182
- });
183
-
184
- expect(transformed[5]).toMatchObject({
185
- id: 6n,
186
- timestamp: '1970-01-01 00:00:00',
187
- timestamptz: '1970-01-01 00:00:00Z'
188
- });
189
-
190
- expect(transformed[6]).toMatchObject({
191
- id: 7n,
192
- timestamp: '9999-12-31 23:59:59',
193
- timestamptz: '9999-12-31 23:59:59Z'
194
- });
195
-
196
- expect(transformed[7]).toMatchObject({
197
- id: 8n,
198
- timestamptz: '0022-02-03 09:13:14Z'
199
- });
200
-
201
- expect(transformed[8]).toMatchObject({
202
- id: 9n,
203
- // 10022-02-03 12:13:14+03 - out of range of both our date parsing logic, and sqlite's date functions
204
- // We can consider just preserving the source string as an alternative if this causes issues.
205
- timestamptz: null
206
- });
207
- }
208
-
209
- function checkResultArrays(transformed: Record<string, any>[]) {
210
- expect(transformed[0]).toMatchObject({
211
- id: 1n,
212
- text: `["text","}te][xt{\\""]`,
213
- uuid: '["baeb2514-4c57-436d-b3cc-c1256211656d"]',
214
- varchar: '["varchar"]',
215
- bool: '[1]',
216
- bytea: '[null]',
217
- int2: '[1000]',
218
- int4: '[1000000]',
219
- int8: `[9007199254740993]`,
220
- numeric: `["18014398509481982123"]`
221
- });
222
-
223
- // Note: Depending on to what extent we use the original postgres value, the whitespace may change, and order may change.
224
- // We do expect that decimals and big numbers are preserved.
225
- expect(transformed[1]).toMatchObject({
226
- id: 2n,
227
- // Expected output after a serialize + parse cycle:
228
- // json: `[{"test":"thing"},{"test":"}te][xt{"}]`,
229
- // jsonb: `[{"foo":5.0,"bool":true,"test":"thing","bignum":18014398509481982123}]`
230
- // Expected using direct PG values:
231
- json: `[{"test": "thing"},{"test": "}te][xt{"}]`,
232
- jsonb: `[{"foo": 5.0, "bool": true, "test": "thing", "bignum": 18014398509481982123}]`
233
- });
234
-
235
- expect(transformed[2]).toMatchObject({
236
- id: 3n,
237
- date: `["2023-03-06"]`,
238
- time: `["15:47:00"]`,
239
- timestamp: `["2023-03-06 15:47:00"]`,
240
- timestamptz: `["2023-03-06 13:47:00Z","2023-03-06 13:47:00.12345Z"]`
241
- });
242
-
243
- expect(transformed[3]).toMatchObject({
244
- id: 4n,
245
- pg_lsn: `["00000016/B374D848"]`,
246
- interval: `["01:00:00"]`,
247
- macaddr: `["00:00:5e:00:53:af"]`,
248
- inet: `["127.0.0.1"]`,
249
- oid: `[1007]`
250
- });
251
-
252
- expect(transformed[4]).toMatchObject({
253
- id: 5n,
254
- text: '[]',
255
- uuid: '[]',
256
- varchar: '[]',
257
- bool: '[]',
258
- bytea: '[]',
259
- int2: '[]',
260
- int4: '[]',
261
- int8: '[]',
262
- numeric: '[]'
263
- });
264
-
265
- expect(transformed[5]).toMatchObject({
266
- id: 6n,
267
- multidimensional: '[["one","1"],["two","2"],["three",null]]'
268
- });
269
-
270
- expect(transformed[6]).toMatchObject({
271
- id: 7n,
272
- multidimensional: '[]'
273
- });
274
-
275
- expect(transformed[7]).toMatchObject({
276
- id: 8n,
277
- multidimensional: '[]'
278
- });
279
-
280
- expect(transformed[8]).toMatchObject({
281
- id: 9n,
282
- multidimensional: '[null]'
283
- });
284
-
285
- expect(transformed[9]).toMatchObject({
286
- id: 10n,
287
- multidimensional: '["null"]'
288
- });
289
- }
290
-
291
- test('test direct queries', async () => {
292
- const db = await connectPgPool();
293
- try {
294
- await setupTable(db);
295
-
296
- await insert(db);
297
-
298
- const transformed = [
299
- ...WalStream.getQueryData(pgwire.pgwireRows(await db.query(`SELECT * FROM test_data ORDER BY id`)))
300
- ];
301
-
302
- checkResults(transformed);
303
- } finally {
304
- await db.end();
305
- }
306
- });
307
-
308
- test('test direct queries - parameterized', async () => {
309
- // Parameterized queries may use a different underlying protocol,
310
- // so we make sure it also gets the same results.
311
- const db = await connectPgPool();
312
- try {
313
- await setupTable(db);
314
-
315
- await insert(db);
316
-
317
- const transformed = [
318
- ...WalStream.getQueryData(
319
- pgwire.pgwireRows(
320
- await db.query({
321
- statement: `SELECT * FROM test_data WHERE $1 ORDER BY id`,
322
- params: [{ type: 'bool', value: true }]
323
- })
324
- )
325
- )
326
- ];
327
-
328
- checkResults(transformed);
329
- } finally {
330
- await db.end();
331
- }
332
- });
333
-
334
- test('test direct queries - arrays', async () => {
335
- const db = await connectPgPool();
336
- try {
337
- await setupTable(db);
338
-
339
- await insertArrays(db);
340
-
341
- const transformed = [
342
- ...WalStream.getQueryData(pgwire.pgwireRows(await db.query(`SELECT * FROM test_data_arrays ORDER BY id`)))
343
- ];
344
-
345
- checkResultArrays(transformed);
346
- } finally {
347
- await db.end();
348
- }
349
- });
350
-
351
- test('test replication', async () => {
352
- const db = await connectPgPool();
353
- try {
354
- await setupTable(db);
355
-
356
- const slotName = 'test_slot';
357
-
358
- await db.query({
359
- statement: 'SELECT pg_drop_replication_slot(slot_name) FROM pg_replication_slots WHERE slot_name = $1',
360
- params: [{ type: 'varchar', value: slotName }]
361
- });
362
-
363
- await db.query({
364
- statement: `SELECT slot_name, lsn FROM pg_catalog.pg_create_logical_replication_slot($1, 'pgoutput')`,
365
- params: [{ type: 'varchar', value: slotName }]
366
- });
367
-
368
- await insert(db);
369
-
370
- const pg: pgwire.PgConnection = await pgwire.pgconnect({ replication: 'database' }, TEST_URI);
371
- const replicationStream = await pg.logicalReplication({
372
- slot: slotName,
373
- options: {
374
- proto_version: '1',
375
- publication_names: 'powersync'
376
- }
377
- });
378
-
379
- const transformed = await getReplicationTx(replicationStream);
380
- await pg.end();
381
-
382
- checkResults(transformed);
383
- } finally {
384
- await db.end();
385
- }
386
- });
387
-
388
- test('test replication - arrays', async () => {
389
- const db = await connectPgPool();
390
- try {
391
- await setupTable(db);
392
-
393
- const slotName = 'test_slot';
394
-
395
- await db.query({
396
- statement: 'SELECT pg_drop_replication_slot(slot_name) FROM pg_replication_slots WHERE slot_name = $1',
397
- params: [{ type: 'varchar', value: slotName }]
398
- });
399
-
400
- await db.query({
401
- statement: `SELECT slot_name, lsn FROM pg_catalog.pg_create_logical_replication_slot($1, 'pgoutput')`,
402
- params: [{ type: 'varchar', value: slotName }]
403
- });
404
-
405
- await insertArrays(db);
406
-
407
- const pg: pgwire.PgConnection = await pgwire.pgconnect({ replication: 'database' }, TEST_URI);
408
- const replicationStream = await pg.logicalReplication({
409
- slot: slotName,
410
- options: {
411
- proto_version: '1',
412
- publication_names: 'powersync'
413
- }
414
- });
415
-
416
- const transformed = await getReplicationTx(replicationStream);
417
- await pg.end();
418
-
419
- checkResultArrays(transformed);
420
- } finally {
421
- await db.end();
422
- }
423
- });
424
-
425
- test('schema', async function () {
426
- const db = await connectPgWire();
427
-
428
- await setupTable(db);
429
-
430
- const schema = await getConnectionSchema(db);
431
- expect(schema).toMatchSnapshot();
432
- });
433
- });
434
-
435
- /**
436
- * Return all the inserts from the first transaction in the replication stream.
437
- */
438
- async function getReplicationTx(replicationStream: pgwire.ReplicationStream) {
439
- let transformed: SqliteRow[] = [];
440
- for await (const batch of replicationStream.pgoutputDecode()) {
441
- for (const msg of batch.messages) {
442
- if (msg.tag == 'insert') {
443
- transformed.push(constructAfterRecord(msg));
444
- } else if (msg.tag == 'commit') {
445
- return transformed;
446
- }
447
- }
448
- }
449
- return transformed;
450
- }