@powersync/service-core 0.0.0-dev-20240725112650 → 0.0.0-dev-20240918092408

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 (331) hide show
  1. package/CHANGELOG.md +80 -2
  2. package/dist/api/RouteAPI.d.ts +68 -0
  3. package/dist/api/RouteAPI.js +2 -0
  4. package/dist/api/RouteAPI.js.map +1 -0
  5. package/dist/api/api-index.d.ts +1 -0
  6. package/dist/api/api-index.js +1 -0
  7. package/dist/api/api-index.js.map +1 -1
  8. package/dist/api/diagnostics.d.ts +4 -4
  9. package/dist/api/diagnostics.js +11 -65
  10. package/dist/api/diagnostics.js.map +1 -1
  11. package/dist/api/schema.d.ts +3 -5
  12. package/dist/api/schema.js +9 -79
  13. package/dist/api/schema.js.map +1 -1
  14. package/dist/auth/KeyStore.d.ts +7 -4
  15. package/dist/auth/KeyStore.js +1 -1
  16. package/dist/auth/KeyStore.js.map +1 -1
  17. package/dist/auth/auth-index.d.ts +0 -1
  18. package/dist/auth/auth-index.js +0 -1
  19. package/dist/auth/auth-index.js.map +1 -1
  20. package/dist/entry/cli-entry.js +3 -2
  21. package/dist/entry/cli-entry.js.map +1 -1
  22. package/dist/entry/commands/compact-action.js +12 -8
  23. package/dist/entry/commands/compact-action.js.map +1 -1
  24. package/dist/entry/commands/migrate-action.js +4 -5
  25. package/dist/entry/commands/migrate-action.js.map +1 -1
  26. package/dist/entry/commands/teardown-action.js +2 -2
  27. package/dist/entry/commands/teardown-action.js.map +1 -1
  28. package/dist/index.d.ts +4 -2
  29. package/dist/index.js +4 -2
  30. package/dist/index.js.map +1 -1
  31. package/dist/metrics/Metrics.d.ts +2 -2
  32. package/dist/metrics/Metrics.js +5 -13
  33. package/dist/metrics/Metrics.js.map +1 -1
  34. package/dist/migrations/db/migrations/1684951997326-init.d.ts +2 -2
  35. package/dist/migrations/db/migrations/1684951997326-init.js +4 -2
  36. package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
  37. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +2 -2
  38. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +4 -2
  39. package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
  40. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +2 -2
  41. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +4 -2
  42. package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
  43. package/dist/migrations/migrations.d.ts +8 -0
  44. package/dist/migrations/migrations.js +19 -7
  45. package/dist/migrations/migrations.js.map +1 -1
  46. package/dist/modules/AbstractModule.d.ts +26 -0
  47. package/dist/modules/AbstractModule.js +11 -0
  48. package/dist/modules/AbstractModule.js.map +1 -0
  49. package/dist/modules/ModuleManager.d.ts +11 -0
  50. package/dist/modules/ModuleManager.js +32 -0
  51. package/dist/modules/ModuleManager.js.map +1 -0
  52. package/dist/modules/modules-index.d.ts +2 -0
  53. package/dist/modules/modules-index.js +3 -0
  54. package/dist/modules/modules-index.js.map +1 -0
  55. package/dist/replication/AbstractReplicationJob.d.ts +38 -0
  56. package/dist/replication/AbstractReplicationJob.js +51 -0
  57. package/dist/replication/AbstractReplicationJob.js.map +1 -0
  58. package/dist/replication/AbstractReplicator.d.ts +53 -0
  59. package/dist/replication/AbstractReplicator.js +187 -0
  60. package/dist/replication/AbstractReplicator.js.map +1 -0
  61. package/dist/replication/ErrorRateLimiter.d.ts +0 -9
  62. package/dist/replication/ErrorRateLimiter.js +1 -42
  63. package/dist/replication/ErrorRateLimiter.js.map +1 -1
  64. package/dist/replication/ReplicationEngine.d.ts +18 -0
  65. package/dist/replication/ReplicationEngine.js +41 -0
  66. package/dist/replication/ReplicationEngine.js.map +1 -0
  67. package/dist/replication/ReplicationModule.d.ts +39 -0
  68. package/dist/replication/ReplicationModule.js +65 -0
  69. package/dist/replication/ReplicationModule.js.map +1 -0
  70. package/dist/replication/replication-index.d.ts +4 -6
  71. package/dist/replication/replication-index.js +4 -6
  72. package/dist/replication/replication-index.js.map +1 -1
  73. package/dist/routes/RouterEngine.d.ts +42 -0
  74. package/dist/routes/RouterEngine.js +80 -0
  75. package/dist/routes/RouterEngine.js.map +1 -0
  76. package/dist/routes/auth.d.ts +2 -2
  77. package/dist/routes/auth.js +11 -11
  78. package/dist/routes/auth.js.map +1 -1
  79. package/dist/routes/configure-fastify.d.ts +30 -176
  80. package/dist/routes/configure-fastify.js +10 -11
  81. package/dist/routes/configure-fastify.js.map +1 -1
  82. package/dist/routes/configure-rsocket.d.ts +3 -3
  83. package/dist/routes/configure-rsocket.js +6 -5
  84. package/dist/routes/configure-rsocket.js.map +1 -1
  85. package/dist/routes/endpoints/admin.d.ts +0 -34
  86. package/dist/routes/endpoints/admin.js +48 -89
  87. package/dist/routes/endpoints/admin.js.map +1 -1
  88. package/dist/routes/endpoints/checkpointing.d.ts +56 -16
  89. package/dist/routes/endpoints/checkpointing.js +33 -12
  90. package/dist/routes/endpoints/checkpointing.js.map +1 -1
  91. package/dist/routes/endpoints/route-endpoints-index.d.ts +0 -1
  92. package/dist/routes/endpoints/route-endpoints-index.js +0 -1
  93. package/dist/routes/endpoints/route-endpoints-index.js.map +1 -1
  94. package/dist/routes/endpoints/socket-route.js +40 -25
  95. package/dist/routes/endpoints/socket-route.js.map +1 -1
  96. package/dist/routes/endpoints/sync-rules.d.ts +1 -1
  97. package/dist/routes/endpoints/sync-rules.js +32 -23
  98. package/dist/routes/endpoints/sync-rules.js.map +1 -1
  99. package/dist/routes/endpoints/sync-stream.d.ts +10 -0
  100. package/dist/routes/endpoints/sync-stream.js +13 -8
  101. package/dist/routes/endpoints/sync-stream.js.map +1 -1
  102. package/dist/routes/router-socket.d.ts +1 -0
  103. package/dist/routes/router-socket.js +2 -1
  104. package/dist/routes/router-socket.js.map +1 -1
  105. package/dist/routes/router.d.ts +6 -2
  106. package/dist/routes/router.js.map +1 -1
  107. package/dist/routes/routes-index.d.ts +1 -0
  108. package/dist/routes/routes-index.js +1 -0
  109. package/dist/routes/routes-index.js.map +1 -1
  110. package/dist/runner/teardown.js +47 -76
  111. package/dist/runner/teardown.js.map +1 -1
  112. package/dist/storage/BucketStorage.d.ts +30 -19
  113. package/dist/storage/BucketStorage.js +0 -10
  114. package/dist/storage/BucketStorage.js.map +1 -1
  115. package/dist/storage/MongoBucketStorage.d.ts +4 -4
  116. package/dist/storage/MongoBucketStorage.js +19 -24
  117. package/dist/storage/MongoBucketStorage.js.map +1 -1
  118. package/dist/storage/SourceEntity.d.ts +20 -0
  119. package/dist/storage/SourceEntity.js +2 -0
  120. package/dist/storage/SourceEntity.js.map +1 -0
  121. package/dist/storage/SourceTable.d.ts +4 -5
  122. package/dist/storage/SourceTable.js +3 -4
  123. package/dist/storage/SourceTable.js.map +1 -1
  124. package/dist/storage/StorageEngine.d.ts +24 -0
  125. package/dist/storage/StorageEngine.js +43 -0
  126. package/dist/storage/StorageEngine.js.map +1 -0
  127. package/dist/storage/StorageProvider.d.ts +21 -0
  128. package/dist/storage/StorageProvider.js +2 -0
  129. package/dist/storage/StorageProvider.js.map +1 -0
  130. package/dist/storage/mongo/MongoBucketBatch.d.ts +1 -1
  131. package/dist/storage/mongo/MongoBucketBatch.js +6 -7
  132. package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
  133. package/dist/storage/mongo/MongoCompactor.js +2 -1
  134. package/dist/storage/mongo/MongoCompactor.js.map +1 -1
  135. package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +2 -2
  136. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +2 -2
  137. package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -1
  138. package/dist/storage/mongo/MongoStorageProvider.d.ts +5 -0
  139. package/dist/storage/mongo/MongoStorageProvider.js +26 -0
  140. package/dist/storage/mongo/MongoStorageProvider.js.map +1 -0
  141. package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +7 -6
  142. package/dist/storage/mongo/MongoSyncBucketStorage.js +24 -15
  143. package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
  144. package/dist/storage/mongo/MongoSyncRulesLock.js +1 -1
  145. package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -1
  146. package/dist/storage/mongo/OperationBatch.d.ts +7 -3
  147. package/dist/storage/mongo/OperationBatch.js +16 -7
  148. package/dist/storage/mongo/OperationBatch.js.map +1 -1
  149. package/dist/storage/mongo/PersistedBatch.d.ts +3 -3
  150. package/dist/storage/mongo/PersistedBatch.js +2 -2
  151. package/dist/storage/mongo/PersistedBatch.js.map +1 -1
  152. package/dist/storage/mongo/models.d.ts +13 -4
  153. package/dist/storage/mongo/models.js.map +1 -1
  154. package/dist/storage/mongo/util.d.ts +12 -1
  155. package/dist/storage/mongo/util.js +50 -2
  156. package/dist/storage/mongo/util.js.map +1 -1
  157. package/dist/storage/storage-index.d.ts +5 -2
  158. package/dist/storage/storage-index.js +5 -2
  159. package/dist/storage/storage-index.js.map +1 -1
  160. package/dist/sync/sync.d.ts +2 -1
  161. package/dist/sync/sync.js +36 -10
  162. package/dist/sync/sync.js.map +1 -1
  163. package/dist/sync/util.js.map +1 -1
  164. package/dist/system/ServiceContext.d.ts +37 -0
  165. package/dist/system/ServiceContext.js +48 -0
  166. package/dist/system/ServiceContext.js.map +1 -0
  167. package/dist/system/system-index.d.ts +1 -1
  168. package/dist/system/system-index.js +1 -1
  169. package/dist/system/system-index.js.map +1 -1
  170. package/dist/util/config/compound-config-collector.d.ts +9 -2
  171. package/dist/util/config/compound-config-collector.js +14 -23
  172. package/dist/util/config/compound-config-collector.js.map +1 -1
  173. package/dist/util/config/sync-rules/sync-rules-provider.d.ts +9 -0
  174. package/dist/util/config/sync-rules/sync-rules-provider.js +15 -0
  175. package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -0
  176. package/dist/util/config/types.d.ts +6 -4
  177. package/dist/util/config/types.js.map +1 -1
  178. package/dist/util/config.d.ts +3 -4
  179. package/dist/util/config.js +5 -20
  180. package/dist/util/config.js.map +1 -1
  181. package/dist/util/protocol-types.d.ts +4 -0
  182. package/dist/util/protocol-types.js +5 -1
  183. package/dist/util/protocol-types.js.map +1 -1
  184. package/dist/util/util-index.d.ts +3 -6
  185. package/dist/util/util-index.js +3 -6
  186. package/dist/util/util-index.js.map +1 -1
  187. package/dist/util/utils.d.ts +10 -6
  188. package/dist/util/utils.js +45 -25
  189. package/dist/util/utils.js.map +1 -1
  190. package/package.json +5 -7
  191. package/src/api/RouteAPI.ts +78 -0
  192. package/src/api/api-index.ts +1 -0
  193. package/src/api/diagnostics.ts +16 -71
  194. package/src/api/schema.ts +13 -89
  195. package/src/auth/KeyStore.ts +9 -6
  196. package/src/auth/auth-index.ts +0 -1
  197. package/src/entry/cli-entry.ts +3 -2
  198. package/src/entry/commands/compact-action.ts +12 -9
  199. package/src/entry/commands/migrate-action.ts +5 -8
  200. package/src/entry/commands/teardown-action.ts +2 -2
  201. package/src/index.ts +5 -2
  202. package/src/metrics/Metrics.ts +6 -16
  203. package/src/migrations/db/migrations/1684951997326-init.ts +9 -4
  204. package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -4
  205. package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +6 -4
  206. package/src/migrations/migrations.ts +24 -8
  207. package/src/modules/AbstractModule.ts +37 -0
  208. package/src/modules/ModuleManager.ts +34 -0
  209. package/src/modules/modules-index.ts +2 -0
  210. package/src/replication/AbstractReplicationJob.ts +79 -0
  211. package/src/replication/AbstractReplicator.ts +227 -0
  212. package/src/replication/ErrorRateLimiter.ts +0 -44
  213. package/src/replication/ReplicationEngine.ts +43 -0
  214. package/src/replication/ReplicationModule.ts +101 -0
  215. package/src/replication/replication-index.ts +4 -6
  216. package/src/routes/RouterEngine.ts +120 -0
  217. package/src/routes/auth.ts +21 -12
  218. package/src/routes/configure-fastify.ts +13 -14
  219. package/src/routes/configure-rsocket.ts +9 -8
  220. package/src/routes/endpoints/admin.ts +74 -100
  221. package/src/routes/endpoints/checkpointing.ts +46 -12
  222. package/src/routes/endpoints/route-endpoints-index.ts +0 -1
  223. package/src/routes/endpoints/socket-route.ts +44 -27
  224. package/src/routes/endpoints/sync-rules.ts +41 -25
  225. package/src/routes/endpoints/sync-stream.ts +13 -8
  226. package/src/routes/router-socket.ts +2 -1
  227. package/src/routes/router.ts +6 -3
  228. package/src/routes/routes-index.ts +1 -0
  229. package/src/runner/teardown.ts +50 -88
  230. package/src/storage/BucketStorage.ts +38 -25
  231. package/src/storage/MongoBucketStorage.ts +23 -26
  232. package/src/storage/SourceEntity.ts +22 -0
  233. package/src/storage/SourceTable.ts +4 -6
  234. package/src/storage/StorageEngine.ts +55 -0
  235. package/src/storage/StorageProvider.ts +27 -0
  236. package/src/storage/mongo/MongoBucketBatch.ts +8 -8
  237. package/src/storage/mongo/MongoCompactor.ts +2 -1
  238. package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +3 -3
  239. package/src/storage/mongo/MongoStorageProvider.ts +31 -0
  240. package/src/storage/mongo/MongoSyncBucketStorage.ts +39 -20
  241. package/src/storage/mongo/MongoSyncRulesLock.ts +1 -1
  242. package/src/storage/mongo/OperationBatch.ts +18 -11
  243. package/src/storage/mongo/PersistedBatch.ts +6 -5
  244. package/src/storage/mongo/models.ts +13 -4
  245. package/src/storage/mongo/util.ts +49 -4
  246. package/src/storage/storage-index.ts +5 -2
  247. package/src/sync/sync.ts +46 -11
  248. package/src/sync/util.ts +0 -1
  249. package/src/system/ServiceContext.ts +68 -0
  250. package/src/system/system-index.ts +1 -1
  251. package/src/util/config/compound-config-collector.ts +30 -31
  252. package/src/util/config/sync-rules/sync-rules-provider.ts +18 -0
  253. package/src/util/config/types.ts +6 -5
  254. package/src/util/config.ts +6 -23
  255. package/src/util/protocol-types.ts +6 -1
  256. package/src/util/util-index.ts +3 -6
  257. package/src/util/utils.ts +55 -39
  258. package/test/src/__snapshots__/sync.test.ts.snap +7 -7
  259. package/test/src/auth.test.ts +7 -7
  260. package/test/src/broadcast_iterable.test.ts +1 -1
  261. package/test/src/checksum_cache.test.ts +3 -3
  262. package/test/src/compacting.test.ts +26 -17
  263. package/test/src/data_storage.test.ts +258 -146
  264. package/test/src/env.ts +1 -3
  265. package/test/src/merge_iterable.test.ts +1 -6
  266. package/test/src/setup.ts +1 -1
  267. package/test/src/stream_utils.ts +42 -0
  268. package/test/src/sync.test.ts +52 -31
  269. package/test/src/util.ts +48 -51
  270. package/test/tsconfig.json +1 -1
  271. package/tsconfig.tsbuildinfo +1 -1
  272. package/dist/auth/SupabaseKeyCollector.d.ts +0 -22
  273. package/dist/auth/SupabaseKeyCollector.js +0 -61
  274. package/dist/auth/SupabaseKeyCollector.js.map +0 -1
  275. package/dist/replication/PgRelation.d.ts +0 -16
  276. package/dist/replication/PgRelation.js +0 -26
  277. package/dist/replication/PgRelation.js.map +0 -1
  278. package/dist/replication/WalConnection.d.ts +0 -34
  279. package/dist/replication/WalConnection.js +0 -190
  280. package/dist/replication/WalConnection.js.map +0 -1
  281. package/dist/replication/WalStream.d.ts +0 -57
  282. package/dist/replication/WalStream.js +0 -515
  283. package/dist/replication/WalStream.js.map +0 -1
  284. package/dist/replication/WalStreamManager.d.ts +0 -30
  285. package/dist/replication/WalStreamManager.js +0 -198
  286. package/dist/replication/WalStreamManager.js.map +0 -1
  287. package/dist/replication/WalStreamRunner.d.ts +0 -38
  288. package/dist/replication/WalStreamRunner.js +0 -155
  289. package/dist/replication/WalStreamRunner.js.map +0 -1
  290. package/dist/replication/util.d.ts +0 -9
  291. package/dist/replication/util.js +0 -62
  292. package/dist/replication/util.js.map +0 -1
  293. package/dist/routes/endpoints/dev.d.ts +0 -312
  294. package/dist/routes/endpoints/dev.js +0 -172
  295. package/dist/routes/endpoints/dev.js.map +0 -1
  296. package/dist/system/CorePowerSyncSystem.d.ts +0 -23
  297. package/dist/system/CorePowerSyncSystem.js +0 -52
  298. package/dist/system/CorePowerSyncSystem.js.map +0 -1
  299. package/dist/util/PgManager.d.ts +0 -24
  300. package/dist/util/PgManager.js +0 -55
  301. package/dist/util/PgManager.js.map +0 -1
  302. package/dist/util/migration_lib.d.ts +0 -11
  303. package/dist/util/migration_lib.js +0 -64
  304. package/dist/util/migration_lib.js.map +0 -1
  305. package/dist/util/pgwire_utils.d.ts +0 -24
  306. package/dist/util/pgwire_utils.js +0 -117
  307. package/dist/util/pgwire_utils.js.map +0 -1
  308. package/dist/util/populate_test_data.d.ts +0 -8
  309. package/dist/util/populate_test_data.js +0 -65
  310. package/dist/util/populate_test_data.js.map +0 -1
  311. package/src/auth/SupabaseKeyCollector.ts +0 -67
  312. package/src/replication/PgRelation.ts +0 -42
  313. package/src/replication/WalConnection.ts +0 -227
  314. package/src/replication/WalStream.ts +0 -624
  315. package/src/replication/WalStreamManager.ts +0 -213
  316. package/src/replication/WalStreamRunner.ts +0 -180
  317. package/src/replication/util.ts +0 -76
  318. package/src/routes/endpoints/dev.ts +0 -199
  319. package/src/system/CorePowerSyncSystem.ts +0 -64
  320. package/src/util/PgManager.ts +0 -64
  321. package/src/util/migration_lib.ts +0 -79
  322. package/src/util/pgwire_utils.ts +0 -139
  323. package/src/util/populate_test_data.ts +0 -78
  324. package/test/src/__snapshots__/pg_test.test.ts.snap +0 -256
  325. package/test/src/large_batch.test.ts +0 -194
  326. package/test/src/pg_test.test.ts +0 -450
  327. package/test/src/schema_changes.test.ts +0 -545
  328. package/test/src/slow_tests.test.ts +0 -338
  329. package/test/src/validation.test.ts +0 -63
  330. package/test/src/wal_stream.test.ts +0 -319
  331. package/test/src/wal_stream_utils.ts +0 -156
