@powersync/service-core 0.0.2
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/.probes/.gitkeep +0 -0
- package/CHANGELOG.md +13 -0
- package/LICENSE +67 -0
- package/README.md +3 -0
- package/dist/api/api-index.d.ts +2 -0
- package/dist/api/api-index.js +3 -0
- package/dist/api/api-index.js.map +1 -0
- package/dist/api/diagnostics.d.ts +21 -0
- package/dist/api/diagnostics.js +183 -0
- package/dist/api/diagnostics.js.map +1 -0
- package/dist/api/schema.d.ts +5 -0
- package/dist/api/schema.js +88 -0
- package/dist/api/schema.js.map +1 -0
- package/dist/auth/CachedKeyCollector.d.ts +46 -0
- package/dist/auth/CachedKeyCollector.js +116 -0
- package/dist/auth/CachedKeyCollector.js.map +1 -0
- package/dist/auth/CompoundKeyCollector.d.ts +8 -0
- package/dist/auth/CompoundKeyCollector.js +23 -0
- package/dist/auth/CompoundKeyCollector.js.map +1 -0
- package/dist/auth/JwtPayload.d.ts +10 -0
- package/dist/auth/JwtPayload.js +2 -0
- package/dist/auth/JwtPayload.js.map +1 -0
- package/dist/auth/KeyCollector.d.ts +24 -0
- package/dist/auth/KeyCollector.js +2 -0
- package/dist/auth/KeyCollector.js.map +1 -0
- package/dist/auth/KeySpec.d.ts +26 -0
- package/dist/auth/KeySpec.js +49 -0
- package/dist/auth/KeySpec.js.map +1 -0
- package/dist/auth/KeyStore.d.ts +39 -0
- package/dist/auth/KeyStore.js +131 -0
- package/dist/auth/KeyStore.js.map +1 -0
- package/dist/auth/LeakyBucket.d.ts +39 -0
- package/dist/auth/LeakyBucket.js +57 -0
- package/dist/auth/LeakyBucket.js.map +1 -0
- package/dist/auth/RemoteJWKSCollector.d.ts +24 -0
- package/dist/auth/RemoteJWKSCollector.js +106 -0
- package/dist/auth/RemoteJWKSCollector.js.map +1 -0
- package/dist/auth/StaticKeyCollector.d.ts +14 -0
- package/dist/auth/StaticKeyCollector.js +19 -0
- package/dist/auth/StaticKeyCollector.js.map +1 -0
- package/dist/auth/SupabaseKeyCollector.d.ts +22 -0
- package/dist/auth/SupabaseKeyCollector.js +61 -0
- package/dist/auth/SupabaseKeyCollector.js.map +1 -0
- package/dist/auth/auth-index.d.ts +10 -0
- package/dist/auth/auth-index.js +11 -0
- package/dist/auth/auth-index.js.map +1 -0
- package/dist/db/db-index.d.ts +1 -0
- package/dist/db/db-index.js +2 -0
- package/dist/db/db-index.js.map +1 -0
- package/dist/db/mongo.d.ts +29 -0
- package/dist/db/mongo.js +65 -0
- package/dist/db/mongo.js.map +1 -0
- package/dist/entry/cli-entry.d.ts +15 -0
- package/dist/entry/cli-entry.js +36 -0
- package/dist/entry/cli-entry.js.map +1 -0
- package/dist/entry/commands/config-command.d.ts +10 -0
- package/dist/entry/commands/config-command.js +21 -0
- package/dist/entry/commands/config-command.js.map +1 -0
- package/dist/entry/commands/migrate-action.d.ts +2 -0
- package/dist/entry/commands/migrate-action.js +18 -0
- package/dist/entry/commands/migrate-action.js.map +1 -0
- package/dist/entry/commands/start-action.d.ts +3 -0
- package/dist/entry/commands/start-action.js +15 -0
- package/dist/entry/commands/start-action.js.map +1 -0
- package/dist/entry/commands/teardown-action.d.ts +2 -0
- package/dist/entry/commands/teardown-action.js +17 -0
- package/dist/entry/commands/teardown-action.js.map +1 -0
- package/dist/entry/entry-index.d.ts +5 -0
- package/dist/entry/entry-index.js +6 -0
- package/dist/entry/entry-index.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/metrics/metrics.d.ts +16 -0
- package/dist/metrics/metrics.js +139 -0
- package/dist/metrics/metrics.js.map +1 -0
- package/dist/migrations/db/migrations/1684951997326-init.d.ts +3 -0
- package/dist/migrations/db/migrations/1684951997326-init.js +31 -0
- package/dist/migrations/db/migrations/1684951997326-init.js.map +1 -0
- package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.d.ts +2 -0
- package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js +5 -0
- package/dist/migrations/db/migrations/1688556755264-initial-sync-rules.js.map +1 -0
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.d.ts +3 -0
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js +54 -0
- package/dist/migrations/db/migrations/1702295701188-sync-rule-state.js.map +1 -0
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.d.ts +3 -0
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js +27 -0
- package/dist/migrations/db/migrations/1711543888062-write-checkpoint-index.js.map +1 -0
- package/dist/migrations/db/store.d.ts +3 -0
- package/dist/migrations/db/store.js +10 -0
- package/dist/migrations/db/store.js.map +1 -0
- package/dist/migrations/migrations.d.ts +10 -0
- package/dist/migrations/migrations.js +94 -0
- package/dist/migrations/migrations.js.map +1 -0
- package/dist/replication/ErrorRateLimiter.d.ts +17 -0
- package/dist/replication/ErrorRateLimiter.js +42 -0
- package/dist/replication/ErrorRateLimiter.js.map +1 -0
- package/dist/replication/PgRelation.d.ts +16 -0
- package/dist/replication/PgRelation.js +26 -0
- package/dist/replication/PgRelation.js.map +1 -0
- package/dist/replication/WalConnection.d.ts +34 -0
- package/dist/replication/WalConnection.js +190 -0
- package/dist/replication/WalConnection.js.map +1 -0
- package/dist/replication/WalStream.d.ts +58 -0
- package/dist/replication/WalStream.js +517 -0
- package/dist/replication/WalStream.js.map +1 -0
- package/dist/replication/WalStreamManager.d.ts +30 -0
- package/dist/replication/WalStreamManager.js +199 -0
- package/dist/replication/WalStreamManager.js.map +1 -0
- package/dist/replication/WalStreamRunner.d.ts +38 -0
- package/dist/replication/WalStreamRunner.js +155 -0
- package/dist/replication/WalStreamRunner.js.map +1 -0
- package/dist/replication/replication-index.d.ts +7 -0
- package/dist/replication/replication-index.js +8 -0
- package/dist/replication/replication-index.js.map +1 -0
- package/dist/replication/util.d.ts +9 -0
- package/dist/replication/util.js +62 -0
- package/dist/replication/util.js.map +1 -0
- package/dist/routes/admin.d.ts +7 -0
- package/dist/routes/admin.js +192 -0
- package/dist/routes/admin.js.map +1 -0
- package/dist/routes/auth.d.ts +58 -0
- package/dist/routes/auth.js +182 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/checkpointing.d.ts +3 -0
- package/dist/routes/checkpointing.js +30 -0
- package/dist/routes/checkpointing.js.map +1 -0
- package/dist/routes/dev.d.ts +6 -0
- package/dist/routes/dev.js +163 -0
- package/dist/routes/dev.js.map +1 -0
- package/dist/routes/route-generators.d.ts +15 -0
- package/dist/routes/route-generators.js +32 -0
- package/dist/routes/route-generators.js.map +1 -0
- package/dist/routes/router-socket.d.ts +10 -0
- package/dist/routes/router-socket.js +5 -0
- package/dist/routes/router-socket.js.map +1 -0
- package/dist/routes/router.d.ts +13 -0
- package/dist/routes/router.js +2 -0
- package/dist/routes/router.js.map +1 -0
- package/dist/routes/routes-index.d.ts +4 -0
- package/dist/routes/routes-index.js +5 -0
- package/dist/routes/routes-index.js.map +1 -0
- package/dist/routes/socket-route.d.ts +2 -0
- package/dist/routes/socket-route.js +119 -0
- package/dist/routes/socket-route.js.map +1 -0
- package/dist/routes/sync-rules.d.ts +6 -0
- package/dist/routes/sync-rules.js +182 -0
- package/dist/routes/sync-rules.js.map +1 -0
- package/dist/routes/sync-stream.d.ts +5 -0
- package/dist/routes/sync-stream.js +74 -0
- package/dist/routes/sync-stream.js.map +1 -0
- package/dist/runner/teardown.d.ts +2 -0
- package/dist/runner/teardown.js +79 -0
- package/dist/runner/teardown.js.map +1 -0
- package/dist/storage/BucketStorage.d.ts +298 -0
- package/dist/storage/BucketStorage.js +25 -0
- package/dist/storage/BucketStorage.js.map +1 -0
- package/dist/storage/MongoBucketStorage.d.ts +51 -0
- package/dist/storage/MongoBucketStorage.js +388 -0
- package/dist/storage/MongoBucketStorage.js.map +1 -0
- package/dist/storage/SourceTable.d.ts +39 -0
- package/dist/storage/SourceTable.js +50 -0
- package/dist/storage/SourceTable.js.map +1 -0
- package/dist/storage/mongo/MongoBucketBatch.d.ts +48 -0
- package/dist/storage/mongo/MongoBucketBatch.js +584 -0
- package/dist/storage/mongo/MongoBucketBatch.js.map +1 -0
- package/dist/storage/mongo/MongoIdSequence.d.ts +12 -0
- package/dist/storage/mongo/MongoIdSequence.js +21 -0
- package/dist/storage/mongo/MongoIdSequence.js.map +1 -0
- package/dist/storage/mongo/MongoPersistedSyncRules.d.ts +9 -0
- package/dist/storage/mongo/MongoPersistedSyncRules.js +9 -0
- package/dist/storage/mongo/MongoPersistedSyncRules.js.map +1 -0
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.d.ts +20 -0
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.js +26 -0
- package/dist/storage/mongo/MongoPersistedSyncRulesContent.js.map +1 -0
- package/dist/storage/mongo/MongoSyncBucketStorage.d.ts +27 -0
- package/dist/storage/mongo/MongoSyncBucketStorage.js +379 -0
- package/dist/storage/mongo/MongoSyncBucketStorage.js.map +1 -0
- package/dist/storage/mongo/MongoSyncRulesLock.d.ts +16 -0
- package/dist/storage/mongo/MongoSyncRulesLock.js +65 -0
- package/dist/storage/mongo/MongoSyncRulesLock.js.map +1 -0
- package/dist/storage/mongo/OperationBatch.d.ts +26 -0
- package/dist/storage/mongo/OperationBatch.js +101 -0
- package/dist/storage/mongo/OperationBatch.js.map +1 -0
- package/dist/storage/mongo/PersistedBatch.d.ts +42 -0
- package/dist/storage/mongo/PersistedBatch.js +200 -0
- package/dist/storage/mongo/PersistedBatch.js.map +1 -0
- package/dist/storage/mongo/db.d.ts +23 -0
- package/dist/storage/mongo/db.js +34 -0
- package/dist/storage/mongo/db.js.map +1 -0
- package/dist/storage/mongo/models.d.ts +137 -0
- package/dist/storage/mongo/models.js +27 -0
- package/dist/storage/mongo/models.js.map +1 -0
- package/dist/storage/mongo/util.d.ts +26 -0
- package/dist/storage/mongo/util.js +81 -0
- package/dist/storage/mongo/util.js.map +1 -0
- package/dist/storage/storage-index.d.ts +14 -0
- package/dist/storage/storage-index.js +15 -0
- package/dist/storage/storage-index.js.map +1 -0
- package/dist/sync/BroadcastIterable.d.ts +38 -0
- package/dist/sync/BroadcastIterable.js +153 -0
- package/dist/sync/BroadcastIterable.js.map +1 -0
- package/dist/sync/LastValueSink.d.ts +25 -0
- package/dist/sync/LastValueSink.js +84 -0
- package/dist/sync/LastValueSink.js.map +1 -0
- package/dist/sync/merge.d.ts +39 -0
- package/dist/sync/merge.js +175 -0
- package/dist/sync/merge.js.map +1 -0
- package/dist/sync/safeRace.d.ts +1 -0
- package/dist/sync/safeRace.js +91 -0
- package/dist/sync/safeRace.js.map +1 -0
- package/dist/sync/sync-index.d.ts +6 -0
- package/dist/sync/sync-index.js +7 -0
- package/dist/sync/sync-index.js.map +1 -0
- package/dist/sync/sync.d.ts +18 -0
- package/dist/sync/sync.js +248 -0
- package/dist/sync/sync.js.map +1 -0
- package/dist/sync/util.d.ts +26 -0
- package/dist/sync/util.js +73 -0
- package/dist/sync/util.js.map +1 -0
- package/dist/system/CorePowerSyncSystem.d.ts +18 -0
- package/dist/system/CorePowerSyncSystem.js +28 -0
- package/dist/system/CorePowerSyncSystem.js.map +1 -0
- package/dist/util/Mutex.d.ts +47 -0
- package/dist/util/Mutex.js +132 -0
- package/dist/util/Mutex.js.map +1 -0
- package/dist/util/PgManager.d.ts +24 -0
- package/dist/util/PgManager.js +55 -0
- package/dist/util/PgManager.js.map +1 -0
- package/dist/util/alerting.d.ts +4 -0
- package/dist/util/alerting.js +14 -0
- package/dist/util/alerting.js.map +1 -0
- package/dist/util/config/collectors/config-collector.d.ts +29 -0
- package/dist/util/config/collectors/config-collector.js +116 -0
- package/dist/util/config/collectors/config-collector.js.map +1 -0
- package/dist/util/config/collectors/impl/base64-config-collector.d.ts +6 -0
- package/dist/util/config/collectors/impl/base64-config-collector.js +15 -0
- package/dist/util/config/collectors/impl/base64-config-collector.js.map +1 -0
- package/dist/util/config/collectors/impl/fallback-config-collector.d.ts +11 -0
- package/dist/util/config/collectors/impl/fallback-config-collector.js +19 -0
- package/dist/util/config/collectors/impl/fallback-config-collector.js.map +1 -0
- package/dist/util/config/collectors/impl/filesystem-config-collector.d.ts +6 -0
- package/dist/util/config/collectors/impl/filesystem-config-collector.js +35 -0
- package/dist/util/config/collectors/impl/filesystem-config-collector.js.map +1 -0
- package/dist/util/config/compound-config-collector.d.ts +32 -0
- package/dist/util/config/compound-config-collector.js +126 -0
- package/dist/util/config/compound-config-collector.js.map +1 -0
- package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.d.ts +7 -0
- package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js +17 -0
- package/dist/util/config/sync-rules/impl/base64-sync-rules-collector.js.map +1 -0
- package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.d.ts +7 -0
- package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js +21 -0
- package/dist/util/config/sync-rules/impl/filesystem-sync-rules-collector.js.map +1 -0
- package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.d.ts +7 -0
- package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js +17 -0
- package/dist/util/config/sync-rules/impl/inline-sync-rules-collector.js.map +1 -0
- package/dist/util/config/sync-rules/sync-collector.d.ts +6 -0
- package/dist/util/config/sync-rules/sync-collector.js +3 -0
- package/dist/util/config/sync-rules/sync-collector.js.map +1 -0
- package/dist/util/config/types.d.ts +53 -0
- package/dist/util/config/types.js +7 -0
- package/dist/util/config/types.js.map +1 -0
- package/dist/util/config.d.ts +7 -0
- package/dist/util/config.js +35 -0
- package/dist/util/config.js.map +1 -0
- package/dist/util/env.d.ts +10 -0
- package/dist/util/env.js +25 -0
- package/dist/util/env.js.map +1 -0
- package/dist/util/memory-tracking.d.ts +7 -0
- package/dist/util/memory-tracking.js +58 -0
- package/dist/util/memory-tracking.js.map +1 -0
- package/dist/util/migration_lib.d.ts +11 -0
- package/dist/util/migration_lib.js +64 -0
- package/dist/util/migration_lib.js.map +1 -0
- package/dist/util/pgwire_utils.d.ts +24 -0
- package/dist/util/pgwire_utils.js +117 -0
- package/dist/util/pgwire_utils.js.map +1 -0
- package/dist/util/populate_test_data.d.ts +8 -0
- package/dist/util/populate_test_data.js +65 -0
- package/dist/util/populate_test_data.js.map +1 -0
- package/dist/util/protocol-types.d.ts +178 -0
- package/dist/util/protocol-types.js +38 -0
- package/dist/util/protocol-types.js.map +1 -0
- package/dist/util/secs.d.ts +2 -0
- package/dist/util/secs.js +49 -0
- package/dist/util/secs.js.map +1 -0
- package/dist/util/util-index.d.ts +22 -0
- package/dist/util/util-index.js +23 -0
- package/dist/util/util-index.js.map +1 -0
- package/dist/util/utils.d.ts +14 -0
- package/dist/util/utils.js +75 -0
- package/dist/util/utils.js.map +1 -0
- package/package.json +55 -0
- package/src/api/api-index.ts +2 -0
- package/src/api/diagnostics.ts +221 -0
- package/src/api/schema.ts +99 -0
- package/src/auth/CachedKeyCollector.ts +132 -0
- package/src/auth/CompoundKeyCollector.ts +33 -0
- package/src/auth/JwtPayload.ts +11 -0
- package/src/auth/KeyCollector.ts +27 -0
- package/src/auth/KeySpec.ts +67 -0
- package/src/auth/KeyStore.ts +156 -0
- package/src/auth/LeakyBucket.ts +66 -0
- package/src/auth/RemoteJWKSCollector.ts +130 -0
- package/src/auth/StaticKeyCollector.ts +21 -0
- package/src/auth/SupabaseKeyCollector.ts +67 -0
- package/src/auth/auth-index.ts +10 -0
- package/src/db/db-index.ts +1 -0
- package/src/db/mongo.ts +72 -0
- package/src/entry/cli-entry.ts +41 -0
- package/src/entry/commands/config-command.ts +36 -0
- package/src/entry/commands/migrate-action.ts +25 -0
- package/src/entry/commands/start-action.ts +24 -0
- package/src/entry/commands/teardown-action.ts +23 -0
- package/src/entry/entry-index.ts +5 -0
- package/src/index.ts +37 -0
- package/src/metrics/metrics.ts +169 -0
- package/src/migrations/db/migrations/1684951997326-init.ts +33 -0
- package/src/migrations/db/migrations/1688556755264-initial-sync-rules.ts +5 -0
- package/src/migrations/db/migrations/1702295701188-sync-rule-state.ts +99 -0
- package/src/migrations/db/migrations/1711543888062-write-checkpoint-index.ts +32 -0
- package/src/migrations/db/store.ts +11 -0
- package/src/migrations/migrations.ts +122 -0
- package/src/replication/ErrorRateLimiter.ts +49 -0
- package/src/replication/PgRelation.ts +42 -0
- package/src/replication/WalConnection.ts +227 -0
- package/src/replication/WalStream.ts +626 -0
- package/src/replication/WalStreamManager.ts +214 -0
- package/src/replication/WalStreamRunner.ts +180 -0
- package/src/replication/replication-index.ts +7 -0
- package/src/replication/util.ts +76 -0
- package/src/routes/admin.ts +229 -0
- package/src/routes/auth.ts +209 -0
- package/src/routes/checkpointing.ts +38 -0
- package/src/routes/dev.ts +194 -0
- package/src/routes/route-generators.ts +39 -0
- package/src/routes/router-socket.ts +13 -0
- package/src/routes/router.ts +17 -0
- package/src/routes/routes-index.ts +5 -0
- package/src/routes/socket-route.ts +131 -0
- package/src/routes/sync-rules.ts +210 -0
- package/src/routes/sync-stream.ts +92 -0
- package/src/runner/teardown.ts +91 -0
- package/src/storage/BucketStorage.ts +386 -0
- package/src/storage/MongoBucketStorage.ts +493 -0
- package/src/storage/SourceTable.ts +60 -0
- package/src/storage/mongo/MongoBucketBatch.ts +756 -0
- package/src/storage/mongo/MongoIdSequence.ts +24 -0
- package/src/storage/mongo/MongoPersistedSyncRules.ts +16 -0
- package/src/storage/mongo/MongoPersistedSyncRulesContent.ts +47 -0
- package/src/storage/mongo/MongoSyncBucketStorage.ts +517 -0
- package/src/storage/mongo/MongoSyncRulesLock.ts +81 -0
- package/src/storage/mongo/OperationBatch.ts +115 -0
- package/src/storage/mongo/PersistedBatch.ts +245 -0
- package/src/storage/mongo/db.ts +69 -0
- package/src/storage/mongo/models.ts +157 -0
- package/src/storage/mongo/util.ts +88 -0
- package/src/storage/storage-index.ts +15 -0
- package/src/sync/BroadcastIterable.ts +161 -0
- package/src/sync/LastValueSink.ts +100 -0
- package/src/sync/merge.ts +200 -0
- package/src/sync/safeRace.ts +99 -0
- package/src/sync/sync-index.ts +6 -0
- package/src/sync/sync.ts +312 -0
- package/src/sync/util.ts +98 -0
- package/src/system/CorePowerSyncSystem.ts +43 -0
- package/src/util/Mutex.ts +159 -0
- package/src/util/PgManager.ts +64 -0
- package/src/util/alerting.ts +17 -0
- package/src/util/config/collectors/config-collector.ts +141 -0
- package/src/util/config/collectors/impl/base64-config-collector.ts +18 -0
- package/src/util/config/collectors/impl/fallback-config-collector.ts +22 -0
- package/src/util/config/collectors/impl/filesystem-config-collector.ts +41 -0
- package/src/util/config/compound-config-collector.ts +171 -0
- package/src/util/config/sync-rules/impl/base64-sync-rules-collector.ts +21 -0
- package/src/util/config/sync-rules/impl/filesystem-sync-rules-collector.ts +26 -0
- package/src/util/config/sync-rules/impl/inline-sync-rules-collector.ts +21 -0
- package/src/util/config/sync-rules/sync-collector.ts +8 -0
- package/src/util/config/types.ts +60 -0
- package/src/util/config.ts +39 -0
- package/src/util/env.ts +28 -0
- package/src/util/memory-tracking.ts +67 -0
- package/src/util/migration_lib.ts +79 -0
- package/src/util/pgwire_utils.ts +139 -0
- package/src/util/populate_test_data.ts +78 -0
- package/src/util/protocol-types.ts +223 -0
- package/src/util/secs.ts +54 -0
- package/src/util/util-index.ts +25 -0
- package/src/util/utils.ts +102 -0
- package/test/src/__snapshots__/pg_test.test.ts.snap +256 -0
- package/test/src/__snapshots__/sync.test.ts.snap +235 -0
- package/test/src/auth.test.ts +340 -0
- package/test/src/broadcast_iterable.test.ts +156 -0
- package/test/src/data_storage.test.ts +1176 -0
- package/test/src/env.ts +8 -0
- package/test/src/large_batch.test.ts +194 -0
- package/test/src/merge_iterable.test.ts +355 -0
- package/test/src/pg_test.test.ts +432 -0
- package/test/src/schema_changes.test.ts +545 -0
- package/test/src/slow_tests.test.ts +257 -0
- package/test/src/sql_functions.test.ts +254 -0
- package/test/src/sql_operators.test.ts +132 -0
- package/test/src/sync.test.ts +293 -0
- package/test/src/sync_rules.test.ts +1051 -0
- package/test/src/util.ts +67 -0
- package/test/src/validation.test.ts +63 -0
- package/test/src/wal_stream.test.ts +310 -0
- package/test/src/wal_stream_utils.ts +147 -0
- package/test/tsconfig.json +20 -0
- package/tsconfig.json +20 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +11 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import * as t from 'ts-codec';
|
|
2
|
+
import { configFile } from '@powersync/service-types';
|
|
3
|
+
import * as micro from '@journeyapps-platform/micro';
|
|
4
|
+
import { RunnerConfig } from '../types.js';
|
|
5
|
+
import * as yaml from 'yaml';
|
|
6
|
+
|
|
7
|
+
export enum ConfigFileFormat {
|
|
8
|
+
YAML = 'yaml',
|
|
9
|
+
JSON = 'json'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Environment variables can be substituted into the YAML config
|
|
14
|
+
* when parsing if the environment variable name starts with this prefix.
|
|
15
|
+
* Attempting to substitute any other environment variable will throw an exception.
|
|
16
|
+
*
|
|
17
|
+
* Example of substitution:
|
|
18
|
+
* storage:
|
|
19
|
+
* type: mongodb
|
|
20
|
+
* uri: !env PS_MONGO_URI
|
|
21
|
+
*/
|
|
22
|
+
const YAML_ENV_PREFIX = 'PS_';
|
|
23
|
+
|
|
24
|
+
// ts-codec itself doesn't give great validation errors, so we use json schema for that
|
|
25
|
+
const configSchemaValidator = micro.schema
|
|
26
|
+
.parseJSONSchema(
|
|
27
|
+
t.generateJSONSchema(configFile.powerSyncConfig, { allowAdditional: true, parsers: [configFile.portParser] })
|
|
28
|
+
)
|
|
29
|
+
.validator();
|
|
30
|
+
|
|
31
|
+
export abstract class ConfigCollector {
|
|
32
|
+
abstract get name(): string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Collects the serialized base PowerSyncConfig.
|
|
36
|
+
* @returns null if this collector cannot provide a config
|
|
37
|
+
*/
|
|
38
|
+
abstract collectSerialized(runnerConfig: RunnerConfig): Promise<configFile.SerializedPowerSyncConfig | null>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Collects the PowerSyncConfig settings.
|
|
42
|
+
* Validates and decodes the config.
|
|
43
|
+
* @returns null if this collector cannot provide a config
|
|
44
|
+
*/
|
|
45
|
+
async collect(runner_config: RunnerConfig): Promise<configFile.PowerSyncConfig | null> {
|
|
46
|
+
const serialized = await this.collectSerialized(runner_config);
|
|
47
|
+
if (!serialized) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* After this point a serialized config has been found. Any failures to decode or validate
|
|
53
|
+
* will result in a hard stop.
|
|
54
|
+
*/
|
|
55
|
+
const decoded = this.decode(serialized);
|
|
56
|
+
this.validate(decoded);
|
|
57
|
+
return decoded;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Validates input config
|
|
62
|
+
* ts-codec itself doesn't give great validation errors, so we use json schema for that
|
|
63
|
+
*/
|
|
64
|
+
validate(config: configFile.PowerSyncConfig) {
|
|
65
|
+
const valid = configSchemaValidator.validate(config);
|
|
66
|
+
if (!valid.valid) {
|
|
67
|
+
throw new Error(`Failed to validate PowerSync config: ${valid.errors.join(', ')}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
decode(encoded: configFile.SerializedPowerSyncConfig): configFile.PowerSyncConfig {
|
|
72
|
+
try {
|
|
73
|
+
return configFile.powerSyncConfig.decode(encoded);
|
|
74
|
+
} catch (ex) {
|
|
75
|
+
throw new Error(`Failed to decode PowerSync config: ${ex}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
protected parseContent(content: string, contentType?: ConfigFileFormat) {
|
|
80
|
+
switch (contentType) {
|
|
81
|
+
case ConfigFileFormat.YAML:
|
|
82
|
+
return this.parseYaml(content);
|
|
83
|
+
case ConfigFileFormat.JSON:
|
|
84
|
+
return this.parseJSON(content);
|
|
85
|
+
default: {
|
|
86
|
+
// No content type provided, need to try both
|
|
87
|
+
try {
|
|
88
|
+
return this.parseYaml(content);
|
|
89
|
+
} catch (ex) {}
|
|
90
|
+
try {
|
|
91
|
+
return this.parseJSON(content);
|
|
92
|
+
} catch (ex) {
|
|
93
|
+
throw new Error(`Could not parse PowerSync config file content as JSON or YAML: ${ex}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
protected parseYaml(content: string) {
|
|
100
|
+
const lineCounter = new yaml.LineCounter();
|
|
101
|
+
|
|
102
|
+
const parsed = yaml.parseDocument(content, {
|
|
103
|
+
schema: 'core',
|
|
104
|
+
keepSourceTokens: true,
|
|
105
|
+
lineCounter,
|
|
106
|
+
customTags: [
|
|
107
|
+
{
|
|
108
|
+
tag: '!env',
|
|
109
|
+
resolve(envName: string, onError: (error: string) => void) {
|
|
110
|
+
if (!envName.startsWith(YAML_ENV_PREFIX)) {
|
|
111
|
+
onError(
|
|
112
|
+
`Attempting to substitute environment variable ${envName} is not allowed. Variables must start with "${YAML_ENV_PREFIX}"`
|
|
113
|
+
);
|
|
114
|
+
return envName;
|
|
115
|
+
}
|
|
116
|
+
const value = process.env[envName];
|
|
117
|
+
if (typeof value == 'undefined') {
|
|
118
|
+
onError(
|
|
119
|
+
`Attempted to substitute environment variable "${envName}" which is undefined. Set this variable on the environment.`
|
|
120
|
+
);
|
|
121
|
+
return envName;
|
|
122
|
+
}
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
if (parsed.errors.length) {
|
|
130
|
+
throw new Error(
|
|
131
|
+
`Could not parse YAML configuration file. Received errors: \n ${parsed.errors.map((e) => e.message).join('\n')}`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return parsed.toJS();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
protected parseJSON(content: string) {
|
|
139
|
+
return JSON.parse(content);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ConfigCollector } from '../config-collector.js';
|
|
2
|
+
import { RunnerConfig } from '../../types.js';
|
|
3
|
+
|
|
4
|
+
export class Base64ConfigCollector extends ConfigCollector {
|
|
5
|
+
get name(): string {
|
|
6
|
+
return 'Base64';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async collectSerialized(runnerConfig: RunnerConfig) {
|
|
10
|
+
const { config_base64 } = runnerConfig;
|
|
11
|
+
if (!config_base64) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Could be JSON or YAML at this point
|
|
16
|
+
return this.parseContent(Buffer.from(config_base64, 'base64').toString());
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { RunnerConfig } from '../../types.js';
|
|
2
|
+
import { FileSystemConfigCollector } from './filesystem-config-collector.js';
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_CONFIG_LOCATION = 'powersync.yaml';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Falls back to reading the PowerSync config file from the previous
|
|
8
|
+
* default location of `powersync.yaml`
|
|
9
|
+
*/
|
|
10
|
+
export class FallbackConfigCollector extends FileSystemConfigCollector {
|
|
11
|
+
get name(): string {
|
|
12
|
+
return 'Fallback powersync.yaml';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async collectSerialized(runnerConfig: RunnerConfig) {
|
|
16
|
+
return super.collectSerialized({
|
|
17
|
+
...runnerConfig,
|
|
18
|
+
// Use the fallback config location
|
|
19
|
+
config_path: DEFAULT_CONFIG_LOCATION
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as micro from '@journeyapps-platform/micro';
|
|
3
|
+
|
|
4
|
+
import { ConfigCollector, ConfigFileFormat } from '../config-collector.js';
|
|
5
|
+
import { RunnerConfig } from '../../types.js';
|
|
6
|
+
|
|
7
|
+
export class FileSystemConfigCollector extends ConfigCollector {
|
|
8
|
+
get name(): string {
|
|
9
|
+
return 'FileSystem';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async collectSerialized(runnerConfig: RunnerConfig) {
|
|
13
|
+
const { config_path } = runnerConfig;
|
|
14
|
+
if (!config_path) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Check if file exists
|
|
19
|
+
try {
|
|
20
|
+
await fs.access(config_path, fs.constants.F_OK);
|
|
21
|
+
} catch (ex) {
|
|
22
|
+
throw new Error(`Config file path ${config_path} was specified, but the file does not exist.`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
micro.logger.info(`Collecting PowerSync configuration from File: ${config_path}`);
|
|
26
|
+
|
|
27
|
+
const content = await fs.readFile(config_path, 'utf-8');
|
|
28
|
+
|
|
29
|
+
let contentType: ConfigFileFormat | undefined;
|
|
30
|
+
switch (true) {
|
|
31
|
+
case config_path.endsWith('.yaml'):
|
|
32
|
+
case config_path.endsWith('.yml'):
|
|
33
|
+
contentType = ConfigFileFormat.YAML;
|
|
34
|
+
break;
|
|
35
|
+
case config_path.endsWith('.json'):
|
|
36
|
+
contentType = ConfigFileFormat.JSON;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
return this.parseContent(content, contentType);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import * as micro from '@journeyapps-platform/micro';
|
|
2
|
+
import { configFile, normalizeConnection } from '@powersync/service-types';
|
|
3
|
+
import { ConfigCollector } from './collectors/config-collector.js';
|
|
4
|
+
import { ResolvedConnection, ResolvedPowerSyncConfig, RunnerConfig, SyncRulesConfig } from './types.js';
|
|
5
|
+
import * as auth from '@/auth/auth-index.js';
|
|
6
|
+
import { SyncRulesCollector } from './sync-rules/sync-collector.js';
|
|
7
|
+
import { Base64ConfigCollector } from './collectors/impl/base64-config-collector.js';
|
|
8
|
+
import { FileSystemConfigCollector } from './collectors/impl/filesystem-config-collector.js';
|
|
9
|
+
import { Base64SyncRulesCollector } from './sync-rules/impl/base64-sync-rules-collector.js';
|
|
10
|
+
import { InlineSyncRulesCollector } from './sync-rules/impl/inline-sync-rules-collector.js';
|
|
11
|
+
import { FileSystemSyncRulesCollector } from './sync-rules/impl/filesystem-sync-rules-collector.js';
|
|
12
|
+
import { FallbackConfigCollector } from './collectors/impl/fallback-config-collector.js';
|
|
13
|
+
|
|
14
|
+
const POWERSYNC_DEV_KID = 'powersync-dev';
|
|
15
|
+
|
|
16
|
+
export type CompoundConfigCollectorOptions = {
|
|
17
|
+
/**
|
|
18
|
+
* Collectors for PowerSync configuration content.
|
|
19
|
+
* The configuration from first collector to provide a configuration
|
|
20
|
+
* is used. The order of the collectors specifies precedence
|
|
21
|
+
*/
|
|
22
|
+
configCollectors: ConfigCollector[];
|
|
23
|
+
/**
|
|
24
|
+
* Collectors for PowerSync sync rules content.
|
|
25
|
+
* The configuration from first collector to provide a configuration
|
|
26
|
+
* is used. The order of the collectors specifies precedence
|
|
27
|
+
*/
|
|
28
|
+
syncRulesCollectors: SyncRulesCollector[];
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const DEFAULT_COLLECTOR_OPTIONS: CompoundConfigCollectorOptions = {
|
|
32
|
+
configCollectors: [new Base64ConfigCollector(), new FileSystemConfigCollector(), new FallbackConfigCollector()],
|
|
33
|
+
syncRulesCollectors: [
|
|
34
|
+
new Base64SyncRulesCollector(),
|
|
35
|
+
new FileSystemSyncRulesCollector(),
|
|
36
|
+
new InlineSyncRulesCollector()
|
|
37
|
+
]
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export class CompoundConfigCollector {
|
|
41
|
+
constructor(protected options: CompoundConfigCollectorOptions = DEFAULT_COLLECTOR_OPTIONS) {}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Collects and resolves base config
|
|
45
|
+
*/
|
|
46
|
+
async collectConfig(runner_config: RunnerConfig = {}): Promise<ResolvedPowerSyncConfig> {
|
|
47
|
+
const baseConfig = await this.collectBaseConfig(runner_config);
|
|
48
|
+
|
|
49
|
+
const connections = baseConfig.replication?.connections ?? [];
|
|
50
|
+
if (connections.length > 1) {
|
|
51
|
+
throw new Error('Only a single replication connection is supported currently');
|
|
52
|
+
}
|
|
53
|
+
|
|
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
|
+
const collectors = new auth.CompoundKeyCollector();
|
|
65
|
+
const keyStore = new auth.KeyStore(collectors);
|
|
66
|
+
|
|
67
|
+
const inputKeys = baseConfig.client_auth?.jwks?.keys ?? [];
|
|
68
|
+
const staticCollector = await auth.StaticKeyCollector.importKeys(inputKeys);
|
|
69
|
+
|
|
70
|
+
collectors.add(staticCollector);
|
|
71
|
+
|
|
72
|
+
if (baseConfig.client_auth?.supabase && mapped.length > 0) {
|
|
73
|
+
collectors.add(new auth.CachedKeyCollector(new auth.SupabaseKeyCollector(mapped[0])));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let jwks_uris = baseConfig.client_auth?.jwks_uri ?? [];
|
|
77
|
+
if (typeof jwks_uris == 'string') {
|
|
78
|
+
jwks_uris = [jwks_uris];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
for (let uri of jwks_uris) {
|
|
82
|
+
collectors.add(
|
|
83
|
+
new auth.CachedKeyCollector(
|
|
84
|
+
new auth.RemoteJWKSCollector(uri, { block_local_ip: !!baseConfig.client_auth?.block_local_jwks })
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const baseDevKey = (baseConfig.client_auth?.jwks?.keys ?? []).find((key) => key.kid == POWERSYNC_DEV_KID);
|
|
90
|
+
|
|
91
|
+
let devKey: auth.KeySpec | undefined;
|
|
92
|
+
if (baseConfig.dev?.demo_auth && baseDevKey != null && baseDevKey.kty == 'oct') {
|
|
93
|
+
devKey = await auth.KeySpec.importKey(baseDevKey);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const sync_rules = await this.collectSyncRules(baseConfig, runner_config);
|
|
97
|
+
|
|
98
|
+
let jwt_audiences: string[] = baseConfig.client_auth?.audience ?? [];
|
|
99
|
+
|
|
100
|
+
let config: ResolvedPowerSyncConfig = {
|
|
101
|
+
connection: mapped[0],
|
|
102
|
+
storage: baseConfig.storage,
|
|
103
|
+
client_keystore: keyStore,
|
|
104
|
+
// Dev tokens only use the static keys, no external key sources
|
|
105
|
+
// We may restrict this even further to only the powersync-dev key.
|
|
106
|
+
dev_client_keystore: new auth.KeyStore(staticCollector),
|
|
107
|
+
api_tokens: baseConfig.api?.tokens ?? [],
|
|
108
|
+
dev: {
|
|
109
|
+
demo_auth: baseConfig.dev?.demo_auth ?? false,
|
|
110
|
+
demo_client: baseConfig.dev?.demo_client ?? false,
|
|
111
|
+
demo_password: baseConfig.dev?.demo_password,
|
|
112
|
+
crud_api: baseConfig.dev?.crud_api ?? false,
|
|
113
|
+
dev_key: devKey
|
|
114
|
+
},
|
|
115
|
+
port: baseConfig.port ?? 8080,
|
|
116
|
+
sync_rules,
|
|
117
|
+
jwt_audiences,
|
|
118
|
+
|
|
119
|
+
token_max_expiration: '1d', // 1 day
|
|
120
|
+
metadata: baseConfig.metadata ?? {},
|
|
121
|
+
migrations: baseConfig.migrations,
|
|
122
|
+
slot_name_prefix: connections[0]?.slot_name_prefix ?? 'powersync_'
|
|
123
|
+
};
|
|
124
|
+
return config;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Collects the base PowerSyncConfig from various registered collectors.
|
|
129
|
+
* @throws if no collector could return a configuration.
|
|
130
|
+
*/
|
|
131
|
+
protected async collectBaseConfig(runner_config: RunnerConfig): Promise<configFile.PowerSyncConfig> {
|
|
132
|
+
for (const collector of this.options.configCollectors) {
|
|
133
|
+
try {
|
|
134
|
+
const baseConfig = await collector.collect(runner_config);
|
|
135
|
+
if (baseConfig) {
|
|
136
|
+
return baseConfig;
|
|
137
|
+
}
|
|
138
|
+
micro.logger.debug(
|
|
139
|
+
`Could not collect PowerSync config with ${collector.name} method. Moving on to next method if available.`
|
|
140
|
+
);
|
|
141
|
+
} catch (ex) {
|
|
142
|
+
// An error in a collector is a hard stop
|
|
143
|
+
throw new Error(`Could not collect config using ${collector.name} method. Caught exception: ${ex}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
throw new Error('PowerSyncConfig could not be collected using any of the registered config collectors.');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
protected async collectSyncRules(
|
|
150
|
+
baseConfig: configFile.PowerSyncConfig,
|
|
151
|
+
runnerConfig: RunnerConfig
|
|
152
|
+
): Promise<SyncRulesConfig> {
|
|
153
|
+
for (const collector of this.options.syncRulesCollectors) {
|
|
154
|
+
try {
|
|
155
|
+
const config = await collector.collect(baseConfig, runnerConfig);
|
|
156
|
+
if (config) {
|
|
157
|
+
return config;
|
|
158
|
+
}
|
|
159
|
+
micro.logger.debug(
|
|
160
|
+
`Could not collect sync rules with ${collector.name} method. Moving on to next method if available.`
|
|
161
|
+
);
|
|
162
|
+
} catch (ex) {
|
|
163
|
+
// An error in a collector is a hard stop
|
|
164
|
+
throw new Error(`Could not collect sync rules using ${collector.name} method. Caught exception: ${ex}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
present: false
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { RunnerConfig, SyncRulesConfig } from '../../types.js';
|
|
2
|
+
import { SyncRulesCollector } from '../sync-collector.js';
|
|
3
|
+
import { configFile } from '@powersync/service-types';
|
|
4
|
+
|
|
5
|
+
export class Base64SyncRulesCollector extends SyncRulesCollector {
|
|
6
|
+
get name(): string {
|
|
7
|
+
return 'Base64';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async collect(baseConfig: configFile.PowerSyncConfig, runnerConfig: RunnerConfig): Promise<SyncRulesConfig | null> {
|
|
11
|
+
const { sync_rules_base64 } = runnerConfig;
|
|
12
|
+
if (!sync_rules_base64) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
present: true,
|
|
18
|
+
content: Buffer.from(sync_rules_base64, 'base64').toString()
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import { RunnerConfig, SyncRulesConfig } from '../../types.js';
|
|
3
|
+
import { SyncRulesCollector } from '../sync-collector.js';
|
|
4
|
+
import { configFile } from '@powersync/service-types';
|
|
5
|
+
|
|
6
|
+
export class FileSystemSyncRulesCollector extends SyncRulesCollector {
|
|
7
|
+
get name(): string {
|
|
8
|
+
return 'FileSystem';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async collect(baseConfig: configFile.PowerSyncConfig, runnerConfig: RunnerConfig): Promise<SyncRulesConfig | null> {
|
|
12
|
+
const sync_path = baseConfig.sync_rules?.path;
|
|
13
|
+
if (!sync_path) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { config_path } = runnerConfig;
|
|
18
|
+
|
|
19
|
+
// Depending on the container, the sync rules may not actually be present.
|
|
20
|
+
// Only persist the path here, and load on demand using `loadSyncRules()`.
|
|
21
|
+
return {
|
|
22
|
+
present: true,
|
|
23
|
+
path: config_path ? path.resolve(path.dirname(config_path), sync_path) : sync_path
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SyncRulesConfig } from '../../types.js';
|
|
2
|
+
import { SyncRulesCollector } from '../sync-collector.js';
|
|
3
|
+
import { configFile } from '@powersync/service-types';
|
|
4
|
+
|
|
5
|
+
export class InlineSyncRulesCollector extends SyncRulesCollector {
|
|
6
|
+
get name(): string {
|
|
7
|
+
return 'Inline';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async collect(baseConfig: configFile.PowerSyncConfig): Promise<SyncRulesConfig | null> {
|
|
11
|
+
const content = baseConfig.sync_rules?.content;
|
|
12
|
+
if (!content) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
present: true,
|
|
18
|
+
...baseConfig.sync_rules
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { configFile } from '@powersync/service-types';
|
|
2
|
+
import { RunnerConfig, SyncRulesConfig } from '../types.js';
|
|
3
|
+
|
|
4
|
+
export abstract class SyncRulesCollector {
|
|
5
|
+
abstract get name(): string;
|
|
6
|
+
|
|
7
|
+
abstract collect(baseConfig: configFile.PowerSyncConfig, runnerConfig: RunnerConfig): Promise<SyncRulesConfig | null>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { NormalizedPostgresConnection, configFile } from '@powersync/service-types';
|
|
2
|
+
import { KeySpec } from '../../auth/KeySpec.js';
|
|
3
|
+
import { KeyStore } from '../../auth/KeyStore.js';
|
|
4
|
+
|
|
5
|
+
export enum ServiceRunner {
|
|
6
|
+
UNIFIED = 'unified',
|
|
7
|
+
API = 'api',
|
|
8
|
+
SYNC = 'sync'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type RunnerConfig = {
|
|
12
|
+
config_path?: string;
|
|
13
|
+
config_base64?: string;
|
|
14
|
+
sync_rules_base64?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type MigrationContext = {
|
|
18
|
+
runner_config: RunnerConfig;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type Runner = (config: RunnerConfig) => Promise<void>;
|
|
22
|
+
|
|
23
|
+
export type ResolvedConnection = configFile.PostgresConnection & NormalizedPostgresConnection;
|
|
24
|
+
|
|
25
|
+
export type SyncRulesConfig = {
|
|
26
|
+
present: boolean;
|
|
27
|
+
content?: string;
|
|
28
|
+
path?: string;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type ResolvedPowerSyncConfig = {
|
|
32
|
+
connection?: ResolvedConnection;
|
|
33
|
+
storage: configFile.StorageConfig;
|
|
34
|
+
dev: {
|
|
35
|
+
demo_auth: boolean;
|
|
36
|
+
demo_password?: string;
|
|
37
|
+
crud_api: boolean;
|
|
38
|
+
demo_client: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Only present when demo_auth == true
|
|
41
|
+
*/
|
|
42
|
+
dev_key?: KeySpec;
|
|
43
|
+
};
|
|
44
|
+
client_keystore: KeyStore;
|
|
45
|
+
/**
|
|
46
|
+
* Keystore for development tokens.
|
|
47
|
+
*/
|
|
48
|
+
dev_client_keystore: KeyStore;
|
|
49
|
+
port: number;
|
|
50
|
+
sync_rules: SyncRulesConfig;
|
|
51
|
+
api_tokens: string[];
|
|
52
|
+
jwt_audiences: string[];
|
|
53
|
+
token_max_expiration: string;
|
|
54
|
+
metadata: Record<string, string>;
|
|
55
|
+
migrations?: {
|
|
56
|
+
disable_auto_migration?: boolean;
|
|
57
|
+
};
|
|
58
|
+
/** Prefix for postgres replication slot names. May eventually be connection-specific. */
|
|
59
|
+
slot_name_prefix: string;
|
|
60
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import { baseUri } from '@powersync/service-types';
|
|
3
|
+
|
|
4
|
+
import { ResolvedConnection, ResolvedPowerSyncConfig, RunnerConfig } from './config/types.js';
|
|
5
|
+
import { CompoundConfigCollector } from './config/compound-config-collector.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Build a single URI from full postgres credentials.
|
|
9
|
+
*/
|
|
10
|
+
export function buildDemoPgUri(options: ResolvedConnection): string {
|
|
11
|
+
if (!options.debug_api) {
|
|
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();
|
|
29
|
+
return collector.collectConfig(runnerConfig);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function loadSyncRules(config: ResolvedPowerSyncConfig): Promise<string | undefined> {
|
|
33
|
+
const sync_rules = config.sync_rules;
|
|
34
|
+
if (sync_rules.content) {
|
|
35
|
+
return sync_rules.content;
|
|
36
|
+
} else if (sync_rules.path) {
|
|
37
|
+
return await fs.readFile(sync_rules.path, 'utf-8');
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/util/env.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { utils } from '@journeyapps-platform/micro';
|
|
2
|
+
|
|
3
|
+
import { ServiceRunner } from './config/types.js';
|
|
4
|
+
|
|
5
|
+
export const env = utils.collectEnvironmentVariables({
|
|
6
|
+
/**
|
|
7
|
+
* Path to configuration file in filesystem
|
|
8
|
+
*/
|
|
9
|
+
POWERSYNC_CONFIG_PATH: utils.type.string.optional(),
|
|
10
|
+
/**
|
|
11
|
+
* Base64 encoded contents of configuration file
|
|
12
|
+
*/
|
|
13
|
+
POWERSYNC_CONFIG_B64: utils.type.string.optional(),
|
|
14
|
+
/**
|
|
15
|
+
* Base64 encoded contents of sync rules YAML
|
|
16
|
+
*/
|
|
17
|
+
POWERSYNC_SYNC_RULES_B64: utils.type.string.optional(),
|
|
18
|
+
/**
|
|
19
|
+
* Runner to be started in this process
|
|
20
|
+
*/
|
|
21
|
+
PS_RUNNER_TYPE: utils.type.string.default(ServiceRunner.UNIFIED),
|
|
22
|
+
/**
|
|
23
|
+
* Port for metrics
|
|
24
|
+
*/
|
|
25
|
+
METRICS_PORT: utils.type.number.optional()
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export type Env = typeof env;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as micro from '@journeyapps-platform/micro';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Track and log memory usage.
|
|
5
|
+
*
|
|
6
|
+
* Only for debugging purposes. This could add significant overhead and/or side-effects,
|
|
7
|
+
* and should not be used in production.
|
|
8
|
+
*/
|
|
9
|
+
export function trackMemoryUsage() {
|
|
10
|
+
let lastMem = process.memoryUsage();
|
|
11
|
+
|
|
12
|
+
let bufferMemory = {
|
|
13
|
+
alloc: 0,
|
|
14
|
+
allocUnsafe: 0,
|
|
15
|
+
allocUnsafeSlow: 0,
|
|
16
|
+
from: 0,
|
|
17
|
+
concat: 0
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const bufferRegistry = new FinalizationRegistry<[keyof typeof bufferMemory, number]>((v) => {
|
|
21
|
+
const [key, value] = v;
|
|
22
|
+
bufferMemory[key] -= value;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
for (let key of Object.keys(bufferMemory)) {
|
|
26
|
+
const typedKey = key as keyof typeof bufferMemory;
|
|
27
|
+
const originalFunction = Buffer[typedKey] as (...args: any[]) => Buffer;
|
|
28
|
+
Buffer[typedKey] = function (...args: any[]) {
|
|
29
|
+
const buffer = originalFunction.apply(this, args);
|
|
30
|
+
bufferMemory[typedKey] += buffer.byteLength;
|
|
31
|
+
bufferRegistry.register(buffer, [typedKey, buffer.byteLength]);
|
|
32
|
+
return buffer;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
setInterval(() => {
|
|
37
|
+
const mem = process.memoryUsage();
|
|
38
|
+
|
|
39
|
+
let isDifferent = false;
|
|
40
|
+
for (const key in mem) {
|
|
41
|
+
if (Math.abs((mem as any)[key] - (lastMem as any)[key]) > 5_000_000) {
|
|
42
|
+
isDifferent = true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (isDifferent) {
|
|
47
|
+
lastMem = mem;
|
|
48
|
+
|
|
49
|
+
const output = `RSS ${mb(mem.rss)} (
|
|
50
|
+
HAT ${mb(mem.heapTotal)} (
|
|
51
|
+
HU ${mb(mem.heapUsed)}
|
|
52
|
+
),
|
|
53
|
+
buffers ${mb(mem.arrayBuffers)} (
|
|
54
|
+
alloc ${mb(bufferMemory.alloc + bufferMemory.allocUnsafe + bufferMemory.allocUnsafeSlow)},
|
|
55
|
+
from ${mb(bufferMemory.from)}
|
|
56
|
+
concat ${mb(bufferMemory.concat)}
|
|
57
|
+
)
|
|
58
|
+
)`.replaceAll(/\s+/g, ' ');
|
|
59
|
+
|
|
60
|
+
micro.logger.info(output);
|
|
61
|
+
}
|
|
62
|
+
}, 50);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function mb(n: number) {
|
|
66
|
+
return Math.round(n / 1024 / 1024) + 'mb';
|
|
67
|
+
}
|