Skip to content

Commit b1a6e1d

Browse files
authored
Improve ergonomics for Kotlin wrapper (#744)
* Rename to `WpRequestResult.Success.response` * Add a `successfulResponse` helper to `WpRequestResult` * Limit `ParsedUrl`'s Kotlin exposure by using `java.net.URL` * Publish Kotlin sources
1 parent d6b89bc commit b1a6e1d

File tree

16 files changed

+56
-33
lines changed

16 files changed

+56
-33
lines changed

native/kotlin/api/android/src/androidTest/kotlin/rs/wordpress/api/android/UsersEndpointAndroidTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ import kotlinx.coroutines.test.runTest
44
import org.junit.Test
55
import rs.wordpress.api.kotlin.WpApiClient
66
import rs.wordpress.api.kotlin.WpRequestResult
7-
import uniffi.wp_api.ParsedUrl
87
import uniffi.wp_api.UserListParams
98
import uniffi.wp_api.WpAuthenticationProvider
9+
import java.net.URL
1010

1111
class UsersEndpointAndroidTest {
1212
// https://developer.android.com/studio/run/emulator-networking
1313
private val siteUrl = "http://10.0.2.2"
14-
private val client = WpApiClient(ParsedUrl.parse(siteUrl), WpAuthenticationProvider.none())
14+
private val client = WpApiClient(URL(siteUrl), WpAuthenticationProvider.none())
1515

1616
@Test
1717
fun testUserListRequest() = runTest {
1818
val result = client.request { requestBuilder ->
1919
requestBuilder.users().listWithViewContext(params = UserListParams())
2020
}
21-
assert(result is WpRequestResult.WpRequestSuccess)
21+
assert(result is WpRequestResult.Success)
2222
}
2323
}

native/kotlin/api/kotlin/build.gradle.kts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ plugins {
88
}
99

1010
java {
11+
withJavadocJar()
12+
withSourcesJar()
13+
1114
sourceCompatibility = JavaVersion.VERSION_17
1215
targetCompatibility = JavaVersion.VERSION_17
1316
toolchain {
@@ -124,6 +127,9 @@ tasks.named("processIntegrationTestResources").configure {
124127
dependsOn(rootProject.tasks.named("copyTestMedia"))
125128
dependsOn(rootProject.tasks.named("copySampleJSON"))
126129
}
130+
tasks.named("sourcesJar").configure {
131+
dependsOn(generateUniFFIBindingsTask)
132+
}
127133

128134
project.afterEvaluate {
129135
publishing {

native/kotlin/api/kotlin/src/integrationTest/kotlin/IntegrationTestHelpers.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ fun defaultApiClient(): WpApiClient {
2525
}
2626

2727
fun <T> WpRequestResult<T>.assertSuccess() {
28-
assert(this is WpRequestResult.WpRequestSuccess)
28+
assert(this is WpRequestResult.Success)
2929
}
3030

3131
fun <T> WpRequestResult<T>.assertSuccessAndRetrieveData(): T {
32-
assert(this is WpRequestResult.WpRequestSuccess) {
32+
assert(this is WpRequestResult.Success) {
3333
"Request wasn't successful: $this"
3434
}
35-
return (this as WpRequestResult.WpRequestSuccess).data
35+
return (this as WpRequestResult.Success).response
3636
}
3737

3838
fun <T> WpRequestResult<T>.wpErrorCode(): WpErrorCode {

native/kotlin/api/kotlin/src/integrationTest/kotlin/ManualParserTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package rs.wordpress.api.kotlin
22

33
import kotlinx.coroutines.test.runTest
44
import org.junit.jupiter.api.Test
5+
import uniffi.wp_api.ParsedUrl
56
import uniffi.wp_api.UniffiWpApiRequestBuilder
67
import uniffi.wp_api.UserListParams
78
import uniffi.wp_api.WpAuthenticationProvider
@@ -19,7 +20,7 @@ class ManualParserTest {
1920
@Test
2021
fun testUserListManualRequestAndParsing() = runTest {
2122
val requestBuilder = UniffiWpApiRequestBuilder(
22-
apiUrlResolver = WpOrgSiteApiUrlResolver(apiRootUrl = testCredentials.apiRootUrl),
23+
apiUrlResolver = WpOrgSiteApiUrlResolver(apiRootUrl = ParsedUrl(testCredentials.apiRootUrl)),
2324
authProvider
2425
)
2526
val userListRequest = requestBuilder.users().listWithEditContext(UserListParams())

native/kotlin/api/kotlin/src/integrationTest/kotlin/TestCredentials.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package rs.wordpress.api.kotlin
33
import kotlinx.serialization.SerialName
44
import kotlinx.serialization.Serializable
55
import kotlinx.serialization.json.Json
6-
import uniffi.wp_api.ParsedUrl
76
import java.io.File
7+
import java.net.URL
88
import java.text.SimpleDateFormat
99
import java.util.TimeZone
1010

@@ -44,5 +44,5 @@ data class TestCredentials(
4444
}
4545
}
4646

47-
val apiRootUrl by lazy { ParsedUrl.parse("$siteUrl/wp-json") }
47+
val apiRootUrl by lazy { URL("$siteUrl/wp-json") }
4848
}

native/kotlin/api/kotlin/src/main/kotlin/rs/wordpress/api/kotlin/ApiDiscoveryResult.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@ import uniffi.wp_api.AutoDiscoveryAttemptSuccess
44
import uniffi.wp_api.FetchAndParseApiRootFailure
55
import uniffi.wp_api.FindApiRootFailure
66
import uniffi.wp_api.ParseUrlException
7-
import uniffi.wp_api.ParsedUrl
7+
import java.net.URL
88

99
sealed class ApiDiscoveryResult {
1010
data class Success(val success: AutoDiscoveryAttemptSuccess) : ApiDiscoveryResult()
1111
data class FailureParseSiteUrl(
1212
val error: ParseUrlException
1313
) : ApiDiscoveryResult()
1414
data class FailureFindApiRoot(
15-
val parsedSiteUrl: ParsedUrl,
15+
val parsedSiteUrl: URL,
1616
val findApiRootFailure: FindApiRootFailure
1717
) : ApiDiscoveryResult()
1818
data class FailureFetchAndParseApiRoot(
19-
val parsedSiteUrl: ParsedUrl,
20-
val apiRootUrl: ParsedUrl,
19+
val parsedSiteUrl: URL,
20+
val apiRootUrl: URL,
2121
val fetchAndParseApiRootFailure: FetchAndParseApiRootFailure
2222
) : ApiDiscoveryResult()
2323
}

native/kotlin/api/kotlin/src/main/kotlin/rs/wordpress/api/kotlin/JetpackApiClient.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import uniffi.wp_api.WpApiMiddlewarePipeline
1313
import uniffi.wp_api.WpAppNotifier
1414
import uniffi.wp_api.WpAuthenticationProvider
1515
import uniffi.wp_api.WpOrgSiteApiUrlResolver
16+
import java.net.URL
1617

1718
class JetpackApiClient(
1819
apiUrlResolver: ApiUrlResolver,
@@ -22,13 +23,13 @@ class JetpackApiClient(
2223
private val dispatcher: CoroutineDispatcher = Dispatchers.IO
2324
) {
2425
constructor(
25-
wpOrgSiteApiRootUrl: ParsedUrl,
26+
wpOrgSiteApiRootUrl: URL,
2627
authProvider: WpAuthenticationProvider,
2728
requestExecutor: RequestExecutor = WpRequestExecutor(),
2829
appNotifier: WpAppNotifier = EmptyAppNotifier(),
2930
dispatcher: CoroutineDispatcher = Dispatchers.IO
3031
) : this(
31-
apiUrlResolver = WpOrgSiteApiUrlResolver(apiRootUrl = wpOrgSiteApiRootUrl),
32+
apiUrlResolver = WpOrgSiteApiUrlResolver(apiRootUrl = ParsedUrl.parse(wpOrgSiteApiRootUrl.toString())),
3233
authProvider,
3334
requestExecutor,
3435
appNotifier,
@@ -58,7 +59,7 @@ class JetpackApiClient(
5859
executeRequest: suspend (UniffiJetpackApiClient) -> T
5960
): WpRequestResult<T> = withContext(dispatcher) {
6061
try {
61-
WpRequestResult.WpRequestSuccess(data = executeRequest(requestBuilder))
62+
WpRequestResult.Success(response = executeRequest(requestBuilder))
6263
} catch (exception: WpApiException) {
6364
mapWpApiExceptionToWpRequestResult(exception)
6465
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package rs.wordpress.api.kotlin
2+
3+
import uniffi.wp_api.ParsedUrl
4+
import java.net.URL
5+
6+
operator fun ParsedUrl.Companion.invoke(url: URL) = parse(url.toString())
7+
8+
fun ParsedUrl.toURL(): URL = URL(this.url())

native/kotlin/api/kotlin/src/main/kotlin/rs/wordpress/api/kotlin/WpApiClient.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import uniffi.wp_api.WpApiMiddlewarePipeline
1313
import uniffi.wp_api.WpAppNotifier
1414
import uniffi.wp_api.WpAuthenticationProvider
1515
import uniffi.wp_api.WpOrgSiteApiUrlResolver
16+
import java.net.URL
1617

1718
class WpApiClient(
1819
apiUrlResolver: ApiUrlResolver,
@@ -22,13 +23,13 @@ class WpApiClient(
2223
private val dispatcher: CoroutineDispatcher = Dispatchers.IO
2324
) {
2425
constructor(
25-
wpOrgSiteApiRootUrl: ParsedUrl,
26+
wpOrgSiteApiRootUrl: URL,
2627
authProvider: WpAuthenticationProvider,
2728
requestExecutor: RequestExecutor = WpRequestExecutor(),
2829
appNotifier: WpAppNotifier = EmptyAppNotifier(),
2930
dispatcher: CoroutineDispatcher = Dispatchers.IO
3031
) : this(
31-
apiUrlResolver = WpOrgSiteApiUrlResolver(apiRootUrl = wpOrgSiteApiRootUrl),
32+
apiUrlResolver = WpOrgSiteApiUrlResolver(apiRootUrl = ParsedUrl.parse(wpOrgSiteApiRootUrl.toString())),
3233
authProvider,
3334
requestExecutor,
3435
appNotifier,
@@ -58,7 +59,7 @@ class WpApiClient(
5859
executeRequest: suspend (UniffiWpApiClient) -> T
5960
): WpRequestResult<T> = withContext(dispatcher) {
6061
try {
61-
WpRequestResult.WpRequestSuccess(data = executeRequest(requestBuilder))
62+
WpRequestResult.Success(response = executeRequest(requestBuilder))
6263
} catch (exception: WpApiException) {
6364
mapWpApiExceptionToWpRequestResult(exception)
6465
}

native/kotlin/api/kotlin/src/main/kotlin/rs/wordpress/api/kotlin/WpComApiClient.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class WpComApiClient(
3939
executeRequest: suspend (UniffiWpComApiClient) -> T
4040
): WpRequestResult<T> = withContext(dispatcher) {
4141
try {
42-
WpRequestResult.WpRequestSuccess(data = executeRequest(requestBuilder))
42+
WpRequestResult.Success(response = executeRequest(requestBuilder))
4343
} catch (exception: WpApiException) {
4444
mapWpApiExceptionToWpRequestResult(exception)
4545
}

native/kotlin/api/kotlin/src/main/kotlin/rs/wordpress/api/kotlin/WpLoginClient.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ class WpLoginClient(
2828
error = exception.error,
2929
)
3030
is AutoDiscoveryAttemptFailure.FindApiRoot -> ApiDiscoveryResult.FailureFindApiRoot(
31-
parsedSiteUrl = exception.parsedSiteUrl,
31+
parsedSiteUrl = exception.parsedSiteUrl.toURL(),
3232
findApiRootFailure = exception.findApiRootFailure,
3333
)
3434

3535
is AutoDiscoveryAttemptFailure.FetchAndParseApiRoot -> ApiDiscoveryResult.FailureFetchAndParseApiRoot(
36-
parsedSiteUrl = exception.parsedSiteUrl,
37-
apiRootUrl = exception.apiRootUrl,
36+
parsedSiteUrl = exception.parsedSiteUrl.toURL(),
37+
apiRootUrl = exception.apiRootUrl.toURL(),
3838
fetchAndParseApiRootFailure = exception.fetchAndParseApiRootFailure
3939
)
4040
}

native/kotlin/api/kotlin/src/main/kotlin/rs/wordpress/api/kotlin/WpRequestResult.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import uniffi.wp_api.WpErrorCode
55
import uniffi.wp_api.WpRedirect
66

77
sealed class WpRequestResult<T> {
8-
data class WpRequestSuccess<T>(val data: T) : WpRequestResult<T>()
8+
data class Success<T>(val response: T) : WpRequestResult<T>()
99
data class WpError<T>(
1010
val errorCode: WpErrorCode,
1111
val errorMessage: String,
@@ -40,4 +40,10 @@ sealed class WpRequestResult<T> {
4040
val statusCode: UShort,
4141
val response: String,
4242
) : WpRequestResult<T>()
43+
44+
fun successfulResponse(): T? =
45+
when (this) {
46+
is Success -> this.response
47+
else -> null
48+
}
4349
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package rs.wordpress.example.shared.domain
22

3-
import uniffi.wp_api.ParsedUrl
3+
import java.net.URL
44

5-
data class AuthenticatedSite(val name: String, val apiRootUrl: ParsedUrl)
5+
data class AuthenticatedSite(val name: String, val apiRootUrl: URL)

native/kotlin/example/composeApp/src/commonMain/kotlin/rs/wordpress/example/shared/repository/AuthenticationRepository.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package rs.wordpress.example.shared.repository
22

33
import rs.wordpress.example.shared.domain.AuthenticatedSite
4-
import uniffi.wp_api.ParsedUrl
54
import uniffi.wp_api.WpAuthentication
65
import uniffi.wp_api.wpAuthenticationFromUsernameAndPassword
6+
import java.net.URL
77

88
class AuthenticationRepository(
99
localTestSiteUrl: String,
@@ -14,16 +14,16 @@ class AuthenticationRepository(
1414

1515
init {
1616
addAuthenticatedSite(
17-
ParsedUrl.parse(localTestSiteUrl),
18-
ParsedUrl.parse("$localTestSiteUrl/wp-json"),
17+
URL(localTestSiteUrl),
18+
URL("$localTestSiteUrl/wp-json"),
1919
localTestSiteUsername,
2020
localTestSitePassword
2121
)
2222
}
2323

24-
fun addAuthenticatedSite(siteUrl: ParsedUrl, apiRootUrl: ParsedUrl, username: String, password: String): Boolean {
24+
fun addAuthenticatedSite(siteUrl: URL, apiRootUrl: URL, username: String, password: String): Boolean {
2525
if (username.isNotEmpty() && password.isNotEmpty()) {
26-
authenticatedSites[AuthenticatedSite(name = siteUrl.url(), apiRootUrl)] =
26+
authenticatedSites[AuthenticatedSite(name = siteUrl.toString(), apiRootUrl)] =
2727
wpAuthenticationFromUsernameAndPassword(username, password)
2828
return true
2929
}

native/kotlin/example/composeApp/src/commonMain/kotlin/rs/wordpress/example/shared/ui/plugins/PluginListViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class PluginListViewModel(private val authRepository: AuthenticationRepository)
3030
}
3131
}
3232
return when (pluginsResult) {
33-
is WpRequestResult.WpRequestSuccess -> pluginsResult.data.data
33+
is WpRequestResult.Success -> pluginsResult.response.data
3434
else -> listOf()
3535
}
3636
}

native/kotlin/example/composeApp/src/commonMain/kotlin/rs/wordpress/example/shared/ui/users/UserListViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class UserListViewModel(private val authRepository: AuthenticationRepository) {
3030
}
3131
}
3232
return when (usersResult) {
33-
is WpRequestResult.WpRequestSuccess -> usersResult.data.data
33+
is WpRequestResult.Success -> usersResult.response.data
3434
else -> throw IllegalStateException("User list request should succeed: $usersResult")
3535
}
3636
}

0 commit comments

Comments
 (0)