package/src/util/utils.ts CHANGED
@@ -1,14 +1,19 @@
1
+ import * as sync_rules from '@powersync/service-sync-rules';
2
+ import * as bson from 'bson';
1
3
  import crypto from 'crypto';
2
- import * as pgwire from '@powersync/service-jpgwire';
3
- import { pgwireRows } from '@powersync/service-jpgwire';
4
+ import * as uuid from 'uuid';
5
+ import { BucketChecksum, OpId } from './protocol-types.js';
4
6
 
5
7
  import * as storage from '../storage/storage-index.js';
6
- import { BucketChecksum, OpId } from './protocol-types.js';
7
- import { retriedQuery } from './pgwire_utils.js';
8
- import { logger } from '@powersync/lib-services-framework';
9
8
 
10
9
  export type ChecksumMap = Map<string, BucketChecksum>;
11
10
 
11
+ export const ID_NAMESPACE = 'a396dd91-09fc-4017-a28d-3df722f651e9';
12
+
13
+ export function escapeIdentifier(identifier: string) {
14
+ return `"${identifier.replace(/"/g, '""').replace(/\./g, '"."')}"`;
15
+ }
16
+
12
17
  export function hashData(type: string, id: string, data: string): number {
13
18
  const hash = crypto.createHash('sha256');
14
19
  hash.update(`put.${type}.${id}.${data}`);
@@ -76,47 +81,58 @@ export function addBucketChecksums(a: BucketChecksum, b: BucketChecksum | null):
76
81
  }
