Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace Kotlin lib with lib generated using openapi-codegen #1708

Open
wants to merge 52 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
34afee9
Kotlin: Upgrade Gradle
svix-mman Feb 11, 2025
11c7f6b
kotlin: Add kotlinx and add dependency on kotlin.jvm 2.1.0
svix-mman Feb 11, 2025
222f492
kotlin: Add `MaybeUnset` and `SvixHttpClient` classes
svix-mman Feb 11, 2025
5f59f45
kotlin: Fix SvixHttpClient
svix-mman Feb 11, 2025
e586995
kotlin: Refactor ApiException
svix-mman Feb 11, 2025
b12224d
kotlin: Refactor high-level client with newly generated code
svix-mman Feb 11, 2025
5991ade
kotlin: Remove this, it's now part of Svix.kt
svix-mman Feb 11, 2025
29c490f
kotlin: Refactor Svix class
svix-mman Feb 11, 2025
03db632
kotlin: Fix tests
svix-mman Feb 11, 2025
983baa6
kotlin: Removed generated code from srcDirs
svix-mman Feb 11, 2025
cd01876
kotlin: Add newly generated models
svix-mman Feb 11, 2025
3d6d0f8
kotlin: Document breaking changes
svix-mman Feb 11, 2025
4dbcec4
kotlin: Bump the version for these deps
svix-mman Feb 12, 2025
2a18d43
kotlin: Remove unused dependency on moshi
svix-mman Feb 12, 2025
5aab712
kotlin: Better debugging. (Will remove before merging)
svix-mman Feb 12, 2025
0d27f3e
kotlin: Format tests
svix-mman Feb 12, 2025
65ac101
kotlin: Make string enums serializable, and add a toString method
svix-mman Feb 12, 2025
b26cc7d
kotlin: Mark int enums as @Serializable
svix-mman Feb 12, 2025
5f41318
kotlin: Add serializeQueryParam util
svix-mman Feb 12, 2025
dd6bfd4
kotlin: use `serializeQueryParam` for none string query params
svix-mman Feb 12, 2025
2babcb4
kotlin: Comma separate list/set params in url query
svix-mman Feb 12, 2025
0f604c7
kotlin: Add `toQueryParam` on enums
svix-mman Feb 12, 2025
33dfe9a
kotlin: Sort lists/sets before comma separating and url encoding
svix-mman Feb 12, 2025
9bdc27c
kotlin: Add test for query param encoding
svix-mman Feb 12, 2025
6d33dd1
kotlin: Test datetime(Instant)/bools are encoded correctly
svix-mman Feb 12, 2025
9f1846d
kotlin: Rename `MaybeUnset.Undefined` to `MaybeUnset.Unset`
svix-mman Feb 12, 2025
60f65b1
kotlin: Add tests for MaybeUnset
svix-mman Feb 12, 2025
a6c7c58
kotlin: Add test for headers
svix-mman Feb 13, 2025
349f31d
kotlin: Test user-agent is set
svix-mman Feb 13, 2025
34f6e08
kotlin: Rework codegen to make this look cleaner
svix-mman Feb 13, 2025
e1e2a38
kotlin: Add retry logic for status code >= 500
svix-mman Feb 13, 2025
f7ac2d9
kotlin: Add instant(timestamp) tests
svix-mman Feb 13, 2025
7ecb5ea
kotlin: Remove debug logic
svix-mman Feb 13, 2025
e29d93e
kotlin: Enable tests in CI
svix-mman Feb 13, 2025
3d8a211
Fix typo
svix-mman Feb 13, 2025
c854ec7
kotlin: Add `messageInRaw`
svix-mman Feb 13, 2025
8751271
kotlin: Document all breaking changes
svix-mman Feb 13, 2025
cddfe67
kotlin: Fix `messageInRaw`
svix-mman Feb 13, 2025
322d6d1
kotlin: Ensure version is set correctly
svix-mman Feb 13, 2025
9b7018d
kotlin: This is the last undocumented breaking change
svix-mman Feb 13, 2025
1cb6cce
kotlin: Add serializer for Map<String,Any>
svix-mman Feb 13, 2025
fd33a08
kotlin: Swap `JsonObject` with `Map<String,Any>`
svix-mman Feb 13, 2025
0fe74e5
kotlin: This is no longer changed
svix-mman Feb 13, 2025
1062b25
kotlin: Document this breaking change
svix-mman Feb 13, 2025
4e2ae31
kotlin: Add test for MaybeUnset<Map<String,Any>>
svix-mman Feb 13, 2025
20d93eb
kotlin: Add test for _very_ nested json
svix-mman Feb 13, 2025
9ca39f1
kotlin: Document `MaybeUnset`
svix-mman Feb 13, 2025
7fcd6b3
kotlin: Break this test to show that it does something
svix-mman Feb 13, 2025
d74c98d
kotlin: Now tests pass
svix-mman Feb 13, 2025
6898019
kotlin: Show full logs if tests fail
svix-mman Feb 13, 2025
b83216d
kotlin: Remove openapi-generator config for kotlin
svix-mman Feb 13, 2025
7e2078b
kotlin: Add doc comments to *Options fields
svix-mman Feb 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .github/workflows/kotlin-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,7 @@ jobs:
distribution: 'temurin'
java-version: '11'

