Skip to content

Commit a7863e8

Browse files
HTTP Client Config (#229)
1 parent 8d5b500 commit a7863e8

File tree

17 files changed

+335
-114
lines changed

17 files changed

+335
-114
lines changed

CHANGELOG.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 1.4.0 (unreleased)
4+
5+
* Added the ability to log PowerSync service HTTP request information via specifying a
6+
`SyncClientConfiguration` in the `SyncOptions.clientConfiguration` parameter used in
7+
`PowerSyncDatabase.connect()` calls.
8+
39
## 1.3.1
410

511
* Update SQLite to 3.50.3.
@@ -12,7 +18,8 @@
1218
## 1.3.0
1319

1420
* Support tables created outside of PowerSync with the `RawTable` API.
15-
For more information, see [the documentation](https://docs.powersync.com/usage/use-case-examples/raw-tables).
21+
For more information,
22+
see [the documentation](https://docs.powersync.com/usage/use-case-examples/raw-tables).
1623
* Fix `runWrapped` catching cancellation exceptions.
1724
* Fix errors in `PowerSyncBackendConnector.fetchCredentials()` crashing Android apps.
1825

@@ -23,7 +30,8 @@
2330

2431
## 1.2.1
2532

26-
* [Supabase Connector] Fixed issue where only `400` HTTP status code errors where reported as connection errors. The connector now reports errors for codes `>=400`.
33+
* [Supabase Connector] Fixed issue where only `400` HTTP status code errors where reported as
34+
connection errors. The connector now reports errors for codes `>=400`.
2735
* Update PowerSync core extension to `0.4.1`, fixing an issue with the new Rust client.
2836
* Rust sync client: Fix writes made while offline not being uploaded reliably.
2937
* Add watchOS support.
@@ -32,7 +40,7 @@
3240

3341
* Add a new sync client implementation written in Rust instead of Kotlin. While this client is still
3442
experimental, we intend to make it the default in the future. The main benefit of this client is
35-
faster sync performance, but upcoming features will also require this client. We encourage
43+
faster sync performance, but upcoming features will also require this client. We encourage
3644
interested users to try it out by opting in to `ExperimentalPowerSyncAPI` and passing options when
3745
connecting:
3846
```Kotlin
@@ -62,10 +70,13 @@
6270

6371
## 1.1.0
6472

65-
* Add `trackPreviousValues` option on `Table` which sets `CrudEntry.previousValues` to previous values on updates.
66-
* Add `trackMetadata` option on `Table` which adds a `_metadata` column that can be used for updates.
73+
* Add `trackPreviousValues` option on `Table` which sets `CrudEntry.previousValues` to previous
74+
values on updates.
75+
* Add `trackMetadata` option on `Table` which adds a `_metadata` column that can be used for
76+
updates.
6777
The configured metadata is available through `CrudEntry.metadata`.
68-
* Add `ignoreEmptyUpdates` option which skips creating CRUD entries for updates that don't change any values.
78+
* Add `ignoreEmptyUpdates` option which skips creating CRUD entries for updates that don't change
79+
any values.
6980

7081
## 1.0.1
7182

PowerSyncKotlin/build.gradle.kts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ kotlin {
4646
sourceSets {
4747
commonMain.dependencies {
4848
api(project(":core"))
49+
implementation(libs.ktor.client.logging)
4950
}
5051
}
5152
}
@@ -58,8 +59,16 @@ listOf("Debug", "Release").forEach { buildType ->
5859
val originalFramework = tasks.getByName("assemblePowerSyncKotlin${buildType}XCFramework")
5960
dependsOn(originalFramework)
6061

61-
val source = project.layout.buildDirectory.map { it.dir("XCFrameworks/${buildType.lowercase()}") }.get().asFile
62-
val archiveFile = project.layout.buildDirectory.map { it.file("FrameworkArchives/PowersyncKotlin$buildType.zip") }.get().asFile
62+
val source =
63+
project.layout.buildDirectory
64+
.map { it.dir("XCFrameworks/${buildType.lowercase()}") }
65+
.get()
66+
.asFile
67+
val archiveFile =
68+
project.layout.buildDirectory
69+
.map { it.file("FrameworkArchives/PowersyncKotlin$buildType.zip") }
70+
.get()
71+
.asFile
6372

6473
archiveFile.parentFile.mkdirs()
6574
archiveFile.delete()

PowerSyncKotlin/src/appleMain/kotlin/com/powersync/SDK.kt

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
package com.powersync
44

5+
import com.powersync.sync.SyncClientConfiguration
56
import com.powersync.sync.SyncOptions
7+
import io.ktor.client.plugins.logging.LogLevel
8+
import io.ktor.client.plugins.logging.Logging
9+
import io.ktor.client.plugins.logging.Logger as KtorLogger
610

711
/**
812
* Helper class designed to bridge SKIEE methods and allow them to throw
@@ -17,16 +21,70 @@ import com.powersync.sync.SyncOptions
1721
public fun throwPowerSyncException(exception: PowerSyncException): Unit = throw exception
1822

1923
/**
20-
* Creates a [ConnectionMethod] based on simple booleans, because creating the actual instance with
24+
* A small wrapper around the Ktor LogLevel enum to allow
25+
* specifying the log level from Swift without exposing the Ktor plugin types.
26+
*/
27+
public enum class SwiftSyncRequestLogLevel {
28+
ALL,
29+
HEADERS,
30+
BODY,
31+
INFO,
32+
NONE,
33+
}
34+
35+
/**
36+
* Mapper function to Ktor LogLevel
37+
*/
38+
internal fun SwiftSyncRequestLogLevel.toKtorLogLevel(): LogLevel =
39+
when (this) {
40+
SwiftSyncRequestLogLevel.ALL -> LogLevel.ALL
41+
SwiftSyncRequestLogLevel.HEADERS -> LogLevel.HEADERS
42+
SwiftSyncRequestLogLevel.BODY -> LogLevel.BODY
43+
SwiftSyncRequestLogLevel.INFO -> LogLevel.INFO
44+
SwiftSyncRequestLogLevel.NONE -> LogLevel.NONE
45+
}
46+
47+
/**
48+
* Configuration which is used to configure the Ktor logging plugin
49+
*/
50+
public data class SwiftRequestLoggerConfig(
51+
public val logLevel: SwiftSyncRequestLogLevel,
52+
public val log: (message: String) -> Unit,
53+
)
54+
55+
/**
56+
* Creates a Ktor [SyncClientConfiguration.ExtendedConfig] that extends the default Ktor client.
57+
* Specifying a [SwiftRequestLoggerConfig] will install the Ktor logging plugin with the specified configuration.
58+
*/
59+
public fun createExtendedSyncClientConfiguration(loggingConfig: SwiftRequestLoggerConfig? = null): SyncClientConfiguration =
60+
SyncClientConfiguration.ExtendedConfig {
61+
if (loggingConfig != null) {
62+
install(Logging) {
63+
// Pass everything to the provided logger. The logger controls the active level
64+
level = loggingConfig.logLevel.toKtorLogLevel()
65+
logger =
66+
object : KtorLogger {
67+
override fun log(message: String) {
68+
loggingConfig.log(message)
69+
}
70+
}
71+
}
72+
}
73+
}
74+
75+
/**
76+
* Creates a [SyncOptions] based on simple parameters, because creating the actual instance with
2177
* the default constructor is not possible from Swift due to an optional argument with an internal
2278
* default value.
2379
*/
2480
@OptIn(ExperimentalPowerSyncAPI::class)
2581
public fun createSyncOptions(
2682
newClient: Boolean,
2783
userAgent: String,
84+
loggingConfig: SwiftRequestLoggerConfig? = null,
2885
): SyncOptions =
2986
SyncOptions(
3087
newClientImplementation = newClient,
3188
userAgent = userAgent,
89+
clientConfiguration = createExtendedSyncClientConfiguration(loggingConfig),
3290
)

core/build.gradle.kts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import org.gradle.internal.os.OperatingSystem
66
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
77
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest
88
import org.jetbrains.kotlin.gradle.tasks.KotlinTest
9+
import org.jetbrains.kotlin.konan.target.Family
910
import java.nio.file.Path
1011
import kotlin.io.path.createDirectories
1112
import kotlin.io.path.writeText
12-
import org.jetbrains.kotlin.konan.target.Family
1313

1414
plugins {
1515
alias(libs.plugins.kotlinMultiplatform)
@@ -140,12 +140,13 @@ val generateVersionConstant by tasks.registering {
140140
dir.mkdir()
141141
val rootPath = dir.toPath()
142142

143-
val source = """
143+
val source =
144+
"""
144145
package $packageName
145146
146147
internal const val LIBRARY_VERSION: String = "$currentVersion"
147148
148-
""".trimIndent()
149+
""".trimIndent()
149150

150151
val packageRoot = packageName.split('.').fold(rootPath, Path::resolve)
151152
packageRoot.createDirectories()
@@ -204,7 +205,6 @@ kotlin {
204205
dependencies {
205206
implementation(libs.uuid)
206207
implementation(libs.kotlin.stdlib)
207-
implementation(libs.ktor.client.core)
208208
implementation(libs.ktor.client.contentnegotiation)
209209
implementation(libs.ktor.serialization.json)
210210
implementation(libs.kotlinx.io)
@@ -213,6 +213,7 @@ kotlin {
213213
implementation(libs.stately.concurrency)
214214
implementation(libs.configuration.annotations)
215215
api(projects.persistence)
216+
api(libs.ktor.client.core)
216217
api(libs.kermit)
217218
}
218219
}
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.powersync.sync
22

33
import com.powersync.ExperimentalPowerSyncAPI
4+
import com.powersync.testutils.ActiveDatabaseTest
45

56
/**
67
* Small utility to run tests both with the legacy Kotlin sync implementation and the new
@@ -11,7 +12,9 @@ abstract class AbstractSyncTest(
1112
protected val useBson: Boolean = false,
1213
) {
1314
@OptIn(ExperimentalPowerSyncAPI::class)
14-
val options: SyncOptions get() {
15-
return SyncOptions(useNewSyncImplementation)
16-
}
15+
internal fun ActiveDatabaseTest.getOptions(): SyncOptions =
16+
SyncOptions(
17+
useNewSyncImplementation,
18+
clientConfiguration = SyncClientConfiguration.ExistingClient(createSyncClient()),
19+
)
1720
}

0 commit comments

Comments
 (0)