77
82
  }
78
83
 
79
- export async function getClientCheckpoint(
80
- db: pgwire.PgClient,
81
- bucketStorage: storage.BucketStorageFactory,
82
- options?: { timeout?: number }
83
- ): Promise<OpId> {
84
- const start = Date.now();
84
+ function getRawReplicaIdentity(
85
+ tuple: sync_rules.ToastableSqliteRow,
86
+ columns: storage.ColumnDescriptor[]
87
+ ): Record<string, any> {
88
+ let result: Record<string, any> = {};
89
+ for (let column of columns) {
90
+ const name = column.name;
91
+ result[name] = tuple[name];
92
+ }
93
+ return result;
94
+ }
85
95
 
86
- const [{ lsn }] = pgwireRows(await db.query(`SELECT pg_logical_emit_message(false, 'powersync', 'ping') as lsn`));
96
+ export function getUuidReplicaIdentityBson(
97
+ tuple: sync_rules.ToastableSqliteRow,
98
+ columns: storage.ColumnDescriptor[]
99
+ ): bson.UUID {
100
+ if (columns.length == 0) {
101
+ // REPLICA IDENTITY NOTHING - generate random id
102
+ return new bson.UUID(uuid.v4());
103
+ }
104
+ const rawIdentity = getRawReplicaIdentity(tuple, columns);
87
105
 
88
- // This old API needs a persisted checkpoint id.
89
- // Since we don't use LSNs anymore, the only way to get that is to wait.
106
+ return uuidForRowBson(rawIdentity);
107
+ }
90
108
 
91
- const timeout = options?.timeout ?? 50_000;
109
+ export function uuidForRowBson(row: sync_rules.SqliteRow): bson.UUID {
110
+ // Important: This must not change, since it will affect how ids are generated.
111
+ // Use BSON so that it's a well-defined format without encoding ambiguities.
112
+ const repr = bson.serialize(row);
113
+ const buffer = Buffer.alloc(16);
114
+ return new bson.UUID(uuid.v5(repr, ID_NAMESPACE, buffer));
115
+ }
92
116
 
93
- logger.info(`Waiting for LSN checkpoint: ${lsn}`);
94
- while (Date.now() - start < timeout) {
95
- const cp = await bucketStorage.getActiveCheckpoint();
96
- if (!cp.hasSyncRules()) {
97
- throw new Error('No sync rules available');
117
+ export function hasToastedValues(row: sync_rules.ToastableSqliteRow) {
118
+ for (let key in row) {
119
+ if (typeof row[key] == 'undefined') {
120
+ return true;
98
121
  }
99
- if (cp.lsn >= lsn) {
100
- logger.info(`Got write checkpoint: ${lsn} : ${cp.checkpoint}`);
101
- return cp.checkpoint;
102
- }
103
-
104
- await new Promise((resolve) => setTimeout(resolve, 30));
105
122
  }
123
+ return false;
124
+ }
106
125
 
107
- throw new Error('Timeout while waiting for checkpoint');
126
+ export function isCompleteRow(row: sync_rules.ToastableSqliteRow): row is sync_rules.SqliteRow {
127
+ return !hasToastedValues(row);
108
128
  }
109
129
 
110
- export async function createWriteCheckpoint(
111
- db: pgwire.PgClient,
112
- bucketStorage: storage.BucketStorageFactory,
113
- user_id: string
114
- ): Promise<bigint> {
115
- const [{ lsn }] = pgwireRows(
116
- await retriedQuery(db, `SELECT pg_logical_emit_message(false, 'powersync', 'ping') as lsn`)
117
- );
118
-
119
- const id = await bucketStorage.createWriteCheckpoint(user_id, { '1': lsn });
120
- logger.info(`Write checkpoint 2: ${JSON.stringify({ lsn, id: String(id) })}`);
121
- return id;
130
+ export function checkpointUserId(user_id: string | undefined, client_id: string | undefined) {
131
+ if (user_id == null) {
132
+ throw new Error('user_id is required');
133
+ }
134
+ if (client_id == null) {
135
+ return user_id;
136
+ }
137
+ return `${user_id}/${client_id}`;
122
138
  }
@@ -61,7 +61,7 @@ exports[`sync - mongodb > compacting data - invalidate checkpoint 2`] = `
61
61
  "object_type": "test",
62
62
  "op": "PUT",
63
63
  "op_id": "3",
64
- "subkey": "6544e3899293153fa7b38331/117ab485-4b42-58a2-ab32-0053a22c3423",
64
+ "subkey": "e5aa2ddc-1328-58fa-a000-0b5ed31eaf1a",
65
65
  },
66
66
  {
67
67
  "checksum": 3028503153n,
@@ -70,7 +70,7 @@ exports[`sync - mongodb > compacting data - invalidate checkpoint 2`] = `
70
70
  "object_type": "test",
71
71
  "op": "PUT",
72
72
  "op_id": "4",
73
- "subkey": "6544e3899293153fa7b38331/ec27c691-b47a-5d92-927a-9944feb89eee",
73
+ "subkey": "13423353-9f27-59b4-baf0-64a5e09f1769",
74
74
  },
75
75
  ],
76
76
  "has_more": false,
@@ -151,7 +151,7 @@ exports[`sync - mongodb > sync global data 1`] = `
151
151
  "object_type": "test",
152
152
  "op": "PUT",
153
153
  "op_id": "1",
154
- "subkey": "6544e3899293153fa7b38331/117ab485-4b42-58a2-ab32-0053a22c3423",
154
+ "subkey": "e5aa2ddc-1328-58fa-a000-0b5ed31eaf1a",
155
155
  },
156
156
  {
157
157
  "checksum": 3280762209n,
@@ -160,7 +160,7 @@ exports[`sync - mongodb > sync global data 1`] = `
160
160
  "object_type": "test",
161
161
  "op": "PUT",
162
162
  "op_id": "2",
163
- "subkey": "6544e3899293153fa7b38331/ec27c691-b47a-5d92-927a-9944feb89eee",
163
+ "subkey": "13423353-9f27-59b4-baf0-64a5e09f1769",
164
164
  },
165
165
  ],