- name: Regen openapi libs
run: |
yarn
./regen_openapi.sh

- name: Build
run: |
cd kotlin
./gradlew build -x test
./gradlew build
svix-mman marked this conversation as resolved.
Show resolved Hide resolved
16 changes: 9 additions & 7 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
# Changelog

## Unreleased

* Libs/Kotlin **(VERY IMPORTANT)**: The parameter order `appId` and `msgId` were swapped on `Message.get` and `Message.expungeContent`
* Libs/C#, Libs/Go and Libs/Kotlin **(Breaking)**: All uses of `ListOptions`/`PostOptions` are removed, and renamed to `{Resource}{Operation}Options`. For example in `Endpoint.List` you would now use `EndpointListOptions`
* Libs/Kotlin **(Breaking)**: In the 4 `*Patch` patch models, nullable fields are of type `MaybeUnset<T>` instead of `T`. call `MaybeUnset.Present(val)` to initialize this value
* Libs/Kotlin **(Breaking)**: `SvixOptions` no longer has `initialRetryDelayMillis` or `numRetries` instead use `retrySchedule`
* Libs/Kotlin **(Breaking)**: All `{Resource}{Operation}Options` and model classes (`ApplicationIn`/`MessageOut`) are now data classes
* Libs/Kotlin **(Breaking)**: Deprecated functions `MessageAttempt.list` and `MessageAttempt.listAttemptsForEndpoint` are removed
* Libs/Kotlin **(Breaking)**: All uses of `java.time.OffsetDateTime` replaced with `kotlinx.datetime.Instant`
* Libs/Kotlin **(Breaking)**: All uses of `java.net.URL` in request/response models are replaced with `String`
svix-mman marked this conversation as resolved.
Show resolved Hide resolved
* Libs/Go: Add `Authentication.ExpireAll` (and `ExpireAllWithOptions`)
* Libs/Go **(Breaking)**: Excluding specific fields on the *Patch models (`ApplicationPatch` for example), all `Nullable{Type}` removed from the models
* Libs/Go **(Breaking)**: All `Nullable{Type}` (for example `NullableString`) are replaced with a new generic `Nullable[T]` type, the new type can be imported from `github.com/svix/svix-webhooks/go/utils`
* Libs/Go **(Breaking)**: All custom model types are now imported from `github.com/svix/svix-webhooks/go/models` instead of `github.com/svix/svix-webhooks/go`
* Libs/Go **(Breaking)**: All `-WithOptions` methods are now removed. Their regular counterparts now take a pointer to an Options type which can be nil when not needed. For example in `Endpoint.RecoverWithOptions` is now `Endpoint.Recover`
* Libs/C# and Libs/Go **(Breaking)**: All uses of `ListOptions`/`PostOptions` are removed, and renamed to `{Resource}{Operation}Options`. For example in `Endpoint.List` you would now use `EndpointListOptions`
* Libs/C# **(Breaking)**: All `IdempotencyKey` method parameters are removed, and are now part of `{Resource}{Operation}Options`. For example in `Message.Create`; to the use `IdempotencyKey`, simply pass it in the `MessageCreateOptions`
* Libs/C# **(Breaking)**: The `Throw` parameter is removed from `SvixOptions`
* Libs/C# **(Breaking)**: All redundant interfaces along with the `Svix.Abstractions` namespace are removed
Expand All @@ -17,15 +25,9 @@
* Libs/Python **(Breaking)**: `EndpointStatsOptions` is renamed to `EndpointGetStatsOptions`
* Libs/Python **(Breaking)**: `MessageAttemptListOptions` is removed in favor of call specific `{Resource}{Operation}Options`
* Libs/Python **(Breaking)**: For `Statistics` in the `aggregate_event_types` method the `task_id` parameter is removed, Please note that previously this parameter was ignored and had no affect (Both sync and async)
* Libs/Kotlin **(Breaking)**: Mark `api` field of all API resource classes as `private` (previously
only some were private, accidentally)
* Libs/Kotlin **(Breaking)**: Update `recover` to return `RecoverOut` (instead of nothing)
* Libs/Kotlin **(Breaking)**: Update `replayMissing` to return `ReplayOut` (instead of nothing)
* Libs/Kotlin **(Breaking)**: Update `sendExample` to return `MessageOut` (instead of nothing)
* Libs/Kotlin **(Breaking)**: Update `MessageAttempt` list methods to each have its own type for
list options, since they don't all support the exact same set of parameters and some of the
parameters that could be set before would just get ignored
* Libs/Kotlin: Fix the parameter names of `Endpoint.get` - `appId` and `endpointId` were swapped
* Libs/Kotlin: Fix a bug in `EventType.list` where `options.order` was not getting honored
* Libs/Rust **(Breaking)**: Add optional `EventTypeDeleteOptions` parameter to `EventType::delete`
* Libs/Rust **(Breaking)**: Add optional `options` parameters to `Endpoint::recover`,
Expand Down
37 changes: 25 additions & 12 deletions kotlin/build.gradle
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
group GROUP
version VERSION_NAME

