@powersync/service-core 0.8.8 → 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.
- package/CHANGELOG.md +31 -0
- package/dist/api/RouteAPI.d.ts +67 -0
- package/dist/api/RouteAPI.js +2 -0
- package/dist/api/RouteAPI.js.map +1 -0
- package/dist/api/api-index.d.ts +1 -0
- package/dist/api/api-index.js +1 -0
- package/dist/api/api-index.js.map +1 -1
- package/dist/api/diagnostics.d.ts +4 -4
- package/dist/api/diagnostics.js +170 -158
- package/dist/api/diagnostics.js.map +1 -1
- package/dist/api/schema.d.ts +3 -5
- package/dist/api/schema.js +14 -80
- package/dist/api/schema.js.map +1 -1
- package/dist/auth/CachedKeyCollector.js.map +1 -1
- package/dist/auth/KeySpec.js.map +1 -1
- package/dist/auth/KeyStore.d.ts +7 -4
- package/dist/auth/KeyStore.js +1 -1
- package/dist/auth/KeyStore.js.map +1 -1
- package/dist/auth/LeakyBucket.js.map +1 -1
- package/dist/auth/RemoteJWKSCollector.d.ts +0 -2
- package/dist/auth/RemoteJWKSCollector.js.map +1 -1
- package/dist/auth/auth-index.d.ts +0 -1
- package/dist/auth/auth-index.js +0 -1
- package/dist/auth/auth-index.js.map +1 -1
- package/dist/db/mongo.js +5 -3
- package/dist/db/mongo.js.map +1 -1
- package/dist/entry/cli-entry.js +3 -2
- package/dist/entry/cli-entry.js.map +1 -1
- package/dist/entry/commands/compact-action.js +90 -14
- package/dist/entry/commands/compact-action.js.map +1 -1
- package/dist/entry/commands/migrate-action.js +4 -5
- package/dist/entry/commands/migrate-action.js.map +1 -1
- package/dist/entry/commands/teardown-action.js +2 -2
- package/dist/entry/commands/teardown-action.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/locks/MongoLocks.js.map +1 -1
- package/dist/metrics/Metrics.d.ts +2 -2
- package/dist/metrics/Metrics.js +5 -13
- package/dist/metrics/Metrics.js.map +1 -1
- package/dist/migrations/db/migrations/1684951997326-init.d.ts +2 -2
- package/dist/migrations/db/migrations/1684951997326-init.js +4 -2
- package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -1
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +2 -2
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +4 -2
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -1
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +2 -2
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +4 -2
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -1
- package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.d.ts +3 -0
- package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js +31 -0
- package/dist/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.js.map +1 -0
- package/dist/migrations/executor.js.map +1 -1
- package/dist/migrations/migrations.d.ts +8 -0
- package/dist/migrations/migrations.js +19 -7
- package/dist/migrations/migrations.js.map +1 -1
- package/dist/migrations/store/migration-store.js.map +1 -1
- package/dist/modules/AbstractModule.d.ts +26 -0
- package/dist/modules/AbstractModule.js +11 -0
- package/dist/modules/AbstractModule.js.map +1 -0
- package/dist/modules/ModuleManager.d.ts +11 -0
- package/dist/modules/ModuleManager.js +32 -0
- package/dist/modules/ModuleManager.js.map +1 -0
- package/dist/modules/modules-index.d.ts +2 -0
- package/dist/modules/modules-index.js +3 -0
- package/dist/modules/modules-index.js.map +1 -0
- package/dist/replication/AbstractReplicationJob.d.ts +37 -0
- package/dist/replication/AbstractReplicationJob.js +51 -0
- package/dist/replication/AbstractReplicationJob.js.map +1 -0
- package/dist/replication/AbstractReplicator.d.ts +53 -0
- package/dist/replication/AbstractReplicator.js +250 -0
- package/dist/replication/AbstractReplicator.js.map +1 -0
- package/dist/replication/ErrorRateLimiter.d.ts +0 -10
- package/dist/replication/ErrorRateLimiter.js +1 -42
- package/dist/replication/ErrorRateLimiter.js.map +1 -1
- package/dist/replication/ReplicationEngine.d.ts +18 -0
- package/dist/replication/ReplicationEngine.js +41 -0
- package/dist/replication/ReplicationEngine.js.map +1 -0
- package/dist/replication/ReplicationModule.d.ts +51 -0
- package/dist/replication/ReplicationModule.js +68 -0
- package/dist/replication/ReplicationModule.js.map +1 -0
- package/dist/replication/replication-index.d.ts +4 -6
- package/dist/replication/replication-index.js +4 -6
- package/dist/replication/replication-index.js.map +1 -1
- package/dist/routes/RouterEngine.d.ts +42 -0
- package/dist/routes/RouterEngine.js +80 -0
- package/dist/routes/RouterEngine.js.map +1 -0
- package/dist/routes/auth.d.ts +2 -2
- package/dist/routes/auth.js +11 -11
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/configure-fastify.d.ts +37 -23
- package/dist/routes/configure-fastify.js +18 -18
- package/dist/routes/configure-fastify.js.map +1 -1
- package/dist/routes/configure-rsocket.d.ts +3 -4
- package/dist/routes/configure-rsocket.js +7 -4
- package/dist/routes/configure-rsocket.js.map +1 -1
- package/dist/routes/endpoints/admin.d.ts +30 -0
- package/dist/routes/endpoints/admin.js +46 -67
- package/dist/routes/endpoints/admin.js.map +1 -1
- package/dist/routes/endpoints/checkpointing.js +103 -15
- package/dist/routes/endpoints/checkpointing.js.map +1 -1
- package/dist/routes/endpoints/socket-route.js +8 -6
- package/dist/routes/endpoints/socket-route.js.map +1 -1
- package/dist/routes/endpoints/sync-rules.d.ts +1 -1
- package/dist/routes/endpoints/sync-rules.js +32 -23
- package/dist/routes/endpoints/sync-rules.js.map +1 -1
- package/dist/routes/endpoints/sync-stream.d.ts +0 -1
- package/dist/routes/endpoints/sync-stream.js +8 -8
- package/dist/routes/endpoints/sync-stream.js.map +1 -1
- package/dist/routes/hooks.js.map +1 -1
- package/dist/routes/route-register.js.map +1 -1
- package/dist/routes/router.d.ts +9 -2
- package/dist/routes/router.js.map +1 -1
- package/dist/routes/routes-index.d.ts +1 -0
- package/dist/routes/routes-index.js +1 -0
- package/dist/routes/routes-index.js.map +1 -1
- package/dist/runner/teardown.js +109 -76
- package/dist/runner/teardown.js.map +1 -1
- package/dist/storage/BucketStorage.d.ts +86 -36
- package/dist/storage/BucketStorage.js +6 -10
- package/dist/storage/BucketStorage.js.map +1 -1
- package/dist/storage/ChecksumCache.js.map +1 -1
- package/dist/storage/MongoBucketStorage.d.ts +7 -11
- package/dist/storage/MongoBucketStorage.js +48 -41
- package/dist/storage/MongoBucketStorage.js.map +1 -1
- package/dist/storage/ReplicationEventPayload.d.ts +14 -0
- package/dist/storage/ReplicationEventPayload.js +2 -0
- package/dist/storage/ReplicationEventPayload.js.map +1 -0
- package/dist/storage/SourceEntity.d.ts +20 -0
- package/dist/storage/SourceEntity.js +2 -0
- package/dist/storage/SourceEntity.js.map +1 -0
- package/dist/storage/SourceTable.d.ts +12 -5
- package/dist/storage/SourceTable.js +12 -5
- package/dist/storage/SourceTable.js.map +1 -1
- package/dist/storage/StorageEngine.d.ts +28 -0
- package/dist/storage/StorageEngine.js +45 -0
- package/dist/storage/StorageEngine.js.map +1 -0
- package/dist/storage/StorageProvider.d.ts +21 -0
- package/dist/storage/StorageProvider.js +2 -0
- package/dist/storage/StorageProvider.js.map +1 -0
- package/dist/storage/WriteCheckpointAPI.d.ts +74 -0
- package/dist/storage/WriteCheckpointAPI.js +16 -0
- package/dist/storage/WriteCheckpointAPI.js.map +1 -0
- package/dist/storage/mongo/MongoBucketBatch.d.ts +24 -5
- package/dist/storage/mongo/MongoBucketBatch.js +119 -62
- package/dist/storage/mongo/MongoBucketBatch.js.map +1 -1
- package/dist/storage/mongo/MongoCompactor.js +20 -3
- package/dist/storage/mongo/MongoCompactor.js.map +1 -1
- package/dist/storage/mongo/MongoIdSequence.js.map +1 -1
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +2 -2
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +2 -2
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -1
- package/dist/storage/mongo/MongoStorageProvider.d.ts +5 -0
- package/dist/storage/mongo/MongoStorageProvider.js +26 -0
- package/dist/storage/mongo/MongoStorageProvider.js.map +1 -0
- package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +18 -10
- package/dist/storage/mongo/MongoSyncBucketStorage.js +140 -25
- package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -1
- package/dist/storage/mongo/MongoSyncRulesLock.js +1 -1
- package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -1
- package/dist/storage/mongo/MongoWriteCheckpointAPI.d.ts +20 -0
- package/dist/storage/mongo/MongoWriteCheckpointAPI.js +103 -0
- package/dist/storage/mongo/MongoWriteCheckpointAPI.js.map +1 -0
- package/dist/storage/mongo/OperationBatch.d.ts +13 -4
- package/dist/storage/mongo/OperationBatch.js +25 -7
- package/dist/storage/mongo/OperationBatch.js.map +1 -1
- package/dist/storage/mongo/PersistedBatch.d.ts +3 -3
- package/dist/storage/mongo/PersistedBatch.js +2 -2
- package/dist/storage/mongo/PersistedBatch.js.map +1 -1
- package/dist/storage/mongo/config.d.ts +19 -0
- package/dist/storage/mongo/config.js +26 -0
- package/dist/storage/mongo/config.js.map +1 -0
- package/dist/storage/mongo/db.d.ts +3 -2
- package/dist/storage/mongo/db.js +1 -0
- package/dist/storage/mongo/db.js.map +1 -1
- package/dist/storage/mongo/models.d.ts +20 -5
- package/dist/storage/mongo/models.js.map +1 -1
- package/dist/storage/mongo/util.d.ts +12 -1
- package/dist/storage/mongo/util.js +50 -2
- package/dist/storage/mongo/util.js.map +1 -1
- package/dist/storage/storage-index.d.ts +8 -2
- package/dist/storage/storage-index.js +8 -2
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/sync/BroadcastIterable.d.ts +0 -1
- package/dist/sync/BroadcastIterable.js.map +1 -1
- package/dist/sync/LastValueSink.d.ts +0 -1
- package/dist/sync/LastValueSink.js.map +1 -1
- package/dist/sync/merge.d.ts +0 -1
- package/dist/sync/merge.js.map +1 -1
- package/dist/sync/safeRace.js.map +1 -1
- package/dist/sync/sync.d.ts +1 -1
- package/dist/sync/sync.js +5 -5
- package/dist/sync/sync.js.map +1 -1
- package/dist/sync/util.d.ts +0 -2
- package/dist/sync/util.js.map +1 -1
- package/dist/system/ServiceContext.d.ts +37 -0
- package/dist/system/ServiceContext.js +48 -0
- package/dist/system/ServiceContext.js.map +1 -0
- package/dist/system/system-index.d.ts +1 -1
- package/dist/system/system-index.js +1 -1
- package/dist/system/system-index.js.map +1 -1
- package/dist/util/Mutex.js.map +1 -1
- package/dist/util/config/collectors/config-collector.js.map +1 -1
- package/dist/util/config/collectors/impl/base64-config-collector.js.map +1 -1
- package/dist/util/config/collectors/impl/filesystem-config-collector.js.map +1 -1
- package/dist/util/config/compound-config-collector.d.ts +9 -2
- package/dist/util/config/compound-config-collector.js +16 -24
- package/dist/util/config/compound-config-collector.js.map +1 -1
- package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js.map +1 -1
- package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js.map +1 -1
- package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js.map +1 -1
- package/dist/util/config/sync-rules/sync-rules-provider.d.ts +9 -0
- package/dist/util/config/sync-rules/sync-rules-provider.js +15 -0
- package/dist/util/config/sync-rules/sync-rules-provider.js.map +1 -0
- package/dist/util/config/types.d.ts +7 -4
- package/dist/util/config/types.js.map +1 -1
- package/dist/util/config.d.ts +3 -4
- package/dist/util/config.js +5 -20
- package/dist/util/config.js.map +1 -1
- package/dist/util/memory-tracking.js.map +1 -1
- package/dist/util/secs.js.map +1 -1
- package/dist/util/util-index.d.ts +3 -6
- package/dist/util/util-index.js +3 -6
- package/dist/util/util-index.js.map +1 -1
- package/dist/util/utils.d.ts +10 -7
- package/dist/util/utils.js +36 -25
- package/dist/util/utils.js.map +1 -1
- package/package.json +8 -12
- package/src/api/RouteAPI.ts +78 -0
- package/src/api/api-index.ts +1 -0
- package/src/api/diagnostics.ts +18 -70
- package/src/api/schema.ts +18 -90
- package/src/auth/KeyStore.ts +9 -6
- package/src/auth/RemoteJWKSCollector.ts +4 -1
- package/src/auth/auth-index.ts +0 -1
- package/src/db/mongo.ts +5 -3
- package/src/entry/cli-entry.ts +3 -2
- package/src/entry/commands/compact-action.ts +24 -12
- package/src/entry/commands/migrate-action.ts +5 -8
- package/src/entry/commands/teardown-action.ts +2 -2
- package/src/index.ts +5 -2
- package/src/metrics/Metrics.ts +6 -16
- package/src/migrations/db/migrations/1684951997326-init.ts +9 -4
- package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +7 -4
- package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +6 -4
- package/src/migrations/db/migrations/1727099539247-custom-write-checkpoint-index.ts +37 -0
- package/src/migrations/migrations.ts +24 -8
- package/src/modules/AbstractModule.ts +37 -0
- package/src/modules/ModuleManager.ts +34 -0
- package/src/modules/modules-index.ts +2 -0
- package/src/replication/AbstractReplicationJob.ts +79 -0
- package/src/replication/AbstractReplicator.ts +228 -0
- package/src/replication/ErrorRateLimiter.ts +0 -44
- package/src/replication/ReplicationEngine.ts +43 -0
- package/src/replication/ReplicationModule.ts +122 -0
- package/src/replication/replication-index.ts +4 -6
- package/src/routes/RouterEngine.ts +120 -0
- package/src/routes/auth.ts +21 -12
- package/src/routes/configure-fastify.ts +26 -27
- package/src/routes/configure-rsocket.ts +13 -8
- package/src/routes/endpoints/admin.ts +72 -76
- package/src/routes/endpoints/checkpointing.ts +51 -11
- package/src/routes/endpoints/socket-route.ts +10 -6
- package/src/routes/endpoints/sync-rules.ts +41 -25
- package/src/routes/endpoints/sync-stream.ts +8 -8
- package/src/routes/router.ts +8 -3
- package/src/routes/routes-index.ts +1 -0
- package/src/runner/teardown.ts +50 -88
- package/src/storage/BucketStorage.ts +103 -41
- package/src/storage/MongoBucketStorage.ts +65 -53
- package/src/storage/ReplicationEventPayload.ts +16 -0
- package/src/storage/SourceEntity.ts +22 -0
- package/src/storage/SourceTable.ts +14 -7
- package/src/storage/StorageEngine.ts +62 -0
- package/src/storage/StorageProvider.ts +27 -0
- package/src/storage/WriteCheckpointAPI.ts +85 -0
- package/src/storage/mongo/MongoBucketBatch.ts +164 -84
- package/src/storage/mongo/MongoCompactor.ts +25 -4
- package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +7 -4
- package/src/storage/mongo/MongoStorageProvider.ts +31 -0
- package/src/storage/mongo/MongoSyncBucketStorage.ts +118 -41
- package/src/storage/mongo/MongoSyncRulesLock.ts +7 -3
- package/src/storage/mongo/MongoWriteCheckpointAPI.ts +151 -0
- package/src/storage/mongo/OperationBatch.ts +28 -12
- package/src/storage/mongo/PersistedBatch.ts +10 -6
- package/src/storage/mongo/config.ts +40 -0
- package/src/storage/mongo/db.ts +4 -1
- package/src/storage/mongo/models.ts +21 -5
- package/src/storage/mongo/util.ts +48 -3
- package/src/storage/storage-index.ts +8 -2
- package/src/sync/sync.ts +7 -4
- package/src/sync/util.ts +0 -1
- package/src/system/ServiceContext.ts +68 -0
- package/src/system/system-index.ts +1 -1
- package/src/util/config/compound-config-collector.ts +31 -31
- package/src/util/config/sync-rules/sync-rules-provider.ts +18 -0
- package/src/util/config/types.ts +7 -5
- package/src/util/config.ts +6 -23
- package/src/util/util-index.ts +3 -6
- package/src/util/utils.ts +48 -41
- package/test/src/__snapshots__/sync.test.ts.snap +14 -14
- package/test/src/auth.test.ts +7 -7
- package/test/src/broadcast_iterable.test.ts +1 -1
- package/test/src/compacting.test.ts +50 -40
- package/test/src/data_storage.test.ts +382 -202
- package/test/src/env.ts +1 -3
- package/test/src/merge_iterable.test.ts +1 -6
- package/test/src/routes/probes.integration.test.ts +34 -30
- package/test/src/setup.ts +1 -1
- package/test/src/stream_utils.ts +42 -0
- package/test/src/sync.test.ts +115 -39
- package/test/src/util.ts +48 -51
- package/test/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +7 -1
- package/dist/auth/SupabaseKeyCollector.d.ts +0 -22
- package/dist/auth/SupabaseKeyCollector.js +0 -61
- package/dist/auth/SupabaseKeyCollector.js.map +0 -1
- package/dist/replication/PgRelation.d.ts +0 -16
- package/dist/replication/PgRelation.js +0 -26
- package/dist/replication/PgRelation.js.map +0 -1
- package/dist/replication/WalConnection.d.ts +0 -34
- package/dist/replication/WalConnection.js +0 -190
- package/dist/replication/WalConnection.js.map +0 -1
- package/dist/replication/WalStream.d.ts +0 -57
- package/dist/replication/WalStream.js +0 -519
- package/dist/replication/WalStream.js.map +0 -1
- package/dist/replication/WalStreamManager.d.ts +0 -30
- package/dist/replication/WalStreamManager.js +0 -198
- package/dist/replication/WalStreamManager.js.map +0 -1
- package/dist/replication/WalStreamRunner.d.ts +0 -38
- package/dist/replication/WalStreamRunner.js +0 -155
- package/dist/replication/WalStreamRunner.js.map +0 -1
- package/dist/replication/util.d.ts +0 -9
- package/dist/replication/util.js +0 -62
- package/dist/replication/util.js.map +0 -1
- package/dist/system/CorePowerSyncSystem.d.ts +0 -23
- package/dist/system/CorePowerSyncSystem.js +0 -52
- package/dist/system/CorePowerSyncSystem.js.map +0 -1
- package/dist/util/PgManager.d.ts +0 -24
- package/dist/util/PgManager.js +0 -55
- package/dist/util/PgManager.js.map +0 -1
- package/dist/util/migration_lib.d.ts +0 -11
- package/dist/util/migration_lib.js +0 -64
- package/dist/util/migration_lib.js.map +0 -1
- package/dist/util/pgwire_utils.d.ts +0 -24
- package/dist/util/pgwire_utils.js +0 -117
- package/dist/util/pgwire_utils.js.map +0 -1
- package/dist/util/populate_test_data.d.ts +0 -8
- package/dist/util/populate_test_data.js +0 -65
- package/dist/util/populate_test_data.js.map +0 -1
- package/src/auth/SupabaseKeyCollector.ts +0 -67
- package/src/replication/PgRelation.ts +0 -42
- package/src/replication/WalConnection.ts +0 -227
- package/src/replication/WalStream.ts +0 -631
- package/src/replication/WalStreamManager.ts +0 -213
- package/src/replication/WalStreamRunner.ts +0 -180
- package/src/replication/util.ts +0 -76
- package/src/system/CorePowerSyncSystem.ts +0 -64
- package/src/util/PgManager.ts +0 -64
- package/src/util/migration_lib.ts +0 -79
- package/src/util/pgwire_utils.ts +0 -139
- package/src/util/populate_test_data.ts +0 -78
- package/test/src/__snapshots__/pg_test.test.ts.snap +0 -256
- package/test/src/large_batch.test.ts +0 -194
- package/test/src/pg_test.test.ts +0 -450
- package/test/src/schema_changes.test.ts +0 -545
- package/test/src/slow_tests.test.ts +0 -338
- package/test/src/validation.test.ts +0 -63
- package/test/src/wal_stream.test.ts +0 -319
- package/test/src/wal_stream_utils.ts +0 -156
|
@@ -13,9 +13,10 @@ import {
|
|
|
13
13
|
BucketParameterDocument,
|
|
14
14
|
CurrentBucket,
|
|
15
15
|
CurrentDataDocument,
|
|
16
|
-
SourceKey
|
|
16
|
+
SourceKey,
|
|
17
|
+
ReplicaId
|
|
17
18
|
} from './models.js';
|
|
18
|
-
import { serializeLookup } from './util.js';
|
|
19
|
+
import { replicaIdToSubkey, serializeLookup } from './util.js';
|
|
19
20
|
import { logger } from '@powersync/lib-services-framework';
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -53,13 +54,16 @@ export class PersistedBatch {
|
|
|
53
54
|
*/
|
|
54
55
|
currentSize = 0;
|
|
55
56
|
|
|
56
|
-
constructor(
|
|
57
|
+
constructor(
|
|
58
|
+
private group_id: number,
|
|
59
|
+
writtenSize: number
|
|
60
|
+
) {
|
|
57
61
|
this.currentSize = writtenSize;
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
saveBucketData(options: {
|
|
61
65
|
op_seq: MongoIdSequence;
|
|
62
|
-
sourceKey:
|
|
66
|
+
sourceKey: ReplicaId;
|
|
63
67
|
table: SourceTable;
|
|
64
68
|
evaluated: EvaluatedRow[];
|
|
65
69
|
before_buckets: CurrentBucket[];
|
|
@@ -70,7 +74,7 @@ export class PersistedBatch {
|
|
|
70
74
|
remaining_buckets.set(key, b);
|
|
71
75
|
}
|
|
72
76
|
|
|
73
|
-
const dchecksum = util.hashDelete(
|
|
77
|
+
const dchecksum = util.hashDelete(replicaIdToSubkey(options.table.id, options.sourceKey));
|
|
74
78
|
|
|
75
79
|
for (let k of options.evaluated) {
|
|
76
80
|
const key = currentBucketKey(k);
|
|
@@ -134,7 +138,7 @@ export class PersistedBatch {
|
|
|
134
138
|
|
|
135
139
|
saveParameterData(data: {
|
|
136
140
|
op_seq: MongoIdSequence;
|
|
137
|
-
sourceKey:
|
|
141
|
+
sourceKey: ReplicaId;
|
|
138
142
|
sourceTable: SourceTable;
|
|
139
143
|
evaluated: EvaluatedParameters[];
|
|
140
144
|
existing_lookups: bson.Binary[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as urijs from 'uri-js';
|
|
2
|
+
|
|
3
|
+
export interface MongoConnectionConfig {
|
|
4
|
+
uri: string;
|
|
5
|
+
username?: string;
|
|
6
|
+
password?: string;
|
|
7
|
+
database?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Validate and normalize connection options.
|
|
12
|
+
*
|
|
13
|
+
* Returns destructured options.
|
|
14
|
+
*
|
|
15
|
+
* For use by both storage and mongo module.
|
|
16
|
+
*/
|
|
17
|
+
export function normalizeMongoConfig(options: MongoConnectionConfig) {
|
|
18
|
+
let uri = urijs.parse(options.uri);
|
|
19
|
+
|
|
20
|
+
const database = options.database ?? uri.path?.substring(1) ?? '';
|
|
21
|
+
|
|
22
|
+
const userInfo = uri.userinfo?.split(':');
|
|
23
|
+
|
|
24
|
+
const username = options.username ?? userInfo?.[0];
|
|
25
|
+
const password = options.password ?? userInfo?.[1];
|
|
26
|
+
|
|
27
|
+
if (database == '') {
|
|
28
|
+
throw new Error(`database required`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
delete uri.userinfo;
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
uri: urijs.serialize(uri),
|
|
35
|
+
database,
|
|
36
|
+
|
|
37
|
+
username,
|
|
38
|
+
password
|
|
39
|
+
};
|
|
40
|
+
}
|
package/src/storage/mongo/db.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import * as mongo from 'mongodb';
|
|
2
2
|
|
|
3
|
+
import { configFile } from '@powersync/service-types';
|
|
3
4
|
import * as db from '../../db/db-index.js';
|
|
4
5
|
import * as locks from '../../locks/locks-index.js';
|
|
5
6
|
import {
|
|
6
7
|
BucketDataDocument,
|
|
7
8
|
BucketParameterDocument,
|
|
8
9
|
CurrentDataDocument,
|
|
10
|
+
CustomWriteCheckpointDocument,
|
|
9
11
|
IdSequenceDocument,
|
|
10
12
|
InstanceDocument,
|
|
11
13
|
SourceTableDocument,
|
|
@@ -13,7 +15,6 @@ import {
|
|
|
13
15
|
WriteCheckpointDocument
|
|
14
16
|
} from './models.js';
|
|
15
17
|
import { BSON_DESERIALIZE_OPTIONS } from './util.js';
|
|
16
|
-
import { configFile } from '@powersync/service-types';
|
|
17
18
|
|
|
18
19
|
export interface PowerSyncMongoOptions {
|
|
19
20
|
/**
|
|
@@ -33,6 +34,7 @@ export class PowerSyncMongo {
|
|
|
33
34
|
readonly op_id_sequence: mongo.Collection<IdSequenceDocument>;
|
|
34
35
|
readonly sync_rules: mongo.Collection<SyncRuleDocument>;
|
|
35
36
|
readonly source_tables: mongo.Collection<SourceTableDocument>;
|
|
37
|
+
readonly custom_write_checkpoints: mongo.Collection<CustomWriteCheckpointDocument>;
|
|
36
38
|
readonly write_checkpoints: mongo.Collection<WriteCheckpointDocument>;
|
|
37
39
|
readonly instance: mongo.Collection<InstanceDocument>;
|
|
38
40
|
readonly locks: mongo.Collection<locks.Lock>;
|
|
@@ -54,6 +56,7 @@ export class PowerSyncMongo {
|
|
|
54
56
|
this.op_id_sequence = db.collection('op_id_sequence');
|
|
55
57
|
this.sync_rules = db.collection('sync_rules');
|
|
56
58
|
this.source_tables = db.collection('source_tables');
|
|
59
|
+
this.custom_write_checkpoints = db.collection('custom_write_checkpoints');
|
|
57
60
|
this.write_checkpoints = db.collection('write_checkpoints');
|
|
58
61
|
this.instance = db.collection('instance');
|
|
59
62
|
this.locks = this.db.collection('locks');
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import * as bson from 'bson';
|
|
2
1
|
import { SqliteJsonValue } from '@powersync/service-sync-rules';
|
|
2
|
+
import * as bson from 'bson';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Replica id uniquely identifying a row on the source database.
|
|
6
|
+
*
|
|
7
|
+
* Can be any value serializable to BSON.
|
|
8
|
+
*
|
|
9
|
+
* If the value is an entire document, the data serialized to a v5 UUID may be a good choice here.
|
|
10
|
+
*/
|
|
11
|
+
export type ReplicaId = bson.UUID | bson.Document | any;
|
|
3
12
|
|
|
4
13
|
export interface SourceKey {
|
|
5
14
|
/** group_id */
|
|
@@ -7,7 +16,7 @@ export interface SourceKey {
|
|
|
7
16
|
/** source table id */
|
|
8
17
|
t: bson.ObjectId;
|
|
9
18
|
/** source key */
|
|
10
|
-
k:
|
|
19
|
+
k: ReplicaId;
|
|
11
20
|
}
|
|
12
21
|
|
|
13
22
|
export interface BucketDataKey {
|
|
@@ -43,7 +52,7 @@ export interface BucketDataDocument {
|
|
|
43
52
|
_id: BucketDataKey;
|
|
44
53
|
op: OpType;
|
|
45
54
|
source_table?: bson.ObjectId;
|
|
46
|
-
source_key?:
|
|
55
|
+
source_key?: ReplicaId;
|
|
47
56
|
table?: string;
|
|
48
57
|
row_id?: string;
|
|
49
58
|
checksum: number;
|
|
@@ -57,11 +66,11 @@ export interface SourceTableDocument {
|
|
|
57
66
|
_id: bson.ObjectId;
|
|
58
67
|
group_id: number;
|
|
59
68
|
connection_id: number;
|
|
60
|
-
relation_id: number | undefined;
|
|
69
|
+
relation_id: number | string | undefined;
|
|
61
70
|
schema_name: string;
|
|
62
71
|
table_name: string;
|
|
63
72
|
replica_id_columns: string[] | null;
|
|
64
|
-
replica_id_columns2: { name: string; type_oid
|
|
73
|
+
replica_id_columns2: { name: string; type_oid?: number; type?: string }[] | undefined;
|
|
65
74
|
snapshot_done: boolean | undefined;
|
|
66
75
|
}
|
|
67
76
|
|
|
@@ -150,6 +159,13 @@ export interface SyncRuleDocument {
|
|
|
150
159
|
content: string;
|
|
151
160
|
}
|
|
152
161
|
|
|
162
|
+
export interface CustomWriteCheckpointDocument {
|
|
163
|
+
_id: bson.ObjectId;
|
|
164
|
+
user_id: string;
|
|
165
|
+
checkpoint: bigint;
|
|
166
|
+
sync_rules_id: number;
|
|
167
|
+
}
|
|
168
|
+
|
|
153
169
|
export interface WriteCheckpointDocument {
|
|
154
170
|
_id: bson.ObjectId;
|
|
155
171
|
user_id: string;
|
|
@@ -2,9 +2,10 @@ import { SqliteJsonValue } from '@powersync/service-sync-rules';
|
|
|
2
2
|
import * as bson from 'bson';
|
|
3
3
|
import * as crypto from 'crypto';
|
|
4
4
|
import * as mongo from 'mongodb';
|
|
5
|
+
import * as uuid from 'uuid';
|
|
5
6
|
import { OplogEntry } from '../../util/protocol-types.js';
|
|
6
|
-
import { timestampToOpId } from '../../util/utils.js';
|
|
7
|
-
import { BucketDataDocument } from './models.js';
|
|
7
|
+
import { ID_NAMESPACE, timestampToOpId } from '../../util/utils.js';
|
|
8
|
+
import { BucketDataDocument, ReplicaId } from './models.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Lookup serialization must be number-agnostic. I.e. normalize numbers, instead of preserving numbers.
|
|
@@ -98,7 +99,7 @@ export function mapOpEntry(row: BucketDataDocument): OplogEntry {
|
|
|
98
99
|
object_type: row.table,
|
|
99
100
|
object_id: row.row_id,
|
|
100
101
|
checksum: Number(row.checksum),
|
|
101
|
-
subkey:
|
|
102
|
+
subkey: replicaIdToSubkey(row.source_table!, row.source_key!),
|
|
102
103
|
data: row.data
|
|
103
104
|
};
|
|
104
105
|
} else {
|
|
@@ -111,3 +112,47 @@ export function mapOpEntry(row: BucketDataDocument): OplogEntry {
|
|
|
111
112
|
};
|
|
112
113
|
}
|
|
113
114
|
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Returns true if two ReplicaId values are the same (serializes to the same BSON value).
|
|
118
|
+
*/
|
|
119
|
+
export function replicaIdEquals(a: ReplicaId, b: ReplicaId) {
|
|
120
|
+
if (a === b) {
|
|
121
|
+
return true;
|
|
122
|
+
} else if (typeof a == 'string' && typeof b == 'string') {
|
|
123
|
+
return a == b;
|
|
124
|
+
} else if (isUUID(a) && isUUID(b)) {
|
|
125
|
+
return a.equals(b);
|
|
126
|
+
} else if (a == null && b == null) {
|
|
127
|
+
return true;
|
|
128
|
+
} else if (a != null || b != null) {
|
|
129
|
+
return false;
|
|
130
|
+
} else {
|
|
131
|
+
// There are many possible primitive values, this covers them all
|
|
132
|
+
return (bson.serialize({ id: a }) as Buffer).equals(bson.serialize({ id: b }));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function replicaIdToSubkey(table: bson.ObjectId, id: ReplicaId): string {
|
|
137
|
+
if (isUUID(id)) {
|
|
138
|
+
// Special case for UUID for backwards-compatiblity
|
|
139
|
+
return `${table.toHexString()}/${id.toHexString()}`;
|
|
140
|
+
} else {
|
|
141
|
+
// Hashed UUID from the table and id
|
|
142
|
+
const repr = bson.serialize({ table, id });
|
|
143
|
+
return uuid.v5(repr, ID_NAMESPACE);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* True if this is a bson.UUID.
|
|
149
|
+
*
|
|
150
|
+
* Works even with multiple copies of the bson package.
|
|
151
|
+
*/
|
|
152
|
+
export function isUUID(value: any): value is bson.UUID {
|
|
153
|
+
if (value == null || typeof value != 'object') {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
const uuid = value as bson.UUID;
|
|
157
|
+
return uuid._bsontype == 'Binary' && uuid.sub_type == bson.Binary.SUBTYPE_UUID;
|
|
158
|
+
}
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
export * from './SourceTable.js';
|
|
2
|
-
export * from './MongoBucketStorage.js';
|
|
3
1
|
export * from './BucketStorage.js';
|
|
2
|
+
export * from './MongoBucketStorage.js';
|
|
3
|
+
export * from './ReplicationEventPayload.js';
|
|
4
|
+
export * from './SourceEntity.js';
|
|
5
|
+
export * from './SourceTable.js';
|
|
6
|
+
export * from './StorageEngine.js';
|
|
4
7
|
|
|
8
|
+
export * from './mongo/config.js';
|
|
5
9
|
export * from './mongo/db.js';
|
|
6
10
|
export * from './mongo/models.js';
|
|
7
11
|
export * from './mongo/MongoBucketBatch.js';
|
|
8
12
|
export * from './mongo/MongoIdSequence.js';
|
|
9
13
|
export * from './mongo/MongoPersistedSyncRules.js';
|
|
10
14
|
export * from './mongo/MongoPersistedSyncRulesContent.js';
|
|
15
|
+
export * from './mongo/MongoStorageProvider.js';
|
|
11
16
|
export * from './mongo/MongoSyncBucketStorage.js';
|
|
12
17
|
export * from './mongo/MongoSyncRulesLock.js';
|
|
13
18
|
export * from './mongo/OperationBatch.js';
|
|
14
19
|
export * from './mongo/PersistedBatch.js';
|
|
15
20
|
export * from './mongo/util.js';
|
|
21
|
+
export * from './WriteCheckpointAPI.js';
|
package/src/sync/sync.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { JSONBig, JsonContainer } from '@powersync/service-jsonbig';
|
|
2
2
|
import { RequestParameters } from '@powersync/service-sync-rules';
|
|
3
3
|
import { Semaphore, withTimeout } from 'async-mutex';
|
|
4
|
+
|
|
4
5
|
import { AbortError } from 'ix/aborterror.js';
|
|
5
6
|
|
|
6
7
|
import * as auth from '../auth/auth-index.js';
|
|
@@ -35,6 +36,7 @@ export interface SyncStreamParameters {
|
|
|
35
36
|
params: util.StreamingSyncRequest;
|
|
36
37
|
syncParams: RequestParameters;
|
|
37
38
|
token: auth.JwtPayload;
|
|
39
|
+
parseOptions: storage.ParseSyncRulesOptions;
|
|
38
40
|
/**
|
|
39
41
|
* If this signal is aborted, the stream response ends as soon as possible, without error.
|
|
40
42
|
*/
|
|
@@ -47,7 +49,7 @@ export interface SyncStreamParameters {
|
|
|
47
49
|
export async function* streamResponse(
|
|
48
50
|
options: SyncStreamParameters
|
|
49
51
|
): AsyncIterable<util.StreamingSyncLine | string | null> {
|
|
50
|
-
const { storage, params, syncParams, token, tokenStreamOptions, tracker, signal } = options;
|
|
52
|
+
const { storage, params, syncParams, token, tokenStreamOptions, tracker, signal, parseOptions } = options;
|
|
51
53
|
// We also need to be able to abort, so we create our own controller.
|
|
52
54
|
const controller = new AbortController();
|
|
53
55
|
if (signal) {
|
|
@@ -63,7 +65,7 @@ export async function* streamResponse(
|
|
|
63
65
|
}
|
|
64
66
|
}
|
|
65
67
|
const ki = tokenStream(token, controller.signal, tokenStreamOptions);
|
|
66
|
-
const stream = streamResponseInner(storage, params, syncParams, tracker, controller.signal);
|
|
68
|
+
const stream = streamResponseInner(storage, params, syncParams, tracker, parseOptions, controller.signal);
|
|
67
69
|
// Merge the two streams, and abort as soon as one of the streams end.
|
|
68
70
|
const merged = mergeAsyncIterables([stream, ki], controller.signal);
|
|
69
71
|
|
|
@@ -87,6 +89,7 @@ async function* streamResponseInner(
|
|
|
87
89
|
params: util.StreamingSyncRequest,
|
|
88
90
|
syncParams: RequestParameters,
|
|
89
91
|
tracker: RequestTracker,
|
|
92
|
+
parseOptions: storage.ParseSyncRulesOptions,
|
|
90
93
|
signal: AbortSignal
|
|
91
94
|
): AsyncGenerator<util.StreamingSyncLine | string | null> {
|
|
92
95
|
// Bucket state of bucket id -> op_id.
|
|
@@ -115,9 +118,9 @@ async function* streamResponseInner(
|
|
|
115
118
|
// Sync rules deleted in the meantime - try again with the next checkpoint.
|
|
116
119
|
continue;
|
|
117
120
|
}
|
|
118
|
-
const
|
|
121
|
+
const syncRules = storage.getParsedSyncRules(parseOptions);
|
|
119
122
|
|
|
120
|
-
const allBuckets = await
|
|
123
|
+
const allBuckets = await syncRules.queryBucketIds({
|
|
121
124
|
getParameterSets(lookups) {
|
|
122
125
|
return storage.getParameterSets(checkpoint, lookups);
|
|
123
126
|
},
|
package/src/sync/util.ts
CHANGED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { LifeCycledSystem, ServiceIdentifier, container } from '@powersync/lib-services-framework';
|
|
2
|
+
|
|
3
|
+
import * as metrics from '../metrics/Metrics.js';
|
|
4
|
+
import * as replication from '../replication/replication-index.js';
|
|
5
|
+
import * as routes from '../routes/routes-index.js';
|
|
6
|
+
import * as storage from '../storage/storage-index.js';
|
|
7
|
+
import * as utils from '../util/util-index.js';
|
|
8
|
+
|
|
9
|
+
export interface ServiceContext {
|
|
10
|
+
configuration: utils.ResolvedPowerSyncConfig;
|
|
11
|
+
lifeCycleEngine: LifeCycledSystem;
|
|
12
|
+
metrics: metrics.Metrics | null;
|
|
13
|
+
replicationEngine: replication.ReplicationEngine | null;
|
|
14
|
+
routerEngine: routes.RouterEngine | null;
|
|
15
|
+
storageEngine: storage.StorageEngine;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Context which allows for registering and getting implementations
|
|
20
|
+
* of various service engines.
|
|
21
|
+
* This controls registering, initializing and the lifecycle of various services.
|
|
22
|
+
*/
|
|
23
|
+
export class ServiceContextContainer implements ServiceContext {
|
|
24
|
+
lifeCycleEngine: LifeCycledSystem;
|
|
25
|
+
storageEngine: storage.StorageEngine;
|
|
26
|
+
|
|
27
|
+
constructor(public configuration: utils.ResolvedPowerSyncConfig) {
|
|
28
|
+
this.lifeCycleEngine = new LifeCycledSystem();
|
|
29
|
+
|
|
30
|
+
this.storageEngine = new storage.StorageEngine({
|
|
31
|
+
configuration
|
|
32
|
+
});
|
|
33
|
+
this.lifeCycleEngine.withLifecycle(this.storageEngine, {
|
|
34
|
+
start: (storageEngine) => storageEngine.start(),
|
|
35
|
+
stop: (storageEngine) => storageEngine.shutDown()
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Mongo storage is available as an option by default TODO: Consider moving this to a Mongo Storage Module
|
|
39
|
+
this.storageEngine.registerProvider(new storage.MongoStorageProvider());
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get replicationEngine(): replication.ReplicationEngine | null {
|
|
43
|
+
return container.getOptional(replication.ReplicationEngine);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get routerEngine(): routes.RouterEngine | null {
|
|
47
|
+
return container.getOptional(routes.RouterEngine);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get metrics(): metrics.Metrics | null {
|
|
51
|
+
return container.getOptional(metrics.Metrics);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Allows for registering core and generic implementations of services/helpers.
|
|
56
|
+
* This uses the framework container under the hood.
|
|
57
|
+
*/
|
|
58
|
+
register<T>(identifier: ServiceIdentifier<T>, implementation: T) {
|
|
59
|
+
container.register(identifier, implementation);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Gets the implementation of an identifiable service.
|
|
64
|
+
*/
|
|
65
|
+
get<T>(identifier: ServiceIdentifier<T>) {
|
|
66
|
+
return container.getImplementation(identifier);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './ServiceContext.js';
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { ResolvedConnection, ResolvedPowerSyncConfig, RunnerConfig, SyncRulesConfig } from './types.js';
|
|
1
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
2
|
+
import { configFile } from '@powersync/service-types';
|
|
4
3
|
import * as auth from '../../auth/auth-index.js';
|
|
5
|
-
import {
|
|
4
|
+
import { ConfigCollector } from './collectors/config-collector.js';
|
|
6
5
|
import { Base64ConfigCollector } from './collectors/impl/base64-config-collector.js';
|
|
6
|
+
import { FallbackConfigCollector } from './collectors/impl/fallback-config-collector.js';
|
|
7
7
|
import { FileSystemConfigCollector } from './collectors/impl/filesystem-config-collector.js';
|
|
8
8
|
import { Base64SyncRulesCollector } from './sync-rules/impl/base64-sync-rules-collector.js';
|
|
9
|
-
import { InlineSyncRulesCollector } from './sync-rules/impl/inline-sync-rules-collector.js';
|
|
10
9
|
import { FileSystemSyncRulesCollector } from './sync-rules/impl/filesystem-sync-rules-collector.js';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
const POWERSYNC_DEV_KID = 'powersync-dev';
|
|
10
|
+
import { InlineSyncRulesCollector } from './sync-rules/impl/inline-sync-rules-collector.js';
|
|
11
|
+
import { SyncRulesCollector } from './sync-rules/sync-collector.js';
|
|
12
|
+
import { ResolvedPowerSyncConfig, RunnerConfig, SyncRulesConfig } from './types.js';
|
|
15
13
|
|
|
16
14
|
export type CompoundConfigCollectorOptions = {
|
|
17
15
|
/**
|
|
@@ -28,6 +26,17 @@ export type CompoundConfigCollectorOptions = {
|
|
|
28
26
|
syncRulesCollectors: SyncRulesCollector[];
|
|
29
27
|
};
|
|
30
28
|
|
|
29
|
+
export type ConfigCollectedEvent = {
|
|
30
|
+
base_config: configFile.PowerSyncConfig;
|
|
31
|
+
resolved_config: ResolvedPowerSyncConfig;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type ConfigCollectorListener = {
|
|
35
|
+
configCollected?: (event: ConfigCollectedEvent) => Promise<void>;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const POWERSYNC_DEV_KID = 'powersync-dev';
|
|
39
|
+
|
|
31
40
|
const DEFAULT_COLLECTOR_OPTIONS: CompoundConfigCollectorOptions = {
|
|
32
41
|
configCollectors: [new Base64ConfigCollector(), new FileSystemConfigCollector(), new FallbackConfigCollector()],
|
|
33
42
|
syncRulesCollectors: [
|
|
@@ -43,24 +52,14 @@ export class CompoundConfigCollector {
|
|
|
43
52
|
/**
|
|
44
53
|
* Collects and resolves base config
|
|
45
54
|
*/
|
|
46
|
-
async collectConfig(
|
|
47
|
-
const baseConfig = await this.collectBaseConfig(
|
|
55
|
+
async collectConfig(runnerConfig: RunnerConfig = {}): Promise<ResolvedPowerSyncConfig> {
|
|
56
|
+
const baseConfig = await this.collectBaseConfig(runnerConfig);
|
|
48
57
|
|
|
49
|
-
const
|
|
50
|
-
if (
|
|
51
|
-
throw new Error('Only a single replication
|
|
58
|
+
const dataSources = baseConfig.replication?.connections ?? [];
|
|
59
|
+
if (dataSources.length > 1) {
|
|
60
|
+
throw new Error('Only a single replication data source is supported currently');
|
|
52
61
|
}
|
|
53
62
|
|
|
54
|
-
const mapped = connections.map((c) => {
|
|
55
|
-
const conf: ResolvedConnection = {
|
|
56
|
-
type: 'postgresql' as const,
|
|
57
|
-
...normalizeConnection(c),
|
|
58
|
-
debug_api: c.debug_api ?? false
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
return conf;
|
|
62
|
-
});
|
|
63
|
-
|
|
64
63
|
const collectors = new auth.CompoundKeyCollector();
|
|
65
64
|
const keyStore = new auth.KeyStore(collectors);
|
|
66
65
|
|
|
@@ -69,10 +68,6 @@ export class CompoundConfigCollector {
|
|
|
69
68
|
|
|
70
69
|
collectors.add(staticCollector);
|
|
71
70
|
|
|
72
|
-
if (baseConfig.client_auth?.supabase && mapped.length > 0) {
|
|
73
|
-
collectors.add(new auth.CachedKeyCollector(new auth.SupabaseKeyCollector(mapped[0])));
|
|
74
|
-
}
|
|
75
|
-
|
|
76
71
|
let jwks_uris = baseConfig.client_auth?.jwks_uri ?? [];
|
|
77
72
|
if (typeof jwks_uris == 'string') {
|
|
78
73
|
jwks_uris = [jwks_uris];
|
|
@@ -93,12 +88,13 @@ export class CompoundConfigCollector {
|
|
|
93
88
|
devKey = await auth.KeySpec.importKey(baseDevKey);
|
|
94
89
|
}
|
|
95
90
|
|
|
96
|
-
const sync_rules = await this.collectSyncRules(baseConfig,
|
|
91
|
+
const sync_rules = await this.collectSyncRules(baseConfig, runnerConfig);
|
|
97
92
|
|
|
98
93
|
let jwt_audiences: string[] = baseConfig.client_auth?.audience ?? [];
|
|
99
94
|
|
|
100
95
|
let config: ResolvedPowerSyncConfig = {
|
|
101
|
-
|
|
96
|
+
base_config: baseConfig,
|
|
97
|
+
connections: baseConfig.replication?.connections || [],
|
|
102
98
|
storage: baseConfig.storage,
|
|
103
99
|
client_keystore: keyStore,
|
|
104
100
|
// Dev tokens only use the static keys, no external key sources
|
|
@@ -124,8 +120,12 @@ export class CompoundConfigCollector {
|
|
|
124
120
|
internal_service_endpoint:
|
|
125
121
|
baseConfig.telemetry?.internal_service_endpoint ?? 'https://pulse.journeyapps.com/v1/metrics'
|
|
126
122
|
},
|
|
127
|
-
|
|
123
|
+
// TODO maybe move this out of the connection or something
|
|
124
|
+
// slot_name_prefix: connections[0]?.slot_name_prefix ?? 'powersync_'
|
|
125
|
+
slot_name_prefix: 'powersync_',
|
|
126
|
+
parameters: baseConfig.parameters ?? {}
|
|
128
127
|
};
|
|
128
|
+
|
|
129
129
|
return config;
|
|
130
130
|
}
|
|
131
131
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SyncRulesConfig } from '../types.js';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
|
|
4
|
+
export interface SyncRulesProvider {
|
|
5
|
+
get(): Promise<string | undefined>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class ConfigurationFileSyncRulesProvider implements SyncRulesProvider {
|
|
9
|
+
constructor(private config: SyncRulesConfig) {}
|
|
10
|
+
|
|
11
|
+
async get(): Promise<string | undefined> {
|
|
12
|
+
if (this.config.content) {
|
|
13
|
+
return this.config.content;
|
|
14
|
+
} else if (this.config.path) {
|
|
15
|
+
return await fs.readFile(this.config.path, 'utf-8');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/util/config/types.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { configFile } from '@powersync/service-types';
|
|
2
|
+
import { PowerSyncConfig } from '@powersync/service-types/src/config/PowerSyncConfig.js';
|
|
3
|
+
import { CompoundKeyCollector } from '../../auth/CompoundKeyCollector.js';
|
|
2
4
|
import { KeySpec } from '../../auth/KeySpec.js';
|
|
3
5
|
import { KeyStore } from '../../auth/KeyStore.js';
|
|
4
6
|
|
|
@@ -20,8 +22,6 @@ export type MigrationContext = {
|
|
|
20
22
|
|
|
21
23
|
export type Runner = (config: RunnerConfig) => Promise<void>;
|
|
22
24
|
|
|
23
|
-
export type ResolvedConnection = configFile.PostgresConnection & NormalizedPostgresConnection;
|
|
24
|
-
|
|
25
25
|
export type SyncRulesConfig = {
|
|
26
26
|
present: boolean;
|
|
27
27
|
content?: string;
|
|
@@ -29,7 +29,8 @@ export type SyncRulesConfig = {
|
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
export type ResolvedPowerSyncConfig = {
|
|
32
|
-
|
|
32
|
+
base_config: PowerSyncConfig;
|
|
33
|
+
connections?: configFile.DataSourceConfig[];
|
|
33
34
|
storage: configFile.StorageConfig;
|
|
34
35
|
dev: {
|
|
35
36
|
demo_auth: boolean;
|
|
@@ -41,7 +42,7 @@ export type ResolvedPowerSyncConfig = {
|
|
|
41
42
|
*/
|
|
42
43
|
dev_key?: KeySpec;
|
|
43
44
|
};
|
|
44
|
-
client_keystore: KeyStore
|
|
45
|
+
client_keystore: KeyStore<CompoundKeyCollector>;
|
|
45
46
|
/**
|
|
46
47
|
* Keystore for development tokens.
|
|
47
48
|
*/
|
|
@@ -63,4 +64,5 @@ export type ResolvedPowerSyncConfig = {
|
|
|
63
64
|
|
|
64
65
|
/** Prefix for postgres replication slot names. May eventually be connection-specific. */
|
|
65
66
|
slot_name_prefix: string;
|
|
67
|
+
parameters: Record<string, number | string | boolean | null>;
|
|
66
68
|
};
|
package/src/util/config.ts
CHANGED
|
@@ -1,31 +1,14 @@
|
|
|
1
1
|
import * as fs from 'fs/promises';
|
|
2
|
-
import { baseUri } from '@powersync/service-types';
|
|
3
2
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { container } from '@powersync/lib-services-framework';
|
|
4
|
+
import { ResolvedPowerSyncConfig, RunnerConfig } from './config/types.js';
|
|
5
|
+
import { CompoundConfigCollector } from './util-index.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Loads the resolved config using the registered config collector
|
|
9
9
|
*/
|
|
10
|
-
export function
|
|
11
|
-
|
|
12
|
-
throw new Error('Not supported');
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const uri = new URL(baseUri(options));
|
|
16
|
-
uri.username = options.username;
|
|
17
|
-
uri.password = options.password;
|
|
18
|
-
if (options.sslmode != 'disable') {
|
|
19
|
-
// verify-full is tricky to actually use on a client, since they won't have the cert
|
|
20
|
-
// Just use "require" by default
|
|
21
|
-
// uri.searchParams.set('sslmode', options.sslmode);
|
|
22
|
-
uri.searchParams.set('sslmode', 'require');
|
|
23
|
-
}
|
|
24
|
-
return uri.toString();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function loadConfig(runnerConfig: RunnerConfig = {}) {
|
|
28
|
-
const collector = new CompoundConfigCollector();
|
|
10
|
+
export async function loadConfig(runnerConfig: RunnerConfig) {
|
|
11
|
+
const collector = container.getImplementation(CompoundConfigCollector);
|
|
29
12
|
return collector.collectConfig(runnerConfig);
|
|
30
13
|
}
|
|
31
14
|
|
package/src/util/util-index.ts
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
export * from './alerting.js';
|
|
2
2
|
export * from './env.js';
|
|
3
3
|
export * from './memory-tracking.js';
|
|
4
|
-
export * from './migration_lib.js';
|
|
5
4
|
export * from './Mutex.js';
|
|
6
|
-
export * from './PgManager.js';
|
|
7
|
-
export * from './pgwire_utils.js';
|
|
8
|
-
export * from './populate_test_data.js';
|
|
9
5
|
export * from './protocol-types.js';
|
|
10
6
|
export * from './secs.js';
|
|
11
7
|
export * from './utils.js';
|
|
12
8
|
|
|
13
9
|
export * from './config.js';
|
|
14
|
-
export * from './config/types.js';
|
|
15
10
|
export * from './config/compound-config-collector.js';
|
|
11
|
+
export * from './config/types.js';
|
|
16
12
|
|
|
17
13
|
export * from './config/collectors/config-collector.js';
|
|
18
14
|
export * from './config/collectors/impl/base64-config-collector.js';
|
|
19
15
|
export * from './config/collectors/impl/fallback-config-collector.js';
|
|
20
16
|
export * from './config/collectors/impl/filesystem-config-collector.js';
|
|
21
17
|
|
|
22
|
-
export * from './config/sync-rules/sync-collector.js';
|
|
23
18
|
export * from './config/sync-rules/impl/base64-sync-rules-collector.js';
|
|
24
19
|
export * from './config/sync-rules/impl/filesystem-sync-rules-collector.js';
|
|
25
20
|
export * from './config/sync-rules/impl/inline-sync-rules-collector.js';
|
|
21
|
+
export * from './config/sync-rules/sync-collector.js';
|
|
22
|
+
export * from './config/sync-rules/sync-rules-provider.js';
|