166
166
  "has_more": false,
@@ -207,7 +207,7 @@ exports[`sync - mongodb > sync legacy non-raw data 1`] = `
207
207
  "object_type": "test",
208
208
  "op": "PUT",
209
209
  "op_id": "1",
210
- "subkey": "6544e3899293153fa7b38331/117ab485-4b42-58a2-ab32-0053a22c3423",
210
+ "subkey": "e5aa2ddc-1328-58fa-a000-0b5ed31eaf1a",
211
211
  },
212
212
  ],
213
213
  "has_more": false,
@@ -273,7 +273,7 @@ exports[`sync - mongodb > sync updates to global data 2`] = `
273
273
  "object_type": "test",
274
274
  "op": "PUT",
275
275
  "op_id": "1",
276
- "subkey": "6544e3899293153fa7b38331/117ab485-4b42-58a2-ab32-0053a22c3423",
276
+ "subkey": "e5aa2ddc-1328-58fa-a000-0b5ed31eaf1a",
277
277
  },
278
278
  ],
279
279
  "has_more": false,
@@ -316,7 +316,7 @@ exports[`sync - mongodb > sync updates to global data 3`] = `
316
316
  "object_type": "test",
317
317
  "op": "PUT",
318
318
  "op_id": "2",
319
- "subkey": "6544e3899293153fa7b38331/ec27c691-b47a-5d92-927a-9944feb89eee",
319
+ "subkey": "13423353-9f27-59b4-baf0-64a5e09f1769",
320
320
  },
321
321
  ],
322
322
  "has_more": false,
@@ -1,11 +1,11 @@
1
- import { describe, expect, test } from 'vitest';
2
- import { StaticKeyCollector } from '../../src/auth/StaticKeyCollector.js';
1
+ import { CachedKeyCollector } from '@/auth/CachedKeyCollector.js';
2
+ import { KeyResult } from '@/auth/KeyCollector.js';
3
+ import { KeySpec } from '@/auth/KeySpec.js';
4
+ import { KeyStore } from '@/auth/KeyStore.js';
5
+ import { RemoteJWKSCollector } from '@/auth/RemoteJWKSCollector.js';
6
+ import { StaticKeyCollector } from '@/auth/StaticKeyCollector.js';
3
7
  import * as jose from 'jose';
4
- import { KeyStore } from '../../src/auth/KeyStore.js';
5
- import { KeySpec } from '../../src/auth/KeySpec.js';
6
- import { RemoteJWKSCollector } from '../../src/auth/RemoteJWKSCollector.js';
7
- import { KeyResult } from '../../src/auth/KeyCollector.js';
8
- import { CachedKeyCollector } from '../../src/auth/CachedKeyCollector.js';
8
+ import { describe, expect, test } from 'vitest';
9
9
 
10
10
  const publicKey: jose.JWK = {
11
11
  use: 'sig',
@@ -1,3 +1,4 @@
1
+ import { BroadcastIterable, IterableSource } from '@/sync/BroadcastIterable.js';
1
2
  import { AsyncIterableX, interval } from 'ix/asynciterable/index.js';
2
3
  import { delayEach } from 'ix/asynciterable/operators/delayeach.js';
3
4
  import { take } from 'ix/asynciterable/operators/take.js';
@@ -5,7 +6,6 @@ import { wrapWithAbort } from 'ix/asynciterable/operators/withabort.js';
5
6
  import { toArray } from 'ix/asynciterable/toarray.js';
6
7
  import * as timers from 'timers/promises';
7
8
  import { describe, expect, test } from 'vitest';
8
- import { BroadcastIterable, IterableSource } from '../../src/sync/BroadcastIterable.js';
9
9
 
10
10
  describe('BroadcastIterable', () => {
11
11
  test('should iterate', async () => {
@@ -1,8 +1,8 @@
1
- import { describe, expect, it } from 'vitest';
1
+ import { ChecksumCache, FetchChecksums, FetchPartialBucketChecksum } from '@/storage/ChecksumCache.js';
2
2
  import { BucketChecksum, OpId } from '@/util/protocol-types.js';
3
- import * as crypto from 'node:crypto';
4
3
  import { addBucketChecksums } from '@/util/util-index.js';
5
- import { ChecksumCache, FetchChecksums, FetchPartialBucketChecksum } from '@/storage/ChecksumCache.js';
4
+ import * as crypto from 'node:crypto';
5
+ import { describe, expect, it } from 'vitest';
6
6
 
7
7
  /**
8
8
  * Create a deterministic BucketChecksum based on the bucket name and checkpoint for testing purposes.
@@ -1,9 +1,11 @@
1
+ import { MongoCompactOptions } from '@/storage/mongo/MongoCompactor.js';
1
2
  import { SqlSyncRules } from '@powersync/service-sync-rules';
2
3
  import { describe, expect, test } from 'vitest';
3
- import { makeTestTable, MONGO_STORAGE_FACTORY } from './util.js';
4
- import { oneFromAsync } from './wal_stream_utils.js';
5
- import { MongoCompactOptions } from '@/storage/mongo/MongoCompactor.js';
6
- import { reduceBucket, validateCompactedBucket, validateBucket } from './bucket_validation.js';
4
+ import { validateCompactedBucket } from './bucket_validation.js';
5
+ import { oneFromAsync } from './stream_utils.js';
6
+ import { BATCH_OPTIONS, makeTestTable, MONGO_STORAGE_FACTORY, rid, testRules, ZERO_LSN } from './util.js';
7
+ import { ParseSyncRulesOptions, PersistedSyncRulesContent, StartBatchOptions } from '@/storage/BucketStorage.js';
8
+ import { getUuidReplicaIdentityBson } from '@/util/util-index.js';
7
9
 
8
10
  const TEST_TABLE = makeTestTable('test', ['id']);
9
11
 
@@ -18,21 +20,22 @@ function compactTests(compactOptions: MongoCompactOptions) {
18
20
  const factory = MONGO_STORAGE_FACTORY;
19
21
 
20
22
  test('compacting (1)', async () => {
21
- const sync_rules = SqlSyncRules.fromYaml(`
23
+ const sync_rules = testRules(`
22
24
  bucket_definitions:
23
25
  global:
24
26
  data: [select * from test]
25
27
  `);
