@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
package/dist/util/utils.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import * as bson from 'bson';
|
|
1
2
|
import crypto from 'crypto';
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import * as uuid from 'uuid';
|
|
4
|
+
export const ID_NAMESPACE = 'a396dd91-09fc-4017-a28d-3df722f651e9';
|
|
5
|
+
export function escapeIdentifier(identifier) {
|
|
6
|
+
return `"${identifier.replace(/"/g, '""').replace(/\./g, '"."')}"`;
|
|
7
|
+
}
|
|
5
8
|
export function hashData(type, id, data) {
|
|
6
9
|
const hash = crypto.createHash('sha256');
|
|
7
10
|
hash.update(`put.${type}.${id}.${data}`);
|
|
@@ -70,31 +73,39 @@ export function addBucketChecksums(a, b) {
|
|
|
70
73
|
};
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
76
|
+
function getRawReplicaIdentity(tuple, columns) {
|
|
77
|
+
let result = {};
|
|
78
|
+
for (let column of columns) {
|
|
79
|
+
const name = column.name;
|
|
80
|
+
result[name] = tuple[name];
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
export function getUuidReplicaIdentityBson(tuple, columns) {
|
|
85
|
+
if (columns.length == 0) {
|
|
86
|
+
// REPLICA IDENTITY NOTHING - generate random id
|
|
87
|
+
return new bson.UUID(uuid.v4());
|
|
88
|
+
}
|
|
89
|
+
const rawIdentity = getRawReplicaIdentity(tuple, columns);
|
|
90
|
+
return uuidForRowBson(rawIdentity);
|
|
91
|
+
}
|
|
92
|
+
export function uuidForRowBson(row) {
|
|
93
|
+
// Important: This must not change, since it will affect how ids are generated.
|
|
94
|
+
// Use BSON so that it's a well-defined format without encoding ambiguities.
|
|
95
|
+
const repr = bson.serialize(row);
|
|
96
|
+
const buffer = Buffer.alloc(16);
|
|
97
|
+
return new bson.UUID(uuid.v5(repr, ID_NAMESPACE, buffer));
|
|
98
|
+
}
|
|
99
|
+
export function hasToastedValues(row) {
|
|
100
|
+
for (let key in row) {
|
|
101
|
+
if (typeof row[key] == 'undefined') {
|
|
102
|
+
return true;
|
|
88
103
|
}
|
|
89
|
-
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
90
104
|
}
|
|
91
|
-
|
|
105
|
+
return false;
|
|
92
106
|
}
|
|
93
|
-
export
|
|
94
|
-
|
|
95
|
-
const id = await bucketStorage.createWriteCheckpoint(user_id, { '1': lsn });
|
|
96
|
-
logger.info(`Write checkpoint 2: ${JSON.stringify({ lsn, id: String(id) })}`);
|
|
97
|
-
return id;
|
|
107
|
+
export function isCompleteRow(row) {
|
|
108
|
+
return !hasToastedValues(row);
|
|
98
109
|
}
|
|
99
110
|
export function checkpointUserId(user_id, client_id) {
|
|
100
111
|
if (user_id == null) {
|
package/dist/util/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/util/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/util/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
|
-
"version": "0.
|
|
8
|
+
"version": "0.10.0",
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"license": "FSL-1.1-Apache-2.0",
|
|
11
11
|
"type": "module",
|
|
@@ -28,32 +28,28 @@
|
|
|
28
28
|
"lru-cache": "^10.2.2",
|
|
29
29
|
"mongodb": "^6.7.0",
|
|
30
30
|
"node-fetch": "^3.3.2",
|
|
31
|
-
"pgwire": "github:kagis/pgwire#f1cb95f9a0f42a612bb5a6b67bb2eb793fc5fc87",
|
|
32
31
|
"ts-codec": "^1.2.2",
|
|
32
|
+
"uri-js": "^4.4.1",
|
|
33
33
|
"uuid": "^9.0.1",
|
|
34
34
|
"winston": "^3.13.0",
|
|
35
35
|
"yaml": "^2.3.2",
|
|
36
|
-
"@powersync/lib-services-framework": "0.
|
|
36
|
+
"@powersync/lib-services-framework": "0.2.0",
|
|
37
37
|
"@powersync/service-jsonbig": "0.17.10",
|
|
38
|
-
"@powersync/service-
|
|
39
|
-
"@powersync/service-
|
|
40
|
-
"@powersync/service-
|
|
41
|
-
"@powersync/service-types": "0.2.0"
|
|
38
|
+
"@powersync/service-rsocket-router": "0.0.14",
|
|
39
|
+
"@powersync/service-sync-rules": "0.21.0",
|
|
40
|
+
"@powersync/service-types": "0.4.0"
|
|
42
41
|
},
|
|
43
42
|
"devDependencies": {
|
|
44
43
|
"@types/async": "^3.2.24",
|
|
45
44
|
"@types/lodash": "^4.17.5",
|
|
46
45
|
"@types/uuid": "^9.0.4",
|
|
47
46
|
"fastify": "4.23.2",
|
|
48
|
-
"fastify-plugin": "^4.5.1"
|
|
49
|
-
"typescript": "^5.2.2",
|
|
50
|
-
"vite-tsconfig-paths": "^4.3.2",
|
|
51
|
-
"vitest": "^0.34.6"
|
|
47
|
+
"fastify-plugin": "^4.5.1"
|
|
52
48
|
},
|
|
53
49
|
"scripts": {
|
|
54
50
|
"build": "tsc -b",
|
|
55
51
|
"build:tests": "tsc -b test/tsconfig.json",
|
|
56
|
-
"test": "vitest
|
|
52
|
+
"test": "vitest",
|
|
57
53
|
"clean": "rm -rf ./dist && tsc -b --clean"
|
|
58
54
|
}
|
|
59
55
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { SqlSyncRules, TablePattern } from '@powersync/service-sync-rules';
|
|
2
|
+
import * as types from '@powersync/service-types';
|
|
3
|
+
import { ParseSyncRulesOptions, SyncRulesBucketStorage } from '../storage/BucketStorage.js';
|
|
4
|
+
|
|
5
|
+
export interface PatternResult {
|
|
6
|
+
schema: string;
|
|
7
|
+
pattern: string;
|
|
8
|
+
wildcard: boolean;
|
|
9
|
+
tables?: types.TableInfo[];
|
|
10
|
+
table?: types.TableInfo;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ReplicationLagOptions {
|
|
14
|
+
bucketStorage: SyncRulesBucketStorage;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Describes all the methods currently required to service the sync API endpoints.
|
|
19
|
+
*/
|
|
20
|
+
export interface RouteAPI {
|
|
21
|
+
/**
|
|
22
|
+
* @returns basic identification of the connection
|
|
23
|
+
*/
|
|
24
|
+
getSourceConfig(): Promise<types.configFile.ResolvedDataSourceConfig>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Checks the current connection status of the data source.
|
|
28
|
+
* This is usually some test query to verify the source can be reached.
|
|
29
|
+
*/
|
|
30
|
+
getConnectionStatus(): Promise<types.ConnectionStatusV2>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Generates replication table information from a given pattern of tables.
|
|
34
|
+
*
|
|
35
|
+
* @param tablePatterns A set of table patterns which typically come from
|
|
36
|
+
* the tables listed in sync rules definitions.
|
|
37
|
+
*
|
|
38
|
+
* @param sqlSyncRules
|
|
39
|
+
* @returns A result of all the tables and columns which should be replicated
|
|
40
|
+
* based off the input patterns. Certain tests are executed on the
|
|
41
|
+
* tables to ensure syncing should function according to the input
|
|
42
|
+
* pattern. Debug errors and warnings are reported per table.
|
|
43
|
+
*/
|
|
44
|
+
getDebugTablesInfo(tablePatterns: TablePattern[], sqlSyncRules: SqlSyncRules): Promise<PatternResult[]>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @returns The replication lag: that is the amount of data which has not been
|
|
48
|
+
* replicated yet, in bytes.
|
|
49
|
+
*/
|
|
50
|
+
getReplicationLag(options: ReplicationLagOptions): Promise<number | undefined>;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get the current LSN or equivalent replication HEAD position identifier
|
|
54
|
+
*/
|
|
55
|
+
getReplicationHead(): Promise<string>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @returns The schema for tables inside the connected database. This is typically
|
|
59
|
+
* used to validate sync rules.
|
|
60
|
+
*/
|
|
61
|
+
getConnectionSchema(): Promise<types.DatabaseSchema[]>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Executes a query and return the result from the data source. This is currently used in the
|
|
65
|
+
* admin API which is exposed in Collide.
|
|
66
|
+
*/
|
|
67
|
+
executeQuery(query: string, params: any[]): Promise<types.internal_routes.ExecuteSqlResponse>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Close any resources that need graceful termination.
|
|
71
|
+
*/
|
|
72
|
+
shutdown(): Promise<void>;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get the default schema (or database) when only a table name is specified in sync rules.
|
|
76
|
+
*/
|
|
77
|
+
getParseSyncRulesOptions(): ParseSyncRulesOptions;
|
|
78
|
+
}
|
package/src/api/api-index.ts
CHANGED
package/src/api/diagnostics.ts
CHANGED
|
@@ -1,51 +1,9 @@
|
|
|
1
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
1
2
|
import { DEFAULT_TAG, SourceTableInterface, SqlSyncRules } from '@powersync/service-sync-rules';
|
|
2
|
-
import {
|
|
3
|
-
import { ConnectionStatus, SyncRulesStatus, TableInfo, baseUri } from '@powersync/service-types';
|
|
3
|
+
import { SyncRulesStatus, TableInfo } from '@powersync/service-types';
|
|
4
4
|
|
|
5
|
-
import * as replication from '../replication/replication-index.js';
|
|
6
5
|
import * as storage from '../storage/storage-index.js';
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
import { CorePowerSyncSystem } from '../system/CorePowerSyncSystem.js';
|
|
10
|
-
import { logger } from '@powersync/lib-services-framework';
|
|
11
|
-
|
|
12
|
-
export async function getConnectionStatus(system: CorePowerSyncSystem): Promise<ConnectionStatus | null> {
|
|
13
|
-
if (system.pgwire_pool == null) {
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const pool = system.requirePgPool();
|
|
18
|
-
|
|
19
|
-
const base = {
|
|
20
|
-
id: system.config.connection!.id,
|
|
21
|
-
postgres_uri: baseUri(system.config.connection!)
|
|
22
|
-
};
|
|
23
|
-
try {
|
|
24
|
-
await util.retriedQuery(pool, `SELECT 'PowerSync connection test'`);
|
|
25
|
-
} catch (e) {
|
|
26
|
-
return {
|
|
27
|
-
...base,
|
|
28
|
-
connected: false,
|
|
29
|
-
errors: [{ level: 'fatal', message: e.message }]
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
try {
|
|
34
|
-
await replication.checkSourceConfiguration(pool);
|
|
35
|
-
} catch (e) {
|
|
36
|
-
return {
|
|
37
|
-
...base,
|
|
38
|
-
connected: true,
|
|
39
|
-
errors: [{ level: 'fatal', message: e.message }]
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
...base,
|
|
45
|
-
connected: true,
|
|
46
|
-
errors: []
|
|
47
|
-
};
|
|
48
|
-
}
|
|
6
|
+
import { RouteAPI } from './RouteAPI.js';
|
|
49
7
|
|
|
50
8
|
export interface DiagnosticsOptions {
|
|
51
9
|
/**
|
|
@@ -66,9 +24,12 @@ export interface DiagnosticsOptions {
|
|
|
66
24
|
check_connection: boolean;
|
|
67
25
|
}
|
|
68
26
|
|
|
27
|
+
export const DEFAULT_DATASOURCE_ID = 'default';
|
|
28
|
+
|
|
69
29
|
export async function getSyncRulesStatus(
|
|
30
|
+
bucketStorage: storage.BucketStorageFactory,
|
|
31
|
+
apiHandler: RouteAPI,
|
|
70
32
|
sync_rules: storage.PersistedSyncRulesContent | null,
|
|
71
|
-
system: CorePowerSyncSystem,
|
|
72
33
|
options: DiagnosticsOptions
|
|
73
34
|
): Promise<SyncRulesStatus | undefined> {
|
|
74
35
|
if (sync_rules == null) {
|
|
@@ -82,7 +43,7 @@ export async function getSyncRulesStatus(
|
|
|
82
43
|
let rules: SqlSyncRules;
|
|
83
44
|
let persisted: storage.PersistedSyncRules;
|
|
84
45
|
try {
|
|
85
|
-
persisted = sync_rules.parsed();
|
|
46
|
+
persisted = sync_rules.parsed(apiHandler.getParseSyncRulesOptions());
|
|
86
47
|
rules = persisted.sync_rules;
|
|
87
48
|
} catch (e) {
|
|
88
49
|
return {
|
|
@@ -92,21 +53,19 @@ export async function getSyncRulesStatus(
|
|
|
92
53
|
};
|
|
93
54
|
}
|
|
94
55
|
|
|
95
|
-
const
|
|
56
|
+
const sourceConfig = await apiHandler.getSourceConfig();
|
|
57
|
+
// This method can run under some situations if no connection is configured yet.
|
|
58
|
+
// It will return a default tag in such a case. This default tag is not module specific.
|
|
59
|
+
const tag = sourceConfig.tag ?? DEFAULT_TAG;
|
|
60
|
+
using systemStorage = live_status ? bucketStorage.getInstance(sync_rules) : undefined;
|
|
96
61
|
const status = await systemStorage?.getStatus();
|
|
97
62
|
let replication_lag_bytes: number | undefined = undefined;
|
|
98
63
|
|
|
99
64
|
let tables_flat: TableInfo[] = [];
|
|
100
65
|
|
|
101
66
|
if (check_connection) {
|
|
102
|
-
const pool = system.requirePgPool();
|
|
103
|
-
|
|
104
67
|
const source_table_patterns = rules.getSourceTables();
|
|
105
|
-
const
|
|
106
|
-
db: pool,
|
|
107
|
-
sync_rules: rules
|
|
108
|
-
});
|
|
109
|
-
const resolved_tables = await wc.getDebugTablesInfo(source_table_patterns);
|
|
68
|
+
const resolved_tables = await apiHandler.getDebugTablesInfo(source_table_patterns, rules);
|
|
110
69
|
tables_flat = resolved_tables.flatMap((info) => {
|
|
111
70
|
if (info.table) {
|
|
112
71
|
return [info.table];
|
|
@@ -119,19 +78,9 @@ export async function getSyncRulesStatus(
|
|
|
119
78
|
|
|
120
79
|
if (systemStorage) {
|
|
121
80
|
try {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
slot_name,
|
|
125
|
-
confirmed_flush_lsn,
|
|
126
|
-
pg_current_wal_lsn(),
|
|
127
|
-
(pg_current_wal_lsn() - confirmed_flush_lsn) AS lsn_distance
|
|
128
|
-
FROM pg_replication_slots WHERE slot_name = $1 LIMIT 1;`,
|
|
129
|
-
params: [{ type: 'varchar', value: systemStorage!.slot_name }]
|
|
81
|
+
replication_lag_bytes = await apiHandler.getReplicationLag({
|
|
82
|
+
bucketStorage: systemStorage
|
|
130
83
|
});
|
|
131
|
-
const [row] = pgwireRows(results);
|
|
132
|
-
if (row) {
|
|
133
|
-
replication_lag_bytes = Number(row.lsn_distance);
|
|
134
|
-
}
|
|
135
84
|
} catch (e) {
|
|
136
85
|
// Ignore
|
|
137
86
|
logger.warn(`Unable to get replication lag`, e);
|
|
@@ -139,7 +88,6 @@ export async function getSyncRulesStatus(
|
|
|
139
88
|
}
|
|
140
89
|
} else {
|
|
141
90
|
const source_table_patterns = rules.getSourceTables();
|
|
142
|
-
const tag = system.config.connection!.tag ?? DEFAULT_TAG;
|
|
143
91
|
|
|
144
92
|
tables_flat = source_table_patterns.map((pattern): TableInfo => {
|
|
145
93
|
if (pattern.isWildcard) {
|
|
@@ -190,8 +138,8 @@ export async function getSyncRulesStatus(
|
|
|
190
138
|
content: include_content ? sync_rules.sync_rules_content : undefined,
|
|
191
139
|
connections: [
|
|
192
140
|
{
|
|
193
|
-
id:
|
|
194
|
-
tag:
|
|
141
|
+
id: sourceConfig.id ?? DEFAULT_DATASOURCE_ID,
|
|
142
|
+
tag: tag,
|
|
195
143
|
slot_name: sync_rules.slot_name,
|
|
196
144
|
initial_replication_done: status?.snapshot_done ?? false,
|
|
197
145
|
// TODO: Rename?
|
package/src/api/schema.ts
CHANGED
|
@@ -1,99 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { pgwireRows } from '@powersync/service-jpgwire';
|
|
3
|
-
import { DatabaseSchema, internal_routes } from '@powersync/service-types';
|
|
1
|
+
import { internal_routes } from '@powersync/service-types';
|
|
4
2
|
|
|
5
|
-
import * as
|
|
6
|
-
import { CorePowerSyncSystem } from '../system/CorePowerSyncSystem.js';
|
|
3
|
+
import * as api from '../api/api-index.js';
|
|
7
4
|
|
|
8
|
-
export async function getConnectionsSchema(
|
|
9
|
-
if (
|
|
10
|
-
return {
|
|
5
|
+
export async function getConnectionsSchema(api: api.RouteAPI): Promise<internal_routes.GetSchemaResponse> {
|
|
6
|
+
if (!api) {
|
|
7
|
+
return {
|
|
8
|
+
connections: [],
|
|
9
|
+
defaultConnectionTag: 'default',
|
|
10
|
+
defaultSchema: ''
|
|
11
|
+
};
|
|
11
12
|
}
|
|
12
|
-
|
|
13
|
+
|
|
14
|
+
const baseConfig = await api.getSourceConfig();
|
|
15
|
+
|
|
13
16
|
return {
|
|
14
17
|
connections: [
|
|
15
18
|
{
|
|
16
|
-
|
|
17
|
-
tag:
|
|
18
|
-
|
|
19
|
+
id: baseConfig.id,
|
|
20
|
+
tag: baseConfig.tag,
|
|
21
|
+
schemas: await api.getConnectionSchema()
|
|
19
22
|
}
|
|
20
|
-
]
|
|
23
|
+
],
|
|
24
|
+
defaultConnectionTag: baseConfig.tag!,
|
|
25
|
+
defaultSchema: api.getParseSyncRulesOptions().defaultSchema
|
|
21
26
|
};
|
|
22
27
|
}
|
|
23
|
-
|
|
24
|
-
export async function getConnectionSchema(db: pgwire.PgClient): Promise<DatabaseSchema[]> {
|
|
25
|
-
// https://github.com/Borvik/vscode-postgres/blob/88ec5ed061a0c9bced6c5d4ec122d0759c3f3247/src/language/server.ts
|
|
26
|
-
const results = await util.retriedQuery(
|
|
27
|
-
db,
|
|
28
|
-
`SELECT
|
|
29
|
-
tbl.schemaname,
|
|
30
|
-
tbl.tablename,
|
|
31
|
-
tbl.quoted_name,
|
|
32
|
-
json_agg(a ORDER BY attnum) as columns
|
|
33
|
-
FROM
|
|
34
|
-
(
|
|
35
|
-
SELECT
|
|
36
|
-
n.nspname as schemaname,
|
|
37
|
-
c.relname as tablename,
|
|
38
|
-
(quote_ident(n.nspname) || '.' || quote_ident(c.relname)) as quoted_name
|
|
39
|
-
FROM
|
|
40
|
-
pg_catalog.pg_class c
|
|
41
|
-
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
|
42
|
-
WHERE
|
|
43
|
-
c.relkind = 'r'
|
|
44
|
-
AND n.nspname not in ('information_schema', 'pg_catalog', 'pg_toast')
|
|
45
|
-
AND n.nspname not like 'pg_temp_%'
|
|
46
|
-
AND n.nspname not like 'pg_toast_temp_%'
|
|
47
|
-
AND c.relnatts > 0
|
|
48
|
-
AND has_schema_privilege(n.oid, 'USAGE') = true
|
|
49
|
-
AND has_table_privilege(quote_ident(n.nspname) || '.' || quote_ident(c.relname), 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') = true
|
|
50
|
-
) as tbl
|
|
51
|
-
LEFT JOIN (
|
|
52
|
-
SELECT
|
|
53
|
-
attrelid,
|
|
54
|
-
attname,
|
|
55
|
-
format_type(atttypid, atttypmod) as data_type,
|
|
56
|
-
(SELECT typname FROM pg_catalog.pg_type WHERE oid = atttypid) as pg_type,
|
|
57
|
-
attnum,
|
|
58
|
-
attisdropped
|
|
59
|
-
FROM
|
|
60
|
-
pg_attribute
|
|
61
|
-
) as a ON (
|
|
62
|
-
a.attrelid = tbl.quoted_name::regclass
|
|
63
|
-
AND a.attnum > 0
|
|
64
|
-
AND NOT a.attisdropped
|
|
65
|
-
AND has_column_privilege(tbl.quoted_name, a.attname, 'SELECT, INSERT, UPDATE, REFERENCES')
|
|
66
|
-
)
|
|
67
|
-
GROUP BY schemaname, tablename, quoted_name`
|
|
68
|
-
);
|
|
69
|
-
const rows = pgwireRows(results);
|
|
70
|
-
|
|
71
|
-
let schemas: Record<string, any> = {};
|
|
72
|
-
|
|
73
|
-
for (let row of rows) {
|
|
74
|
-
const schema = (schemas[row.schemaname] ??= {
|
|
75
|
-
name: row.schemaname,
|
|
76
|
-
tables: []
|
|
77
|
-
});
|
|
78
|
-
const table = {
|
|
79
|
-
name: row.tablename,
|
|
80
|
-
columns: [] as any[]
|
|
81
|
-
};
|
|
82
|
-
schema.tables.push(table);
|
|
83
|
-
|
|
84
|
-
const columnInfo = JSON.parse(row.columns);
|
|
85
|
-
for (let column of columnInfo) {
|
|
86
|
-
let pg_type = column.pg_type as string;
|
|
87
|
-
if (pg_type.startsWith('_')) {
|
|
88
|
-
pg_type = `${pg_type.substring(1)}[]`;
|
|
89
|
-
}
|
|
90
|
-
table.columns.push({
|
|
91
|
-
name: column.attname,
|
|
92
|
-
type: column.data_type,
|
|
93
|
-
pg_type: pg_type
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return Object.values(schemas);
|
|
99
|
-
}
|
package/src/auth/KeyStore.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
1
2
|
import * as jose from 'jose';
|
|
2
3
|
import secs from '../util/secs.js';
|
|
3
|
-
import { KeyOptions, KeySpec, SUPPORTED_ALGORITHMS } from './KeySpec.js';
|
|
4
|
-
import { KeyCollector } from './KeyCollector.js';
|
|
5
4
|
import { JwtPayload } from './JwtPayload.js';
|
|
6
|
-
import {
|
|
5
|
+
import { KeyCollector } from './KeyCollector.js';
|
|
6
|
+
import { KeyOptions, KeySpec, SUPPORTED_ALGORITHMS } from './KeySpec.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* KeyStore to get keys and verify tokens.
|
|
@@ -32,10 +32,13 @@ import { logger } from '@powersync/lib-services-framework';
|
|
|
32
32
|
* If we have a matching kid, we can generally get a detailed error (e.g. signature verification failed, invalid algorithm, etc).
|
|
33
33
|
* If we don't have a matching kid, we'll generally just get an error "Could not find an appropriate key...".
|
|
34
34
|
*/
|
|
35
|
-
export class KeyStore {
|
|
36
|
-
|
|
35
|
+
export class KeyStore<Collector extends KeyCollector = KeyCollector> {
|
|
36
|
+
/**
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
collector: Collector;
|
|
37
40
|
|
|
38
|
-
constructor(collector:
|
|
41
|
+
constructor(collector: Collector) {
|
|
39
42
|
this.collector = collector;
|
|
40
43
|
}
|
|
41
44
|
|
|
@@ -22,7 +22,10 @@ export type RemoteJWKSCollectorOptions = {
|
|
|
22
22
|
export class RemoteJWKSCollector implements KeyCollector {
|
|
23
23
|
private url: URL;
|
|
24
24
|
|
|
25
|
-
constructor(
|
|
25
|
+
constructor(
|
|
26
|
+
url: string,
|
|
27
|
+
protected options?: RemoteJWKSCollectorOptions
|
|
28
|
+
) {
|
|
26
29
|
try {
|
|
27
30
|
this.url = new URL(url);
|
|
28
31
|
} catch (e) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as jose from 'jose';
|
|
2
|
+
import { KeySpec, KeyOptions } from './KeySpec.js';
|
|
3
|
+
import { KeyCollector, KeyResult } from './KeyCollector.js';
|
|
4
|
+
|
|
5
|
+
const SUPABASE_KEY_OPTIONS: KeyOptions = {
|
|
6
|
+
requiresAudience: ['authenticated'],
|
|
7
|
+
maxLifetimeSeconds: 86400 * 7 + 1200 // 1 week + 20 minutes margin
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Set of static keys for Supabase.
|
|
12
|
+
*
|
|
13
|
+
* Same as StaticKeyCollector, but with some configuration tweaks for Supabase.
|
|
14
|
+
*
|
|
15
|
+
* Similar to SupabaseKeyCollector, but using hardcoded keys instead of fetching
|
|
16
|
+
* from the database.
|
|
17
|
+
*
|
|
18
|
+
* A key can be added both with and without a kid, in case wildcard matching is desired.
|
|
19
|
+
*/
|
|
20
|
+
export class StaticSupabaseKeyCollector implements KeyCollector {
|
|
21
|
+
static async importKeys(keys: jose.JWK[]) {
|
|
22
|
+
const parsedKeys = await Promise.all(keys.map((key) => KeySpec.importKey(key, SUPABASE_KEY_OPTIONS)));
|
|
23
|
+
return new StaticSupabaseKeyCollector(parsedKeys);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
constructor(private keys: KeySpec[]) {}
|
|
27
|
+
|
|
28
|
+
async getKeys(): Promise<KeyResult> {
|
|
29
|
+
return { keys: this.keys, errors: [] };
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/auth/auth-index.ts
CHANGED
package/src/db/mongo.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as mongo from 'mongodb';
|
|
|
2
2
|
import * as timers from 'timers/promises';
|
|
3
3
|
|
|
4
4
|
import { configFile } from '@powersync/service-types';
|
|
5
|
+
import { normalizeMongoConfig } from '../storage/storage-index.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Time for new connection to timeout.
|
|
@@ -30,10 +31,11 @@ export const MONGO_OPERATION_TIMEOUT_MS = 30_000;
|
|
|
30
31
|
export const MONGO_CLEAR_OPERATION_TIMEOUT_MS = 5_000;
|
|
31
32
|
|
|
32
33
|
export function createMongoClient(config: configFile.PowerSyncConfig['storage']) {
|
|
33
|
-
|
|
34
|
+
const normalized = normalizeMongoConfig(config);
|
|
35
|
+
return new mongo.MongoClient(normalized.uri, {
|
|
34
36
|
auth: {
|
|
35
|
-
username:
|
|
36
|
-
password:
|
|
37
|
+
username: normalized.username,
|
|
38
|
+
password: normalized.password
|
|
37
39
|
},
|
|
38
40
|
// Time for connection to timeout
|
|
39
41
|
connectTimeoutMS: MONGO_CONNECT_TIMEOUT_MS,
|
package/src/entry/cli-entry.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
|
|
3
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
3
4
|
import * as utils from '../util/util-index.js';
|
|
5
|
+
import { registerCompactAction } from './commands/compact-action.js';
|
|
4
6
|
import { registerMigrationAction } from './commands/migrate-action.js';
|
|
7
|
+
import { registerStartAction } from './commands/start-action.js';
|
|
5
8
|
import { registerTearDownAction } from './commands/teardown-action.js';
|
|
6
|
-
import { registerCompactAction, registerStartAction } from './entry-index.js';
|
|
7
|
-
import { logger } from '@powersync/lib-services-framework';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Generates a Commander program which serves as the entry point
|