@powersync/service-core 0.8.8 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -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/StaticSupabaseKeyCollector.d.ts +19 -0
- package/dist/auth/StaticSupabaseKeyCollector.js +28 -0
- package/dist/auth/StaticSupabaseKeyCollector.js.map +1 -0
- package/dist/auth/auth-index.d.ts +1 -1
- package/dist/auth/auth-index.js +1 -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 +31 -23
- 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/StaticSupabaseKeyCollector.ts +31 -0
- package/src/auth/auth-index.ts +1 -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 +48 -30
- 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
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import * as pgwire from '@powersync/service-jpgwire';
|
|
2
|
-
export type MigrationFunction = (db: pgwire.PgConnection) => Promise<void>;
|
|
3
|
-
export declare class Migrations {
|
|
4
|
-
private migrations;
|
|
5
|
-
add(id: number, name: string, up: MigrationFunction): void;
|
|
6
|
-
up(db: pgwire.PgConnection): Promise<void>;
|
|
7
|
-
getCurrentMigration(db: pgwire.PgConnection): Promise<{
|
|
8
|
-
id: number;
|
|
9
|
-
}>;
|
|
10
|
-
ensureMigrationsTable(db: pgwire.PgConnection): Promise<void>;
|
|
11
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
// Very loosely based on https://github.com/porsager/postgres-shift/
|
|
2
|
-
export class Migrations {
|
|
3
|
-
constructor() {
|
|
4
|
-
this.migrations = [];
|
|
5
|
-
}
|
|
6
|
-
add(id, name, up) {
|
|
7
|
-
if (this.migrations.length > 0 && this.migrations[this.migrations.length - 1].id >= id) {
|
|
8
|
-
throw new Error('Migration ids must be strictly incrementing');
|
|
9
|
-
}
|
|
10
|
-
this.migrations.push({ id, up, name });
|
|
11
|
-
}
|
|
12
|
-
async up(db) {
|
|
13
|
-
await db.query('BEGIN');
|
|
14
|
-
try {
|
|
15
|
-
await this.ensureMigrationsTable(db);
|
|
16
|
-
const current = await this.getCurrentMigration(db);
|
|
17
|
-
let currentId = current ? current.id : 0;
|
|
18
|
-
for (let migration of this.migrations) {
|
|
19
|
-
if (migration.id <= currentId) {
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
await migration.up(db);
|
|
23
|
-
await db.query({
|
|
24
|
-
statement: `
|
|
25
|
-
insert into migrations (
|
|
26
|
-
migration_id,
|
|
27
|
-
name
|
|
28
|
-
) values (
|
|
29
|
-
$1,
|
|
30
|
-
$2
|
|
31
|
-
)
|
|
32
|
-
`,
|
|
33
|
-
params: [
|
|
34
|
-
{ type: 'int4', value: migration.id },
|
|
35
|
-
{ type: 'varchar', value: migration.name }
|
|
36
|
-
]
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
await db.query('COMMIT');
|
|
40
|
-
}
|
|
41
|
-
catch (e) {
|
|
42
|
-
await db.query('ROLLBACK');
|
|
43
|
-
throw e;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
getCurrentMigration(db) {
|
|
47
|
-
return db
|
|
48
|
-
.query(`
|
|
49
|
-
select migration_id as id from migrations
|
|
50
|
-
order by migration_id desc
|
|
51
|
-
limit 1
|
|
52
|
-
`)
|
|
53
|
-
.then((results) => ({ id: results.rows[0][0] }));
|
|
54
|
-
}
|
|
55
|
-
async ensureMigrationsTable(db) {
|
|
56
|
-
await db.query(`create table if not exists migrations (
|
|
57
|
-
migration_id serial primary key,
|
|
58
|
-
created_at timestamp with time zone not null default now(),
|
|
59
|
-
name text
|
|
60
|
-
)
|
|
61
|
-
`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
//# sourceMappingURL=migration_lib.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migration_lib.js","sourceRoot":"","sources":["../../src/util/migration_lib.ts"],"names":[],"mappings":"AAUA,oEAAoE;AACpE,MAAM,OAAO,UAAU;IAAvB;QACU,eAAU,GAAgB,EAAE,CAAC;IAkEvC,CAAC;IAhEC,GAAG,CAAC,EAAU,EAAE,IAAY,EAAE,EAAqB;QACjD,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;YACtF,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;SAChE;QACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,EAAE,CAAC,EAAuB;QAC9B,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACxB,IAAI;YACF,MAAM,IAAI,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;YACrC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC;YACnD,IAAI,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAEzC,KAAK,IAAI,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE;gBACrC,IAAI,SAAS,CAAC,EAAE,IAAI,SAAS,EAAE;oBAC7B,SAAS;iBACV;gBACD,MAAM,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBAEvB,MAAM,EAAE,CAAC,KAAK,CAAC;oBACb,SAAS,EAAE;;;;;;;;KAQhB;oBACK,MAAM,EAAE;wBACN,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE;wBACrC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE;qBAC3C;iBACF,CAAC,CAAC;aACJ;YAED,MAAM,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;SAC1B;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC3B,MAAM,CAAC,CAAC;SACT;IACH,CAAC;IAED,mBAAmB,CAAC,EAAuB;QACzC,OAAO,EAAE;aACN,KAAK,CACJ;;;;KAIH,CACE;aACA,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAW,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,qBAAqB,CAAC,EAAuB;QACjD,MAAM,EAAE,CAAC,KAAK,CAAC;;;;;KAKd,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import * as bson from 'bson';
|
|
2
|
-
import * as pgwire from '@powersync/service-jpgwire';
|
|
3
|
-
import { SqliteJsonValue, SqliteRow, ToastableSqliteRow } from '@powersync/service-sync-rules';
|
|
4
|
-
import * as replication from '../replication/replication-index.js';
|
|
5
|
-
/**
|
|
6
|
-
* pgwire message -> SQLite row.
|
|
7
|
-
* @param message
|
|
8
|
-
*/
|
|
9
|
-
export declare function constructAfterRecord(message: pgwire.PgoutputInsert | pgwire.PgoutputUpdate): SqliteRow;
|
|
10
|
-
export declare function hasToastedValues(row: ToastableSqliteRow): boolean;
|
|
11
|
-
export declare function isCompleteRow(row: ToastableSqliteRow): row is SqliteRow;
|
|
12
|
-
/**
|
|
13
|
-
* pgwire message -> SQLite row.
|
|
14
|
-
* @param message
|
|
15
|
-
*/
|
|
16
|
-
export declare function constructBeforeRecord(message: pgwire.PgoutputDelete | pgwire.PgoutputUpdate): SqliteRow | undefined;
|
|
17
|
-
export declare function getUuidReplicaIdentityString(tuple: ToastableSqliteRow, columns: replication.ReplicationColumn[]): string;
|
|
18
|
-
export declare function uuidForRow(row: SqliteRow): string;
|
|
19
|
-
export declare function getUuidReplicaIdentityBson(tuple: ToastableSqliteRow, columns: replication.ReplicationColumn[]): bson.UUID;
|
|
20
|
-
export declare function uuidForRowBson(row: SqliteRow): bson.UUID;
|
|
21
|
-
export declare function escapeIdentifier(identifier: string): string;
|
|
22
|
-
export declare function autoParameter(arg: SqliteJsonValue | boolean): pgwire.StatementParam;
|
|
23
|
-
export declare function retriedQuery(db: pgwire.PgClient, ...statements: pgwire.Statement[]): Promise<pgwire.PgResult>;
|
|
24
|
-
export declare function retriedQuery(db: pgwire.PgClient, query: string): Promise<pgwire.PgResult>;
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
// Adapted from https://github.com/kagis/pgwire/blob/0dc927f9f8990a903f238737326e53ba1c8d094f/mod.js#L2218
|
|
2
|
-
import * as bson from 'bson';
|
|
3
|
-
import * as uuid from 'uuid';
|
|
4
|
-
import * as pgwire from '@powersync/service-jpgwire';
|
|
5
|
-
import { toSyncRulesRow } from '@powersync/service-sync-rules';
|
|
6
|
-
import { logger } from '@powersync/lib-services-framework';
|
|
7
|
-
/**
|
|
8
|
-
* pgwire message -> SQLite row.
|
|
9
|
-
* @param message
|
|
10
|
-
*/
|
|
11
|
-
export function constructAfterRecord(message) {
|
|
12
|
-
const rawData = message.afterRaw;
|
|
13
|
-
const record = pgwire.decodeTuple(message.relation, rawData);
|
|
14
|
-
return toSyncRulesRow(record);
|
|
15
|
-
}
|
|
16
|
-
export function hasToastedValues(row) {
|
|
17
|
-
for (let key in row) {
|
|
18
|
-
if (typeof row[key] == 'undefined') {
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
export function isCompleteRow(row) {
|
|
25
|
-
return !hasToastedValues(row);
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* pgwire message -> SQLite row.
|
|
29
|
-
* @param message
|
|
30
|
-
*/
|
|
31
|
-
export function constructBeforeRecord(message) {
|
|
32
|
-
const rawData = message.beforeRaw;
|
|
33
|
-
if (rawData == null) {
|
|
34
|
-
return undefined;
|
|
35
|
-
}
|
|
36
|
-
const record = pgwire.decodeTuple(message.relation, rawData);
|
|
37
|
-
return toSyncRulesRow(record);
|
|
38
|
-
}
|
|
39
|
-
function getRawReplicaIdentity(tuple, columns) {
|
|
40
|
-
let result = {};
|
|
41
|
-
for (let column of columns) {
|
|
42
|
-
const name = column.name;
|
|
43
|
-
result[name] = tuple[name];
|
|
44
|
-
}
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
const ID_NAMESPACE = 'a396dd91-09fc-4017-a28d-3df722f651e9';
|
|
48
|
-
export function getUuidReplicaIdentityString(tuple, columns) {
|
|
49
|
-
const rawIdentity = getRawReplicaIdentity(tuple, columns);
|
|
50
|
-
return uuidForRow(rawIdentity);
|
|
51
|
-
}
|
|
52
|
-
export function uuidForRow(row) {
|
|
53
|
-
// Important: This must not change, since it will affect how ids are generated.
|
|
54
|
-
// Use BSON so that it's a well-defined format without encoding ambiguities.
|
|
55
|
-
const repr = bson.serialize(row);
|
|
56
|
-
return uuid.v5(repr, ID_NAMESPACE);
|
|
57
|
-
}
|
|
58
|
-
export function getUuidReplicaIdentityBson(tuple, columns) {
|
|
59
|
-
if (columns.length == 0) {
|
|
60
|
-
// REPLICA IDENTITY NOTHING - generate random id
|
|
61
|
-
return new bson.UUID(uuid.v4());
|
|
62
|
-
}
|
|
63
|
-
const rawIdentity = getRawReplicaIdentity(tuple, columns);
|
|
64
|
-
return uuidForRowBson(rawIdentity);
|
|
65
|
-
}
|
|
66
|
-
export function uuidForRowBson(row) {
|
|
67
|
-
// Important: This must not change, since it will affect how ids are generated.
|
|
68
|
-
// Use BSON so that it's a well-defined format without encoding ambiguities.
|
|
69
|
-
const repr = bson.serialize(row);
|
|
70
|
-
const buffer = Buffer.alloc(16);
|
|
71
|
-
return new bson.UUID(uuid.v5(repr, ID_NAMESPACE, buffer));
|
|
72
|
-
}
|
|
73
|
-
export function escapeIdentifier(identifier) {
|
|
74
|
-
return `"${identifier.replace(/"/g, '""').replace(/\./g, '"."')}"`;
|
|
75
|
-
}
|
|
76
|
-
export function autoParameter(arg) {
|
|
77
|
-
if (arg == null) {
|
|
78
|
-
return { type: 'varchar', value: null };
|
|
79
|
-
}
|
|
80
|
-
else if (typeof arg == 'string') {
|
|
81
|
-
return { type: 'varchar', value: arg };
|
|
82
|
-
}
|
|
83
|
-
else if (typeof arg == 'number') {
|
|
84
|
-
if (Number.isInteger(arg)) {
|
|
85
|
-
return { type: 'int8', value: arg };
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
return { type: 'float8', value: arg };
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
else if (typeof arg == 'boolean') {
|
|
92
|
-
return { type: 'bool', value: arg };
|
|
93
|
-
}
|
|
94
|
-
else if (typeof arg == 'bigint') {
|
|
95
|
-
return { type: 'int8', value: arg };
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
throw new Error(`Unsupported query parameter: ${typeof arg}`);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Retry a simple query - up to 2 attempts total.
|
|
103
|
-
*/
|
|
104
|
-
export async function retriedQuery(db, ...args) {
|
|
105
|
-
for (let tries = 2;; tries--) {
|
|
106
|
-
try {
|
|
107
|
-
return await db.query(...args);
|
|
108
|
-
}
|
|
109
|
-
catch (e) {
|
|
110
|
-
if (tries == 1) {
|
|
111
|
-
throw e;
|
|
112
|
-
}
|
|
113
|
-
logger.warn('Query error, retrying', e);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
//# sourceMappingURL=pgwire_utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pgwire_utils.js","sourceRoot":"","sources":["../../src/util/pgwire_utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { NormalizedPostgresConnection } from '@powersync/service-types';
|
|
2
|
-
export interface PopulateDataOptions {
|
|
3
|
-
connection: NormalizedPostgresConnection;
|
|
4
|
-
num_transactions: number;
|
|
5
|
-
per_transaction: number;
|
|
6
|
-
size: number;
|
|
7
|
-
}
|
|
8
|
-
export declare function populateData(options: PopulateDataOptions): Promise<number>;
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import * as crypto from 'crypto';
|
|
2
|
-
import { Worker, isMainThread, parentPort, workerData } from 'node:worker_threads';
|
|
3
|
-
import { connectPgWire } from '@powersync/service-jpgwire';
|
|
4
|
-
if (isMainThread || parentPort == null) {
|
|
5
|
-
// Not a worker - ignore
|
|
6
|
-
}
|
|
7
|
-
else {
|
|
8
|
-
try {
|
|
9
|
-
const options = workerData;
|
|
10
|
-
const result = await populateDataInner(options);
|
|
11
|
-
parentPort.postMessage(result);
|
|
12
|
-
process.exit(0);
|
|
13
|
-
}
|
|
14
|
-
catch (e) {
|
|
15
|
-
// This is a bug, not a connection issue
|
|
16
|
-
console.error(e);
|
|
17
|
-
// Only closes the Worker thread
|
|
18
|
-
process.exit(2);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
async function populateDataInner(options) {
|
|
22
|
-
// Dedicated connection so we can release the memory easily
|
|
23
|
-
const initialDb = await connectPgWire(options.connection, { type: 'standard' });
|
|
24
|
-
const largeDescription = crypto.randomBytes(options.size / 2).toString('hex');
|
|
25
|
-
let operation_count = 0;
|
|
26
|
-
for (let i = 0; i < options.num_transactions; i++) {
|
|
27
|
-
const prefix = `test${i}K`;
|
|
28
|
-
await initialDb.query({
|
|
29
|
-
statement: `INSERT INTO test_data(id, description, other) SELECT $1 || i, $2, 'foo' FROM generate_series(1, $3) i`,
|
|
30
|
-
params: [
|
|
31
|
-
{ type: 'varchar', value: prefix },
|
|
32
|
-
{ type: 'varchar', value: largeDescription },
|
|
33
|
-
{ type: 'int4', value: options.per_transaction }
|
|
34
|
-
]
|
|
35
|
-
});
|
|
36
|
-
operation_count += options.per_transaction;
|
|
37
|
-
}
|
|
38
|
-
await initialDb.end();
|
|
39
|
-
return operation_count;
|
|
40
|
-
}
|
|
41
|
-
export async function populateData(options) {
|
|
42
|
-
const WORKER_TIMEOUT = 30000;
|
|
43
|
-
const worker = new Worker(new URL('./populate_test_data.js', import.meta.url), {
|
|
44
|
-
workerData: options
|
|
45
|
-
});
|
|
46
|
-
const timeout = setTimeout(() => {
|
|
47
|
-
// Exits with code 1 below
|
|
48
|
-
worker.terminate();
|
|
49
|
-
}, WORKER_TIMEOUT);
|
|
50
|
-
try {
|
|
51
|
-
return await new Promise((resolve, reject) => {
|
|
52
|
-
worker.on('message', resolve);
|
|
53
|
-
worker.on('error', reject);
|
|
54
|
-
worker.on('exit', (code) => {
|
|
55
|
-
if (code !== 0) {
|
|
56
|
-
reject(new Error(`Populating data failed with exit code ${code}`));
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
finally {
|
|
62
|
-
clearTimeout(timeout);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
//# sourceMappingURL=populate_test_data.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"populate_test_data.js","sourceRoot":"","sources":["../../src/util/populate_test_data.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import * as jose from 'jose';
|
|
2
|
-
import * as pgwire from '@powersync/service-jpgwire';
|
|
3
|
-
import { connectPgWirePool, pgwireRows } from '@powersync/service-jpgwire';
|
|
4
|
-
import { KeyCollector } from './KeyCollector.js';
|
|
5
|
-
import { KeyOptions, KeySpec } from './KeySpec.js';
|
|
6
|
-
import { retriedQuery } from '../util/pgwire_utils.js';
|
|
7
|
-
import { ResolvedConnection } from '../util/config/types.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Fetches key from the Supabase database.
|
|
11
|
-
*
|
|
12
|
-
* Unfortunately, despite the JWTs containing a kid, we have no way to lookup that kid
|
|
13
|
-
* before receiving a valid token.
|
|
14
|
-
*/
|
|
15
|
-
export class SupabaseKeyCollector implements KeyCollector {
|
|
16
|
-
private pool: pgwire.PgClient;
|
|
17
|
-
|
|
18
|
-
private keyOptions: KeyOptions = {
|
|
19
|
-
requiresAudience: ['authenticated'],
|
|
20
|
-
maxLifetimeSeconds: 86400 * 7 + 1200 // 1 week + 20 minutes margin
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
constructor(connection: ResolvedConnection) {
|
|
24
|
-
this.pool = connectPgWirePool(connection, {
|
|
25
|
-
// To avoid overloading the source database with open connections,
|
|
26
|
-
// limit to a single connection, and close the connection shortly
|
|
27
|
-
// after using it.
|
|
28
|
-
idleTimeout: 5_000,
|
|
29
|
-
maxSize: 1
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async getKeys() {
|
|
34
|
-
let row: { jwt_secret: string };
|
|
35
|
-
try {
|
|
36
|
-
const rows = pgwireRows(
|
|
37
|
-
await retriedQuery(this.pool, `SELECT current_setting('app.settings.jwt_secret') as jwt_secret`)
|
|
38
|
-
);
|
|
39
|
-
row = rows[0] as any;
|
|
40
|
-
} catch (e) {
|
|
41
|
-
if (e.message?.includes('unrecognized configuration parameter')) {
|
|
42
|
-
throw new jose.errors.JOSEError(`Generate a new JWT secret on Supabase. Cause: ${e.message}`);
|
|
43
|
-
} else {
|
|
44
|
-
throw e;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
const secret = row?.jwt_secret as string | undefined;
|
|
48
|
-
if (secret == null) {
|
|
49
|
-
return {
|
|
50
|
-
keys: [],
|
|
51
|
-
errors: [new jose.errors.JWKSNoMatchingKey()]
|
|
52
|
-
};
|
|
53
|
-
} else {
|
|
54
|
-
const key: jose.JWK = {
|
|
55
|
-
kty: 'oct',
|
|
56
|
-
alg: 'HS256',
|
|
57
|
-
// While the secret is valid base64, the base64-encoded form is the secret value.
|
|
58
|
-
k: Buffer.from(secret, 'utf8').toString('base64url')
|
|
59
|
-
};
|
|
60
|
-
const imported = await KeySpec.importKey(key, this.keyOptions);
|
|
61
|
-
return {
|
|
62
|
-
keys: [imported],
|
|
63
|
-
errors: []
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { PgoutputRelation } from '@powersync/service-jpgwire';
|
|
2
|
-
|
|
3
|
-
export interface PgRelation {
|
|
4
|
-
readonly relationId: number;
|
|
5
|
-
readonly schema: string;
|
|
6
|
-
readonly name: string;
|
|
7
|
-
readonly replicaIdentity: ReplicationIdentity;
|
|
8
|
-
readonly replicationColumns: ReplicationColumn[];
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export type ReplicationIdentity = 'default' | 'nothing' | 'full' | 'index';
|
|
12
|
-
|
|
13
|
-
export interface ReplicationColumn {
|
|
14
|
-
readonly name: string;
|
|
15
|
-
readonly typeOid: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function getReplicaIdColumns(relation: PgoutputRelation): ReplicationColumn[] {
|
|
19
|
-
if (relation.replicaIdentity == 'nothing') {
|
|
20
|
-
return [];
|
|
21
|
-
} else {
|
|
22
|
-
return relation.columns.filter((c) => (c.flags & 0b1) != 0).map((c) => ({ name: c.name, typeOid: c.typeOid }));
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
export function getRelId(source: PgoutputRelation): number {
|
|
26
|
-
// Source types are wrong here
|
|
27
|
-
const relId = (source as any).relationOid as number;
|
|
28
|
-
if (relId == null || typeof relId != 'number') {
|
|
29
|
-
throw new Error(`No relation id!`);
|
|
30
|
-
}
|
|
31
|
-
return relId;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function getPgOutputRelation(source: PgoutputRelation): PgRelation {
|
|
35
|
-
return {
|
|
36
|
-
name: source.name,
|
|
37
|
-
schema: source.schema,
|
|
38
|
-
relationId: getRelId(source),
|
|
39
|
-
replicaIdentity: source.replicaIdentity,
|
|
40
|
-
replicationColumns: getReplicaIdColumns(source)
|
|
41
|
-
};
|
|
42
|
-
}
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import * as pgwire from '@powersync/service-jpgwire';
|
|
2
|
-
import { pgwireRows } from '@powersync/service-jpgwire';
|
|
3
|
-
import { DEFAULT_TAG, SqlSyncRules, TablePattern } from '@powersync/service-sync-rules';
|
|
4
|
-
import { ReplicationError, TableInfo } from '@powersync/service-types';
|
|
5
|
-
|
|
6
|
-
import * as storage from '../storage/storage-index.js';
|
|
7
|
-
import * as util from '../util/util-index.js';
|
|
8
|
-
|
|
9
|
-
import { ReplicaIdentityResult, getReplicationIdentityColumns } from './util.js';
|
|
10
|
-
/**
|
|
11
|
-
* Connection that _manages_ WAL, but does not do streaming.
|
|
12
|
-
*/
|
|
13
|
-
export class WalConnection {
|
|
14
|
-
db: pgwire.PgClient;
|
|
15
|
-
connectionTag = DEFAULT_TAG;
|
|
16
|
-
publication_name = 'powersync';
|
|
17
|
-
|
|
18
|
-
sync_rules: SqlSyncRules;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* db can be a PgConnection or PgPool.
|
|
22
|
-
*
|
|
23
|
-
* No transactions are used here, but it is up to the client to ensure
|
|
24
|
-
* nothing here is called in the middle of another transaction if
|
|
25
|
-
* PgConnection is used.
|
|
26
|
-
*/
|
|
27
|
-
constructor(options: { db: pgwire.PgClient; sync_rules: SqlSyncRules }) {
|
|
28
|
-
this.db = options.db;
|
|
29
|
-
this.sync_rules = options.sync_rules;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async checkSourceConfiguration() {
|
|
33
|
-
await checkSourceConfiguration(this.db);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async getDebugTableInfo(tablePattern: TablePattern, name: string, relationId: number | null): Promise<TableInfo> {
|
|
37
|
-
const schema = tablePattern.schema;
|
|
38
|
-
let id_columns_result: ReplicaIdentityResult | undefined = undefined;
|
|
39
|
-
let id_columns_error = null;
|
|
40
|
-
|
|
41
|
-
if (relationId != null) {
|
|
42
|
-
try {
|
|
43
|
-
id_columns_result = await getReplicationIdentityColumns(this.db, relationId);
|
|
44
|
-
} catch (e) {
|
|
45
|
-
id_columns_error = { level: 'fatal', message: e.message };
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const id_columns = id_columns_result?.columns ?? [];
|
|
50
|
-
|
|
51
|
-
const sourceTable = new storage.SourceTable(0, this.connectionTag, relationId ?? 0, schema, name, id_columns, true);
|
|
52
|
-
|
|
53
|
-
const syncData = this.sync_rules.tableSyncsData(sourceTable);
|
|
54
|
-
const syncParameters = this.sync_rules.tableSyncsParameters(sourceTable);
|
|
55
|
-
|
|
56
|
-
if (relationId == null) {
|
|
57
|
-
return {
|
|
58
|
-
schema: schema,
|
|
59
|
-
name: name,
|
|
60
|
-
pattern: tablePattern.isWildcard ? tablePattern.tablePattern : undefined,
|
|
61
|
-
replication_id: [],
|
|
62
|
-
data_queries: syncData,
|
|
63
|
-
parameter_queries: syncParameters,
|
|
64
|
-
// Also
|
|
65
|
-
errors: [{ level: 'warning', message: `Table ${sourceTable.qualifiedName} not found.` }]
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
if (id_columns.length == 0 && id_columns_error == null) {
|
|
69
|
-
let message = `No replication id found for ${sourceTable.qualifiedName}. Replica identity: ${id_columns_result?.replicationIdentity}.`;
|
|
70
|
-
if (id_columns_result?.replicationIdentity == 'default') {
|
|
71
|
-
message += ' Configure a primary key on the table.';
|
|
72
|
-
}
|
|
73
|
-
id_columns_error = { level: 'fatal', message };
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
let selectError = null;
|
|
77
|
-
try {
|
|
78
|
-
await util.retriedQuery(this.db, `SELECT * FROM ${sourceTable.escapedIdentifier} LIMIT 1`);
|
|
79
|
-
} catch (e) {
|
|
80
|
-
selectError = { level: 'fatal', message: e.message };
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
let replicateError = null;
|
|
84
|
-
|
|
85
|
-
const publications = await util.retriedQuery(this.db, {
|
|
86
|
-
statement: `SELECT tablename FROM pg_publication_tables WHERE pubname = $1 AND schemaname = $2 AND tablename = $3`,
|
|
87
|
-
params: [
|
|
88
|
-
{ type: 'varchar', value: this.publication_name },
|
|
89
|
-
{ type: 'varchar', value: tablePattern.schema },
|
|
90
|
-
{ type: 'varchar', value: name }
|
|
91
|
-
]
|
|
92
|
-
});
|
|
93
|
-
if (publications.rows.length == 0) {
|
|
94
|
-
replicateError = {
|
|
95
|
-
level: 'fatal',
|
|
96
|
-
message: `Table ${sourceTable.qualifiedName} is not part of publication '${this.publication_name}'. Run: \`ALTER PUBLICATION ${this.publication_name} ADD TABLE ${sourceTable.qualifiedName}\`.`
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return {
|
|
101
|
-
schema: schema,
|
|
102
|
-
name: name,
|
|
103
|
-
pattern: tablePattern.isWildcard ? tablePattern.tablePattern : undefined,
|
|
104
|
-
replication_id: id_columns.map((c) => c.name),
|
|
105
|
-
data_queries: syncData,
|
|
106
|
-
parameter_queries: syncParameters,
|
|
107
|
-
errors: [id_columns_error, selectError, replicateError].filter((error) => error != null) as ReplicationError[]
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async getDebugTablesInfo(tablePatterns: TablePattern[]): Promise<PatternResult[]> {
|
|
112
|
-
let result: PatternResult[] = [];
|
|
113
|
-
|
|
114
|
-
for (let tablePattern of tablePatterns) {
|
|
115
|
-
const schema = tablePattern.schema;
|
|
116
|
-
|
|
117
|
-
let patternResult: PatternResult = {
|
|
118
|
-
schema: schema,
|
|
119
|
-
pattern: tablePattern.tablePattern,
|
|
120
|
-
wildcard: tablePattern.isWildcard
|
|
121
|
-
};
|
|
122
|
-
result.push(patternResult);
|
|
123
|
-
|
|
124
|
-
if (tablePattern.isWildcard) {
|
|
125
|
-
patternResult.tables = [];
|
|
126
|
-
const prefix = tablePattern.tablePrefix;
|
|
127
|
-
const results = await util.retriedQuery(this.db, {
|
|
128
|
-
statement: `SELECT c.oid AS relid, c.relname AS table_name
|
|
129
|
-
FROM pg_class c
|
|
130
|
-
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
131
|
-
WHERE n.nspname = $1
|
|
132
|
-
AND c.relkind = 'r'
|
|
133
|
-
AND c.relname LIKE $2`,
|
|
134
|
-
params: [
|
|
135
|
-
{ type: 'varchar', value: schema },
|
|
136
|
-
{ type: 'varchar', value: tablePattern.tablePattern }
|
|
137
|
-
]
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
for (let row of pgwireRows(results)) {
|
|
141
|
-
const name = row.table_name as string;
|
|
142
|
-
const relationId = row.relid as number;
|
|
143
|
-
if (!name.startsWith(prefix)) {
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
const details = await this.getDebugTableInfo(tablePattern, name, relationId);
|
|
147
|
-
patternResult.tables.push(details);
|
|
148
|
-
}
|
|
149
|
-
} else {
|
|
150
|
-
const results = await util.retriedQuery(this.db, {
|
|
151
|
-
statement: `SELECT c.oid AS relid, c.relname AS table_name
|
|
152
|
-
FROM pg_class c
|
|
153
|
-
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
154
|
-
WHERE n.nspname = $1
|
|
155
|
-
AND c.relkind = 'r'
|
|
156
|
-
AND c.relname = $2`,
|
|
157
|
-
params: [
|
|
158
|
-
{ type: 'varchar', value: schema },
|
|
159
|
-
{ type: 'varchar', value: tablePattern.tablePattern }
|
|
160
|
-
]
|
|
161
|
-
});
|
|
162
|
-
if (results.rows.length == 0) {
|
|
163
|
-
// Table not found
|
|
164
|
-
const details = await this.getDebugTableInfo(tablePattern, tablePattern.name, null);
|
|
165
|
-
patternResult.table = details;
|
|
166
|
-
} else {
|
|
167
|
-
const row = pgwireRows(results)[0];
|
|
168
|
-
const name = row.table_name as string;
|
|
169
|
-
const relationId = row.relid as number;
|
|
170
|
-
patternResult.table = await this.getDebugTableInfo(tablePattern, name, relationId);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return result;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export interface PatternResult {
|
|
179
|
-
schema: string;
|
|
180
|
-
pattern: string;
|
|
181
|
-
wildcard: boolean;
|
|
182
|
-
tables?: TableInfo[];
|
|
183
|
-
table?: TableInfo;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export async function checkSourceConfiguration(db: pgwire.PgClient) {
|
|
187
|
-
// TODO: configurable
|
|
188
|
-
const publication_name = 'powersync';
|
|
189
|
-
|
|
190
|
-
// Check basic config
|
|
191
|
-
await util.retriedQuery(
|
|
192
|
-
db,
|
|
193
|
-
`DO $$
|
|
194
|
-
BEGIN
|
|
195
|
-
if current_setting('wal_level') is distinct from 'logical' then
|
|
196
|
-
raise exception 'wal_level must be set to ''logical'', your database has it set to ''%''. Please edit your config file and restart PostgreSQL.', current_setting('wal_level');
|
|
197
|
-
end if;
|
|
198
|
-
if (current_setting('max_replication_slots')::int >= 1) is not true then
|
|
199
|
-
raise exception 'Your max_replication_slots setting is too low, it must be greater than 1. Please edit your config file and restart PostgreSQL.';
|
|
200
|
-
end if;
|
|
201
|
-
if (current_setting('max_wal_senders')::int >= 1) is not true then
|
|
202
|
-
raise exception 'Your max_wal_senders setting is too low, it must be greater than 1. Please edit your config file and restart PostgreSQL.';
|
|
203
|
-
end if;
|
|
204
|
-
end;
|
|
205
|
-
$$ LANGUAGE plpgsql;`
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
// Check that publication exists
|
|
209
|
-
const rs = await util.retriedQuery(db, {
|
|
210
|
-
statement: `SELECT * FROM pg_publication WHERE pubname = $1`,
|
|
211
|
-
params: [{ type: 'varchar', value: publication_name }]
|
|
212
|
-
});
|
|
213
|
-
const row = pgwireRows(rs)[0];
|
|
214
|
-
if (row == null) {
|
|
215
|
-
throw new Error(
|
|
216
|
-
`Publication '${publication_name}' does not exist. Run: \`CREATE PUBLICATION ${publication_name} FOR ALL TABLES\`, or read the documentation for details.`
|
|
217
|
-
);
|
|
218
|
-
}
|
|
219
|
-
if (row.pubinsert == false || row.pubupdate == false || row.pubdelete == false || row.pubtruncate == false) {
|
|
220
|
-
throw new Error(
|
|
221
|
-
`Publication '${publication_name}' does not publish all changes. Create a publication using \`WITH (publish = "insert, update, delete, truncate")\` (the default).`
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
if (row.pubviaroot) {
|
|
225
|
-
throw new Error(`'${publication_name}' uses publish_via_partition_root, which is not supported.`);
|
|
226
|
-
}
|
|
227
|
-
}
|