@powersync/service-core 0.8.7 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/dist/api/RouteAPI.d.ts +67 -0
  3. package/dist/api/RouteAPI.js +2 -0
  4. package/dist/api/RouteAPI.js.map +1 -0
  5. package/dist/api/api-index.d.ts +1 -0
  6. package/dist/api/api-index.js +1 -0
  7. package/dist/api/api-index.js.map +1 -1
  8. package/dist/api/diagnostics.d.ts +4 -4
  9. package/dist/api/diagnostics.js +170 -158
  10. package/dist/api/diagnostics.js.map +1 -1
  11. package/dist/api/schema.d.ts +3 -5
  12. package/dist/api/schema.js +14 -80
  13. package/dist/api/schema.js.map +1 -1
  14. package/dist/auth/CachedKeyCollector.js.map +1 -1
  15. package/dist/auth/KeySpec.js.map +1 -1
  16. package/dist/auth/KeyStore.d.ts +7 -4
  17. package/dist/auth/KeyStore.js +1 -1
  18. package/dist/auth/KeyStore.js.map +1 -1
  19. package/dist/auth/LeakyBucket.js.map +1 -1
  20. package/dist/auth/RemoteJWKSCollector.d.ts +0 -2
  21. package/dist/auth/RemoteJWKSCollector.js.map +1 -1
  22. package/dist/auth/auth-index.d.ts +0 -1
  23. package/dist/auth/auth-index.js +0 -1
  24. package/dist/auth/auth-index.js.map +1 -1
  25. package/dist/db/mongo.js +5 -3
  26. package/dist/db/mongo.js.map +1 -1
  27. package/dist/entry/cli-entry.js +3 -2
  28. package/dist/entry/cli-entry.js.map +1 -1
  29. package/dist/entry/commands/compact-action.js +90 -14
  30. package/dist/entry/commands/compact-action.js.map +1 -1
  31. package/dist/entry/commands/migrate-action.js +4 -5
  32. package/dist/entry/commands/migrate-action.js.map +1 -1
  33. package/dist/entry/commands/teardown-action.js +2 -2
  34. package/dist/entry/commands/teardown-action.js.map +1 -1
  35. package/dist/index.d.ts +4 -2
  36. package/dist/index.js +4 -2
  37. package/dist/index.js.map +1 -1
  38. package/dist/locks/MongoLocks.js.map +1 -1
  39. package/dist/metrics/Metrics.d.ts +2 -2
  40. package/dist/metrics/Metrics.js +5 -13
  41. package/dist/metrics/Metrics.js.map +1 -1
  42. package/dist/migrations/db/migrations/1684951997326-init.d.ts +2 -2
  43. package/dist/migrations/db/migrations/1684951997326-init.js +4 -2
  44. package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
  45. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +2 -2
  46. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +4 -2
  47. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
  48. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +2 -2
  49. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +4 -2
  50. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
  51. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.d.ts +3 -0
  52. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js +31 -0
  53. package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js.map +1 -0
  54. package/dist/migrations/executor.js.map +1 -1
  55. package/dist/migrations/migrations.d.ts +8 -0
  56. package/dist/migrations/migrations.js +19 -7
  57. package/dist/migrations/migrations.js.map +1 -1
  58. package/dist/migrations/store/migration-store.js.map +1 -1
  59. package/dist/modules/AbstractModule.d.ts +26 -0
  60. package/dist/modules/AbstractModule.js +11 -0
  61. package/dist/modules/AbstractModule.js.map +1 -0
  62. package/dist/modules/ModuleManager.d.ts +11 -0
  63. package/dist/modules/ModuleManager.js +32 -0
  64. package/dist/modules/ModuleManager.js.map +1 -0
  65. package/dist/modules/modules-index.d.ts +2 -0
  66. package/dist/modules/modules-index.js +3 -0
  67. package/dist/modules/modules-index.js.map +1 -0
  68. package/dist/replication/AbstractReplicationJob.d.ts +37 -0
  69. package/dist/replication/AbstractReplicationJob.js +51 -0
  70. package/dist/replication/AbstractReplicationJob.js.map +1 -0
  71. package/dist/replication/AbstractReplicator.d.ts +53 -0
  72. package/dist/replication/AbstractReplicator.js +250 -0
  73. package/dist/replication/AbstractReplicator.js.map +1 -0
  74. package/dist/replication/ErrorRateLimiter.d.ts +0 -10
  75. package/dist/replication/ErrorRateLimiter.js +1 -42
  76. package/dist/replication/ErrorRateLimiter.js.map +1 -1
  77. package/dist/replication/ReplicationEngine.d.ts +18 -0
  78. package/dist/replication/ReplicationEngine.js +41 -0
  79. package/dist/replication/ReplicationEngine.js.map +1 -0
  80. package/dist/replication/ReplicationModule.d.ts +51 -0
  81. package/dist/replication/ReplicationModule.js +68 -0
  82. package/dist/replication/ReplicationModule.js.map +1 -0
  83. package/dist/replication/replication-index.d.ts +4 -6
  84. package/dist/replication/replication-index.js +4 -6
  85. package/dist/replication/replication-index.js.map +1 -1
  86. package/dist/routes/RouterEngine.d.ts +42 -0
  87. package/dist/routes/RouterEngine.js +80 -0
  88. package/dist/routes/RouterEngine.js.map +1 -0
  89. package/dist/routes/auth.d.ts +2 -2
  90. package/dist/routes/auth.js +11 -11
  91. package/dist/routes/auth.js.map +1 -1
  92. package/dist/routes/configure-fastify.d.ts +37 -7
  93. package/dist/routes/configure-fastify.js +20 -19
  94. package/dist/routes/configure-fastify.js.map +1 -1
  95. package/dist/routes/configure-rsocket.d.ts +3 -4
  96. package/dist/routes/configure-rsocket.js +7 -4
  97. package/dist/routes/configure-rsocket.js.map +1 -1
  98. package/dist/routes/endpoints/admin.d.ts +30 -0
  99. package/dist/routes/endpoints/admin.js +46 -67
  100. package/dist/routes/endpoints/admin.js.map +1 -1
  101. package/dist/routes/endpoints/checkpointing.js +103 -15
  102. package/dist/routes/endpoints/checkpointing.js.map +1 -1
  103. package/dist/routes/endpoints/probes.d.ts +74 -0
  104. package/dist/routes/endpoints/probes.js +51 -0
  105. package/dist/routes/endpoints/probes.js.map +1 -0
  106. package/dist/routes/endpoints/socket-route.js +8 -6
  107. package/dist/routes/endpoints/socket-route.js.map +1 -1
  108. package/dist/routes/endpoints/sync-rules.d.ts +1 -1
  109. package/dist/routes/endpoints/sync-rules.js +32 -23
  110. package/dist/routes/endpoints/sync-rules.js.map +1 -1
  111. package/dist/routes/endpoints/sync-stream.d.ts +0 -1
  112. package/dist/routes/endpoints/sync-stream.js +8 -8
  113. package/dist/routes/endpoints/sync-stream.js.map +1 -1
  114. package/dist/routes/hooks.js.map +1 -1
  115. package/dist/routes/route-register.js.map +1 -1
  116. package/dist/routes/router.d.ts +11 -4
  117. package/dist/routes/router.js.map +1 -1
  118. package/dist/routes/routes-index.d.ts +1 -0
  119. package/dist/routes/routes-index.js +1 -0
  120. package/dist/routes/routes-index.js.map +1 -1
  121. package/dist/runner/teardown.js +109 -76
  122. package/dist/runner/teardown.js.map +1 -1
  123. package/dist/storage/BucketStorage.d.ts +86 -36
  124. package/dist/storage/BucketStorage.js +6 -10
  125. package/dist/storage/BucketStorage.js.map +1 -1
  126. package/dist/storage/ChecksumCache.js.map +1 -1
  127. package/dist/storage/MongoBucketStorage.d.ts +7 -11
  128. package/dist/storage/MongoBucketStorage.js +48 -41
  129. package/dist/storage/MongoBucketStorage.js.map +1 -1
  130. package/dist/storage/ReplicationEventPayload.d.ts +14 -0
  131. package/dist/storage/ReplicationEventPayload.js +2 -0
  132. package/dist/storage/ReplicationEventPayload.js.map +1 -0
  133. package/dist/storage/SourceEntity.d.ts +20 -0
  134. package/dist/storage/SourceEntity.js +2 -0
  135. package/dist/storage/SourceEntity.js.map +1 -0
  136. package/dist/storage/SourceTable.d.ts +12 -5
  137. package/dist/storage/SourceTable.js +12 -5
  138. package/dist/storage/SourceTable.js.map +1 -1
  139. package/dist/storage/StorageEngine.d.ts +28 -0
  140. package/dist/storage/StorageEngine.js +45 -0
  141. package/dist/storage/StorageEngine.js.map +1 -0
  142. package/dist/storage/StorageProvider.d.ts +21 -0
  143. package/dist/storage/StorageProvider.js +2 -0
  144. package/dist/storage/StorageProvider.js.map +1 -0
  145. package/dist/storage/WriteCheckpointAPI.d.ts +74 -0
  146. package/dist/storage/WriteCheckpointAPI.js +16 -0
  147. package/dist/storage/WriteCheckpointAPI.js.map +1 -0
  148. package/dist/storage/mongo/MongoBucketBatch.d.ts +24 -5
  149. package/dist/storage/mongo/MongoBucketBatch.js +119 -62
  150. package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
  151. package/dist/storage/mongo/MongoCompactor.js +20 -3
  152. package/dist/storage/mongo/MongoCompactor.js.map +1 -1
  153. package/dist/storage/mongo/MongoIdSequence.js.map +1 -1
  154. package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +2 -2
  155. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +2 -2
  156. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -1
  157. package/dist/storage/mongo/MongoStorageProvider.d.ts +5 -0
  158. package/dist/storage/mongo/MongoStorageProvider.js +26 -0
  159. package/dist/storage/mongo/MongoStorageProvider.js.map +1 -0
  160. package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +18 -10
  161. package/dist/storage/mongo/MongoSyncBucketStorage.js +140 -25
  162. package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
  163. package/dist/storage/mongo/MongoSyncRulesLock.js +1 -1
  164. package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -1
  165. package/dist/storage/mongo/MongoWriteCheckpointAPI.d.ts +20 -0
  166. package/dist/storage/mongo/MongoWriteCheckpointAPI.js +103 -0
  167. package/dist/storage/mongo/MongoWriteCheckpointAPI.js.map +1 -0
  168. package/dist/storage/mongo/OperationBatch.d.ts +13 -4
  169. package/dist/storage/mongo/OperationBatch.js +25 -7
  170. package/dist/storage/mongo/OperationBatch.js.map +1 -1
  171. package/dist/storage/mongo/PersistedBatch.d.ts +3 -3
  172. package/dist/storage/mongo/PersistedBatch.js +2 -2
  173. package/dist/storage/mongo/PersistedBatch.js.map +1 -1
  174. package/dist/storage/mongo/config.d.ts +19 -0
  175. package/dist/storage/mongo/config.js +26 -0
  176. package/dist/storage/mongo/config.js.map +1 -0
  177. package/dist/storage/mongo/db.d.ts +3 -2
  178. package/dist/storage/mongo/db.js +1 -0
  179. package/dist/storage/mongo/db.js.map +1 -1
  180. package/dist/storage/mongo/models.d.ts +20 -5
  181. package/dist/storage/mongo/models.js.map +1 -1
  182. package/dist/storage/mongo/util.d.ts +12 -1
  183. package/dist/storage/mongo/util.js +50 -2
  184. package/dist/storage/mongo/util.js.map +1 -1
  185. package/dist/storage/storage-index.d.ts +8 -2
  186. package/dist/storage/storage-index.js +8 -2
  187. package/dist/storage/storage-index.js.map +1 -1
  188. package/dist/sync/BroadcastIterable.d.ts +0 -1
  189. package/dist/sync/BroadcastIterable.js.map +1 -1
  190. package/dist/sync/LastValueSink.d.ts +0 -1
  191. package/dist/sync/LastValueSink.js.map +1 -1
  192. package/dist/sync/merge.d.ts +0 -1
  193. package/dist/sync/merge.js.map +1 -1
  194. package/dist/sync/safeRace.js.map +1 -1
  195. package/dist/sync/sync.d.ts +1 -1
  196. package/dist/sync/sync.js +5 -5
  197. package/dist/sync/sync.js.map +1 -1
  198. package/dist/sync/util.d.ts +0 -2
  199. package/dist/sync/util.js.map +1 -1
  200. package/dist/system/ServiceContext.d.ts +37 -0
  201. package/dist/system/ServiceContext.js +48 -0
  202. package/dist/system/ServiceContext.js.map +1 -0
  203. package/dist/system/system-index.d.ts +1 -1
  204. package/dist/system/system-index.js +1 -1
  205. package/dist/system/system-index.js.map +1 -1
  206. package/dist/util/Mutex.js.map +1 -1
  207. package/dist/util/config/collectors/config-collector.js.map +1 -1
  208. package/dist/util/config/collectors/impl/base64-config-collector.js.map +1 -1
  209. package/dist/util/config/collectors/impl/filesystem-config-collector.js.map +1 -1
  210. package/dist/util/config/compound-config-collector.d.ts +9 -2
  211. package/dist/util/config/compound-config-collector.js +16 -24
  212. package/dist/util/config/compound-config-collector.js.map +1 -1
  213. package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js.map +1 -1
  214. package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js.map +1 -1
  215. package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js.map +1 -1
  216. package/dist/util/config/sync-rules/sync-rules-provider.d.ts +9 -0
  217. package/dist/util/config/sync-rules/sync-rules-provider.js +15 -0
  218. package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -0
  219. package/dist/util/config/types.d.ts +7 -4
  220. package/dist/util/config/types.js.map +1 -1
  221. package/dist/util/config.d.ts +3 -4
  222. package/dist/util/config.js +5 -20
  223. package/dist/util/config.js.map +1 -1
  224. package/dist/util/memory-tracking.js.map +1 -1
  225. package/dist/util/secs.js.map +1 -1
  226. package/dist/util/util-index.d.ts +3 -6
  227. package/dist/util/util-index.js +3 -6
  228. package/dist/util/util-index.js.map +1 -1
  229. package/dist/util/utils.d.ts +10 -7
  230. package/dist/util/utils.js +36 -25
  231. package/dist/util/utils.js.map +1 -1
  232. package/package.json +8 -12
  233. package/src/api/RouteAPI.ts +78 -0
  234. package/src/api/api-index.ts +1 -0
  235. package/src/api/diagnostics.ts +18 -70
  236. package/src/api/schema.ts +18 -90
  237. package/src/auth/KeyStore.ts +9 -6
  238. package/src/auth/RemoteJWKSCollector.ts +4 -1
  239. package/src/auth/auth-index.ts +0 -1
  240. package/src/db/mongo.ts +5 -3
  241. package/src/entry/cli-entry.ts +3 -2
  242. package/src/entry/commands/compact-action.ts +24 -12
  243. package/src/entry/commands/migrate-action.ts +5 -8
  244. package/src/entry/commands/teardown-action.ts +2 -2
  245. package/src/index.ts +5 -2
  246. package/src/metrics/Metrics.ts +6 -16
  247. package/src/migrations/db/migrations/1684951997326-init.ts +9 -4
  248. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -4
  249. package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +6 -4
  250. package/src/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.ts +37 -0
  251. package/src/migrations/migrations.ts +24 -8
  252. package/src/modules/AbstractModule.ts +37 -0
  253. package/src/modules/ModuleManager.ts +34 -0
  254. package/src/modules/modules-index.ts +2 -0
  255. package/src/replication/AbstractReplicationJob.ts +79 -0
  256. package/src/replication/AbstractReplicator.ts +228 -0
  257. package/src/replication/ErrorRateLimiter.ts +0 -44
  258. package/src/replication/ReplicationEngine.ts +43 -0
  259. package/src/replication/ReplicationModule.ts +122 -0
  260. package/src/replication/replication-index.ts +4 -6
  261. package/src/routes/RouterEngine.ts +120 -0
  262. package/src/routes/auth.ts +21 -12
  263. package/src/routes/configure-fastify.ts +28 -28
  264. package/src/routes/configure-rsocket.ts +13 -8
  265. package/src/routes/endpoints/admin.ts +72 -76
  266. package/src/routes/endpoints/checkpointing.ts +51 -11
  267. package/src/routes/endpoints/probes.ts +58 -0
  268. package/src/routes/endpoints/socket-route.ts +10 -6
  269. package/src/routes/endpoints/sync-rules.ts +41 -25
  270. package/src/routes/endpoints/sync-stream.ts +8 -8
  271. package/src/routes/router.ts +10 -5
  272. package/src/routes/routes-index.ts +1 -0
  273. package/src/runner/teardown.ts +50 -88
  274. package/src/storage/BucketStorage.ts +103 -41
  275. package/src/storage/MongoBucketStorage.ts +65 -53
  276. package/src/storage/ReplicationEventPayload.ts +16 -0
  277. package/src/storage/SourceEntity.ts +22 -0
  278. package/src/storage/SourceTable.ts +14 -7
  279. package/src/storage/StorageEngine.ts +62 -0
  280. package/src/storage/StorageProvider.ts +27 -0
  281. package/src/storage/WriteCheckpointAPI.ts +85 -0
  282. package/src/storage/mongo/MongoBucketBatch.ts +164 -84
  283. package/src/storage/mongo/MongoCompactor.ts +25 -4
  284. package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +7 -4
  285. package/src/storage/mongo/MongoStorageProvider.ts +31 -0
  286. package/src/storage/mongo/MongoSyncBucketStorage.ts +118 -41
  287. package/src/storage/mongo/MongoSyncRulesLock.ts +7 -3
  288. package/src/storage/mongo/MongoWriteCheckpointAPI.ts +151 -0
  289. package/src/storage/mongo/OperationBatch.ts +28 -12
  290. package/src/storage/mongo/PersistedBatch.ts +10 -6
  291. package/src/storage/mongo/config.ts +40 -0
  292. package/src/storage/mongo/db.ts +4 -1
  293. package/src/storage/mongo/models.ts +21 -5
  294. package/src/storage/mongo/util.ts +48 -3
  295. package/src/storage/storage-index.ts +8 -2
  296. package/src/sync/sync.ts +7 -4
  297. package/src/sync/util.ts +0 -1
  298. package/src/system/ServiceContext.ts +68 -0
  299. package/src/system/system-index.ts +1 -1
  300. package/src/util/config/compound-config-collector.ts +31 -31
  301. package/src/util/config/sync-rules/sync-rules-provider.ts +18 -0
  302. package/src/util/config/types.ts +7 -5
  303. package/src/util/config.ts +6 -23
  304. package/src/util/util-index.ts +3 -6
  305. package/src/util/utils.ts +48 -41
  306. package/test/src/__snapshots__/sync.test.ts.snap +14 -14
  307. package/test/src/auth.test.ts +7 -7
  308. package/test/src/broadcast_iterable.test.ts +1 -1
  309. package/test/src/compacting.test.ts +50 -40
  310. package/test/src/data_storage.test.ts +382 -202
  311. package/test/src/env.ts +1 -3
  312. package/test/src/merge_iterable.test.ts +1 -6
  313. package/test/src/routes/probes.integration.test.ts +235 -0
  314. package/test/src/routes/probes.test.ts +153 -0
  315. package/test/src/setup.ts +1 -1
  316. package/test/src/stream_utils.ts +42 -0
  317. package/test/src/sync.test.ts +115 -39
  318. package/test/src/util.ts +48 -51
  319. package/test/tsconfig.json +1 -1
  320. package/tsconfig.tsbuildinfo +1 -1
  321. package/vitest.config.ts +7 -1
  322. package/dist/auth/SupabaseKeyCollector.d.ts +0 -22
  323. package/dist/auth/SupabaseKeyCollector.js +0 -61
  324. package/dist/auth/SupabaseKeyCollector.js.map +0 -1
  325. package/dist/replication/PgRelation.d.ts +0 -16
  326. package/dist/replication/PgRelation.js +0 -26
  327. package/dist/replication/PgRelation.js.map +0 -1
  328. package/dist/replication/WalConnection.d.ts +0 -34
  329. package/dist/replication/WalConnection.js +0 -190
  330. package/dist/replication/WalConnection.js.map +0 -1
  331. package/dist/replication/WalStream.d.ts +0 -57
  332. package/dist/replication/WalStream.js +0 -519
  333. package/dist/replication/WalStream.js.map +0 -1
  334. package/dist/replication/WalStreamManager.d.ts +0 -30
  335. package/dist/replication/WalStreamManager.js +0 -198
  336. package/dist/replication/WalStreamManager.js.map +0 -1
  337. package/dist/replication/WalStreamRunner.d.ts +0 -38
  338. package/dist/replication/WalStreamRunner.js +0 -155
  339. package/dist/replication/WalStreamRunner.js.map +0 -1
  340. package/dist/replication/util.d.ts +0 -9
  341. package/dist/replication/util.js +0 -62
  342. package/dist/replication/util.js.map +0 -1
  343. package/dist/system/CorePowerSyncSystem.d.ts +0 -23
  344. package/dist/system/CorePowerSyncSystem.js +0 -52
  345. package/dist/system/CorePowerSyncSystem.js.map +0 -1
  346. package/dist/util/PgManager.d.ts +0 -24
  347. package/dist/util/PgManager.js +0 -55
  348. package/dist/util/PgManager.js.map +0 -1
  349. package/dist/util/migration_lib.d.ts +0 -11
  350. package/dist/util/migration_lib.js +0 -64
  351. package/dist/util/migration_lib.js.map +0 -1
  352. package/dist/util/pgwire_utils.d.ts +0 -24
  353. package/dist/util/pgwire_utils.js +0 -117
  354. package/dist/util/pgwire_utils.js.map +0 -1
  355. package/dist/util/populate_test_data.d.ts +0 -8
  356. package/dist/util/populate_test_data.js +0 -65
  357. package/dist/util/populate_test_data.js.map +0 -1
  358. package/src/auth/SupabaseKeyCollector.ts +0 -67
  359. package/src/replication/PgRelation.ts +0 -42
  360. package/src/replication/WalConnection.ts +0 -227
  361. package/src/replication/WalStream.ts +0 -631
  362. package/src/replication/WalStreamManager.ts +0 -213
  363. package/src/replication/WalStreamRunner.ts +0 -180
  364. package/src/replication/util.ts +0 -76
  365. package/src/system/CorePowerSyncSystem.ts +0 -64
  366. package/src/util/PgManager.ts +0 -64
  367. package/src/util/migration_lib.ts +0 -79
  368. package/src/util/pgwire_utils.ts +0 -139
  369. package/src/util/populate_test_data.ts +0 -78
  370. package/test/src/__snapshots__/pg_test.test.ts.snap +0 -256
  371. package/test/src/large_batch.test.ts +0 -194
  372. package/test/src/pg_test.test.ts +0 -450
  373. package/test/src/schema_changes.test.ts +0 -545
  374. package/test/src/slow_tests.test.ts +0 -338
  375. package/test/src/validation.test.ts +0 -63
  376. package/test/src/wal_stream.test.ts +0 -319
  377. package/test/src/wal_stream_utils.ts +0 -156
@@ -1,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
- }