26
28
 
27
- const storage = (await factory()).getInstance({ id: 1, sync_rules, slot_name: 'test' });
29
+ const storage = (await factory()).getInstance(sync_rules);
28
30
 
29
- const result = await storage.startBatch({}, async (batch) => {
31
+ const result = await storage.startBatch(BATCH_OPTIONS, async (batch) => {
30
32
  await batch.save({
31
33
  sourceTable: TEST_TABLE,
32
34
  tag: 'insert',
33
35
  after: {
34
36
  id: 't1'
35
- }
37
+ },
38
+ afterReplicaId: rid('t1')
36
39
  });
37
40
 
38
41
  await batch.save({
@@ -40,7 +43,8 @@ bucket_definitions:
40
43
  tag: 'insert',
41
44
  after: {
42
45
  id: 't2'
43
- }
46
+ },
47
+ afterReplicaId: rid('t2')
44
48
  });
45
49
 
46
50
  await batch.save({
@@ -48,7 +52,8 @@ bucket_definitions:
48
52
  tag: 'update',
49
53
  after: {
50
54
  id: 't2'
51
- }
55
+ },
56
+ afterReplicaId: rid('t2')
52
57
  });
53
58
  });
54
59
 
@@ -108,21 +113,22 @@ bucket_definitions:
108
113
  });