wrapper {
gradleVersion = '8.7'
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
}

buildscript {
ext.kotlin_version = '1.9.23'
ext.kotlin_version = '2.1.10'
ext.spotless_version = "6.25.0"

repositories {
Expand All @@ -21,6 +13,21 @@ buildscript {
}
}

plugins {
id 'org.jetbrains.kotlin.jvm' version '2.1.10'
id 'org.jetbrains.kotlin.plugin.serialization' version '2.1.10'
}

group GROUP
version VERSION_NAME


wrapper {
gradleVersion = '8.7'
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
}


apply plugin: 'kotlin'
apply plugin: 'com.diffplug.spotless'

Expand All @@ -30,23 +37,29 @@ repositories {

sourceSets {
main.kotlin.srcDirs += 'lib/src/main/kotlin'
main.kotlin.srcDirs += 'lib/generated/openapi/src/main/kotlin'
// main.kotlin.srcDirs += 'lib/generated/openapi/src/main/kotlin'
sourceSets.test.kotlin.srcDirs = ["lib/src/test/main/kotlin"]
test.kotlin.srcDirs = ['lib/src/test']
}

test {
useJUnitPlatform()
testLogging {
events "failed"
exceptionFormat "full"
}
}

dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-datetime:0.6.2'
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.8.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2"
implementation "com.squareup.moshi:moshi-kotlin:1.12.0"
implementation "com.squareup.okhttp3:okhttp:4.9.1"
implementation "com.squareup.okhttp3:okhttp:4.12.0"
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.jetbrains.kotlin:kotlin-test-junit5:1.5.21'
testImplementation "org.wiremock:wiremock:3.12.0"
}

jar {
Expand Down
2 changes: 0 additions & 2 deletions kotlin/deploy.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,10 @@ nexusPublishing {
}

task sourcesJar(type: Jar) {
classifier = "sources"
from sourceSets.main.allSource
}

task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = "javadoc"
from javadoc.destinationDir
}

Expand Down
Binary file modified kotlin/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
4 changes: 2 additions & 2 deletions kotlin/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStorePath=wrapper/dists
23 changes: 0 additions & 23 deletions kotlin/lib/generated/openapi/.openapi-generator-ignore

This file was deleted.

121 changes: 59 additions & 62 deletions kotlin/lib/src/main/kotlin/Application.kt
Original file line number Diff line number Diff line change
@@ -1,106 +1,103 @@
// this file is @generated (with minor manual changes)
// this file is @generated
package com.svix.kotlin

import com.svix.kotlin.exceptions.ApiException
import com.svix.kotlin.internal.apis.ApplicationApi
import com.svix.kotlin.models.ApplicationIn
import com.svix.kotlin.models.ApplicationOut
import com.svix.kotlin.models.ApplicationPatch
import com.svix.kotlin.models.ListResponseApplicationOut
import com.svix.kotlin.models.Ordering
import okhttp3.Headers

class ApplicationListOptions {
var limit: Int? = null
var iterator: String? = null
var order: Ordering? = null
data class ApplicationListOptions(
val limit: ULong? = null,
val iterator: String? = null,
val order: Ordering? = null,
)

/** Limit the number of returned items */
fun limit(limit: Int) = apply { this.limit = limit }
data class ApplicationCreateOptions(val idempotencyKey: String? = null)

/** The iterator returned from a prior invocation */
fun iterator(iterator: String) = apply { this.iterator = iterator }

/** The sorting order of the returned items */
fun order(order: Ordering) = apply { this.order = order }
}

class Application internal constructor(token: String, options: SvixOptions) {
svix-mman marked this conversation as resolved.
Show resolved Hide resolved
private val api = ApplicationApi(options.serverUrl)

init {
api.accessToken = token
api.userAgent = options.getUA()
options.initialRetryDelayMillis?.let { api.initialRetryDelayMillis = it }
options.numRetries?.let { api.numRetries = it }
}
class Application(private val client: SvixHttpClient) {

/** List of all the organization's applications. */
suspend fun list(
options: ApplicationListOptions = ApplicationListOptions()
): ListResponseApplicationOut {
try {
return api.v1ApplicationList(options.limit, options.iterator, options.order)
} catch (e: Exception) {
throw ApiException.wrap(e)
}
val url = client.newUrlBuilder().encodedPath("/api/v1/app")
options.limit?.let { url.addQueryParameter("limit", serializeQueryParam(it)) }
options.iterator?.let { url.addQueryParameter("iterator", it) }
options.order?.let { url.addQueryParameter("order", serializeQueryParam(it)) }
return client.executeRequest<Any, ListResponseApplicationOut>("GET", url.build())
}

/** Create a new application. */
suspend fun create(
applicationIn: ApplicationIn,
options: PostOptions = PostOptions(),
options: ApplicationCreateOptions = ApplicationCreateOptions(),
): ApplicationOut {
try {
return api.v1ApplicationCreate(applicationIn, null, options.idempotencyKey)
} catch (e: Exception) {
throw ApiException.wrap(e)
}
val url = client.newUrlBuilder().encodedPath("/api/v1/app")
val headers = Headers.Builder()
options.idempotencyKey?.let { headers.add("idempotency-key", it) }

return client.executeRequest<ApplicationIn, ApplicationOut>(
"POST",
url.build(),
headers = headers.build(),
reqBody = applicationIn,
)
}

/** Get or create an application. */
suspend fun getOrCreate(
applicationIn: ApplicationIn,
options: PostOptions = PostOptions(),
options: ApplicationCreateOptions = ApplicationCreateOptions(),
): ApplicationOut {
try {
return api.v1ApplicationCreate(applicationIn, true, options.idempotencyKey)
} catch (e: Exception) {
throw ApiException.wrap(e)
}
val url =
client
.newUrlBuilder()
.encodedPath("/api/v1/app")
.addQueryParameter("get_if_exists", "true")
var headers = Headers.Builder()
options.idempotencyKey?.let { headers = headers.add("idempotency-key", it) }

return client.executeRequest<ApplicationIn, ApplicationOut>(
"POST",
url.build(),
headers = headers.build(),
reqBody = applicationIn,
)
}

/** Get an application. */
suspend fun get(appId: String): ApplicationOut {
try {
return api.v1ApplicationGet(appId)
} catch (e: Exception) {
throw ApiException.wrap(e)
}
val url = client.newUrlBuilder().encodedPath("/api/v1/app/$appId")
return client.executeRequest<Any, ApplicationOut>("GET", url.build())
}

/** Update an application. */
suspend fun update(appId: String, applicationIn: ApplicationIn): ApplicationOut {
try {
return api.v1ApplicationUpdate(appId, applicationIn)
} catch (e: Exception) {
throw ApiException.wrap(e)
}
val url = client.newUrlBuilder().encodedPath("/api/v1/app/$appId")

return client.executeRequest<ApplicationIn, ApplicationOut>(
"PUT",
url.build(),
reqBody = applicationIn,
)
}

/** Delete an application. */
suspend fun delete(appId: String) {
try {
api.v1ApplicationDelete(appId)
} catch (e: Exception) {
throw ApiException.wrap(e)
}
val url = client.newUrlBuilder().encodedPath("/api/v1/app/$appId")
client.executeRequest<Any, Boolean>("DELETE", url.build())
}

/** Partially update an application. */
suspend fun patch(appId: String, applicationPatch: ApplicationPatch): ApplicationOut {
try {
return api.v1ApplicationPatch(appId, applicationPatch)
} catch (e: Exception) {
throw ApiException.wrap(e)
}
val url = client.newUrlBuilder().encodedPath("/api/v1/app/$appId")

return client.executeRequest<ApplicationPatch, ApplicationOut>(
"PATCH",
url.build(),
reqBody = applicationPatch,
)
}
}
Loading
Loading