109
114
 
110
115
  test('compacting (2)', async () => {
111
- const sync_rules = SqlSyncRules.fromYaml(`
116
+ const sync_rules = testRules(`
112
117
  bucket_definitions:
113
118
  global:
114
119
  data: [select * from test]
115
120
  `);
116
121
 
117
- const storage = (await factory()).getInstance({ id: 1, sync_rules, slot_name: 'test' });
122
+ const storage = (await factory()).getInstance(sync_rules);
118
123
 
119
- const result = await storage.startBatch({}, async (batch) => {
124
+ const result = await storage.startBatch(BATCH_OPTIONS, async (batch) => {
120
125
  await batch.save({
121
126
  sourceTable: TEST_TABLE,
122
127
  tag: 'insert',
123
128
  after: {
124
129
  id: 't1'
125
- }
130
+ },
131
+ afterReplicaId: rid('t1')
126
132
  });
127
133
 
128
134
  await batch.save({
@@ -130,7 +136,8 @@ bucket_definitions:
130
136
  tag: 'insert',
131
137
  after: {
132
138
  id: 't2'
133
- }
139
+ },
140
+ afterReplicaId: rid('t2')
134
141
  });
135
142
 
136
143
  await batch.save({
@@ -138,7 +145,8 @@ bucket_definitions:
138
145
  tag: 'delete',
139
146
  before: {
140
147
  id: 't1'
141
- }
148
+ },
149
+ beforeReplicaId: rid('t1')
142
150
  });
143
151
 
144
152
  await batch.save({
@@ -146,7 +154,8 @@ bucket_definitions:
146
154
  tag: 'update',
147
155
  after: {
148
156
  id: 't2'
149
- }
157
+ },
158
+ afterReplicaId: rid('t2')
150
159
  });
151
160
  });
152
161