From 54cf128e68841879b4ce5917e05d5eb2d884a840 Mon Sep 17 00:00:00 2001 From: geisterfurz007 Date: Sun, 22 Oct 2023 14:19:04 +0200 Subject: [PATCH] refactor: share code between kotlin and android --- src/SDK/Language/Android.php | 36 +++++++--- .../src/main/java/io/appwrite/ID.kt.twig | 10 --- .../main/java/io/appwrite/Permission.kt.twig | 21 ------ .../src/main/java/io/appwrite/Query.kt.twig | 60 ---------------- .../src/main/java/io/appwrite/Role.kt.twig | 72 ------------------- .../io/appwrite/services/ServiceTest.kt.twig | 2 - .../main/kotlin/io/appwrite/Client.kt.twig | 42 ++++++----- .../main/kotlin}/io/appwrite/Response.kt.twig | 0 .../test/kotlin}/io/appwrite/IDTest.kt.twig | 0 .../io/appwrite/PermissionTest.kt.twig | 0 .../kotlin}/io/appwrite/QueryTest.kt.twig | 0 .../test/kotlin}/io/appwrite/RoleTest.kt.twig | 0 .../io/appwrite/cookies/CookiesTest.kt.twig | 2 +- .../io/appwrite/models/ModelTest.kt.twig | 0 14 files changed, 53 insertions(+), 192 deletions(-) delete mode 100644 templates/android/library/src/main/java/io/appwrite/ID.kt.twig delete mode 100644 templates/android/library/src/main/java/io/appwrite/Permission.kt.twig delete mode 100644 templates/android/library/src/main/java/io/appwrite/Query.kt.twig delete mode 100644 templates/android/library/src/main/java/io/appwrite/Role.kt.twig rename templates/{android/library/src/main/java => kotlin/src/main/kotlin}/io/appwrite/Response.kt.twig (100%) rename templates/{android/library/src/test/java => kotlin/src/test/kotlin}/io/appwrite/IDTest.kt.twig (100%) rename templates/{android/library/src/test/java => kotlin/src/test/kotlin}/io/appwrite/PermissionTest.kt.twig (100%) rename templates/{android/library/src/test/java => kotlin/src/test/kotlin}/io/appwrite/QueryTest.kt.twig (100%) rename templates/{android/library/src/test/java => kotlin/src/test/kotlin}/io/appwrite/RoleTest.kt.twig (100%) rename templates/{android/library/src/test/java => kotlin/src/test/kotlin}/io/appwrite/cookies/CookiesTest.kt.twig (96%) rename templates/{android/library/src/test/java => kotlin/src/test/kotlin}/io/appwrite/models/ModelTest.kt.twig (100%) diff --git a/src/SDK/Language/Android.php b/src/SDK/Language/Android.php index e7a92d9fcb..966d1cc089 100644 --- a/src/SDK/Language/Android.php +++ b/src/SDK/Language/Android.php @@ -108,22 +108,42 @@ public function getFiles(): array [ 'scope' => 'default', 'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/Permission.kt', - 'template' => '/android/library/src/main/java/io/appwrite/Permission.kt.twig', + 'template' => '/kotlin/src/main/kotlin/io/appwrite/Permission.kt.twig', + ], + [ + 'scope' => 'default', + 'destination' => '/library/src/test/java/{{ sdk.namespace | caseSlash }}/PermissionTest.kt', + 'template' => '/kotlin/src/test/kotlin/io/appwrite/PermissionTest.kt.twig', ], [ 'scope' => 'default', 'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/Role.kt', - 'template' => '/android/library/src/main/java/io/appwrite/Role.kt.twig', + 'template' => '/kotlin/src/main/kotlin/io/appwrite/Role.kt.twig', + ], + [ + 'scope' => 'default', + 'destination' => '/library/src/test/java/{{ sdk.namespace | caseSlash }}/RoleTest.kt', + 'template' => '/kotlin/src/test/kotlin/io/appwrite/RoleTest.kt.twig', ], [ 'scope' => 'default', 'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/ID.kt', - 'template' => '/android/library/src/main/java/io/appwrite/ID.kt.twig', + 'template' => '/kotlin/src/main/kotlin/io/appwrite/ID.kt.twig', + ], + [ + 'scope' => 'default', + 'destination' => '/library/src/test/java/{{ sdk.namespace | caseSlash }}/IDTest.kt', + 'template' => '/kotlin/src/test/kotlin/io/appwrite/IDTest.kt.twig', ], [ 'scope' => 'default', 'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/Query.kt', - 'template' => '/android/library/src/main/java/io/appwrite/Query.kt.twig', + 'template' => '/kotlin/src/main/kotlin/io/appwrite/Query.kt.twig', + ], + [ + 'scope' => 'default', + 'destination' => '/library/src/test/java/{{ sdk.namespace | caseSlash }}/QueryTest.kt', + 'template' => '/kotlin/src/test/kotlin/io/appwrite/QueryTest.kt.twig', ], [ 'scope' => 'default', @@ -178,7 +198,7 @@ public function getFiles(): array [ 'scope' => 'default', 'destination' => '/library/src/main/java/{{ sdk.namespace | caseSlash }}/Response.kt', - 'template' => '/android/library/src/main/java/io/appwrite/Response.kt.twig', + 'template' => '/kotlin/src/main/kotlin/io/appwrite/Response.kt.twig', ], [ 'scope' => 'default', @@ -238,7 +258,7 @@ public function getFiles(): array [ 'scope' => 'default', 'destination' => '/library/src/test/java/{{ sdk.namespace | caseSlash }}/cookies/CookiesTest.kt', - 'template' => '/android/library/src/test/java/io/appwrite/cookies/CookiesTest.kt.twig', + 'template' => '/kotlin/src/test/kotlin/io/appwrite/cookies/CookiesTest.kt.twig', ], [ 'scope' => 'default', @@ -400,12 +420,12 @@ public function getFiles(): array [ 'scope' => 'definition', 'destination' => 'library/src/main/java/io/appwrite/models/{{ definition.name | caseUcfirst }}.kt', - 'template' => '/android/library/src/main/java/io/appwrite/models/Model.kt.twig', + 'template' => '/kotlin/src/main/kotlin/io/appwrite/models/Model.kt.twig', ], [ 'scope' => 'definition', 'destination' => 'library/src/test/java/io/appwrite/models/{{ definition.name | caseUcfirst }}Test.kt', - 'template' => '/android/library/src/test/java/io/appwrite/models/ModelTest.kt.twig', + 'template' => '/kotlin/src/test/kotlin/io/appwrite/models/ModelTest.kt.twig', ], ]; } diff --git a/templates/android/library/src/main/java/io/appwrite/ID.kt.twig b/templates/android/library/src/main/java/io/appwrite/ID.kt.twig deleted file mode 100644 index 3ac3c98b04..0000000000 --- a/templates/android/library/src/main/java/io/appwrite/ID.kt.twig +++ /dev/null @@ -1,10 +0,0 @@ -package {{ sdk.namespace | caseDot }} - -class ID { - companion object { - fun custom(id: String): String - = id - fun unique(): String - = "unique()" - } -} \ No newline at end of file diff --git a/templates/android/library/src/main/java/io/appwrite/Permission.kt.twig b/templates/android/library/src/main/java/io/appwrite/Permission.kt.twig deleted file mode 100644 index 33e5b741c9..0000000000 --- a/templates/android/library/src/main/java/io/appwrite/Permission.kt.twig +++ /dev/null @@ -1,21 +0,0 @@ -package {{ sdk.namespace | caseDot }} - -class Permission { - companion object { - fun read(role: String): String { - return "read(\"${role}\")" - } - fun write(role: String): String { - return "write(\"${role}\")" - } - fun create(role: String): String { - return "create(\"${role}\")" - } - fun update(role: String): String { - return "update(\"${role}\")" - } - fun delete(role: String): String { - return "delete(\"${role}\")" - } - } -} \ No newline at end of file diff --git a/templates/android/library/src/main/java/io/appwrite/Query.kt.twig b/templates/android/library/src/main/java/io/appwrite/Query.kt.twig deleted file mode 100644 index e9c5a9c880..0000000000 --- a/templates/android/library/src/main/java/io/appwrite/Query.kt.twig +++ /dev/null @@ -1,60 +0,0 @@ -package {{ sdk.namespace | caseDot }} - -class Query { - companion object { - fun equal(attribute: String, value: Any) = addQuery(attribute, "equal", value) - - fun notEqual(attribute: String, value: Any) = Query.addQuery(attribute, "notEqual", value) - - fun lessThan(attribute: String, value: Any) = Query.addQuery(attribute, "lessThan", value) - - fun lessThanEqual(attribute: String, value: Any) = Query.addQuery(attribute, "lessThanEqual", value) - - fun greaterThan(attribute: String, value: Any) = Query.addQuery(attribute, "greaterThan", value) - - fun greaterThanEqual(attribute: String, value: Any) = Query.addQuery(attribute, "greaterThanEqual", value) - - fun search(attribute: String, value: String) = Query.addQuery(attribute, "search", value) - - fun isNull(attribute: String) = "isNull(\"${attribute}\")" - - fun isNotNull(attribute: String) = "isNotNull(\"${attribute}\")" - - fun between(attribute: String, start: Int, end: Int) = Query.addQuery(attribute, "between", listOf(start, end)) - - fun between(attribute: String, start: Double, end: Double) = Query.addQuery(attribute, "between", listOf(start, end)) - - fun between(attribute: String, start: String, end: String) = Query.addQuery(attribute, "between", listOf(start, end)) - - fun startsWith(attribute: String, value: String) = Query.addQuery(attribute, "startsWith", value) - - fun endsWith(attribute: String, value: String) = Query.addQuery(attribute, "endsWith", value) - - fun select(attributes: List) = "select([${attributes.joinToString(",") { "\"$it\"" }}])" - - fun orderAsc(attribute: String) = "orderAsc(\"${attribute}\")" - - fun orderDesc(attribute: String) = "orderDesc(\"${attribute}\")" - - fun cursorBefore(documentId: String) = "cursorBefore(\"${documentId}\")" - - fun cursorAfter(documentId: String) = "cursorAfter(\"${documentId}\")" - - fun limit(limit: Int) = "limit(${limit})" - - fun offset(offset: Int) = "offset(${offset})" - - private fun addQuery(attribute: String, method: String, value: Any): String { - return when (value) { - is List<*> -> "${method}(\"${attribute}\", [${value.map{it -> parseValues(it!!)}.joinToString(",")}])" - else -> "${method}(\"${attribute}\", [${Query.parseValues(value)}])" - } - } - private fun parseValues(value: Any): String { - return when (value) { - is String -> "\"${value}\"" - else -> "${value}" - } - } - } -} diff --git a/templates/android/library/src/main/java/io/appwrite/Role.kt.twig b/templates/android/library/src/main/java/io/appwrite/Role.kt.twig deleted file mode 100644 index 2e4de98614..0000000000 --- a/templates/android/library/src/main/java/io/appwrite/Role.kt.twig +++ /dev/null @@ -1,72 +0,0 @@ -package {{ sdk.namespace | caseDot }} - -/** - * Helper class to generate role strings for [Permission]. - */ -class Role { - companion object { - - /** - * Grants access to anyone. - * - * This includes authenticated and unauthenticated users. - */ - fun any(): String = "any" - - /** - * Grants access to a specific user by user ID. - * - * You can optionally pass verified or unverified for - * [status] to target specific types of users. - */ - fun user(id: String, status: String = ""): String = if(status.isEmpty()) { - "user:$id" - } else { - "user:$id/$status" - } - - /** - * Grants access to any authenticated or anonymous user. - * - * You can optionally pass verified or unverified for - * [status] to target specific types of users. - */ - fun users(status: String = ""): String = if(status.isEmpty()) { - "users" - } else { - "users/$status" - } - - /** - * Grants access to any guest user without a session. - * - * Authenticated users don't have access to this role. - */ - fun guests(): String = "guests" - - /** - * Grants access to a team by team ID. - * - * You can optionally pass a role for [role] to target - * team members with the specified role. - */ - fun team(id: String, role: String = ""): String = if(role.isEmpty()) { - "team:$id" - } else { - "team:$id/$role" - } - - /** - * Grants access to a specific member of a team. - * - * When the member is removed from the team, they will - * no longer have access. - */ - fun member(id: String): String = "member:$id" - - /** - * Grants access to a user with the specified label. - */ - fun label(name: String): String = "label:$name" - } -} \ No newline at end of file diff --git a/templates/android/library/src/test/java/io/appwrite/services/ServiceTest.kt.twig b/templates/android/library/src/test/java/io/appwrite/services/ServiceTest.kt.twig index 191f797c93..9b4851688e 100644 --- a/templates/android/library/src/test/java/io/appwrite/services/ServiceTest.kt.twig +++ b/templates/android/library/src/test/java/io/appwrite/services/ServiceTest.kt.twig @@ -16,9 +16,7 @@ import org.junit.Test import org.junit.runner.RunWith import kotlin.test.assertIs -{%~ if method.type == 'webAuth' ~%} @RunWith(AndroidJUnit4::class) -{%~ endif ~%} class {{service.name | caseUcfirst}}ServiceTest { private lateinit var client: Client private lateinit var {{service.name | caseCamel}}: {{service.name | caseUcfirst}} diff --git a/templates/kotlin/src/main/kotlin/io/appwrite/Client.kt.twig b/templates/kotlin/src/main/kotlin/io/appwrite/Client.kt.twig index 7181175ca5..605bd0d05f 100644 --- a/templates/kotlin/src/main/kotlin/io/appwrite/Client.kt.twig +++ b/templates/kotlin/src/main/kotlin/io/appwrite/Client.kt.twig @@ -17,7 +17,6 @@ import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.MediaType.Companion.toMediaType import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.toRequestBody -import okhttp3.logging.HttpLoggingInterceptor import java.io.BufferedInputStream import java.io.BufferedReader import java.io.File @@ -32,6 +31,7 @@ import javax.net.ssl.TrustManager import javax.net.ssl.X509TrustManager import kotlin.coroutines.CoroutineContext import kotlin.coroutines.resume +import okhttp3.Response as Okhttp3Response class Client @JvmOverloads constructor( var endPoint: String = "{{spec.endpoint}}", @@ -67,6 +67,7 @@ class Client @JvmOverloads constructor( "x-sdk-platform" to "{{ sdk.platform }}", "x-sdk-language" to "{{ language.name | caseLower }}", "x-sdk-version" to "{{ sdk.version }}"{% if spec.global.defaultHeaders | length > 0 %},{% endif %} + {% for key,header in spec.global.defaultHeaders %} "{{ key | caseLower }}" to "{{ header }}"{% if not loop.last %},{% endif %} {% endfor %} @@ -108,6 +109,7 @@ class Client @JvmOverloads constructor( val builder = OkHttpClient() .newBuilder() + .cookieJar(JavaNetCookieJar(cookieJar)) if (!selfSigned) { http = builder.build() @@ -225,7 +227,10 @@ class Client @JvmOverloads constructor( .get() .build() - return awaitResponse(request, responseType, converter) + val response = awaitResponse(request, responseType) + + @Suppress("UNCHECKED_CAST") + return converter?.invoke(response.data) ?: response.data as T } val body = if (MultipartBody.FORM.toString() == headers["content-type"]) { @@ -262,7 +267,10 @@ class Client @JvmOverloads constructor( .method(method, body) .build() - return awaitResponse(request, responseType, converter) + val response = awaitResponse(request, responseType) + + @Suppress("UNCHECKED_CAST") + return converter?.invoke(response.data) ?: response.data as T } /** @@ -400,11 +408,10 @@ class Client @JvmOverloads constructor( * @return [T] */ @Throws({{ spec.title | caseUcfirst }}Exception::class) - private suspend fun awaitResponse( + internal suspend fun awaitResponse( request: Request, responseType: Class, - converter: ((Any) -> T)? = null - ) = suspendCancellableCoroutine { + ) = suspendCancellableCoroutine> { http.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { if (it.isCancelled) { @@ -413,23 +420,22 @@ class Client @JvmOverloads constructor( it.cancel(e) } - @Suppress("UNCHECKED_CAST") - override fun onResponse(call: Call, response: Response) { + override fun onResponse(call: Call, response: Okhttp3Response) { if (!response.isSuccessful) { val body = response.body!! .charStream() .buffered() .use(BufferedReader::readText) - + val error = if (response.headers["content-type"]?.contains("application/json") == true) { val map = gson.fromJson>( body, object : TypeToken>(){}.type ) {{ spec.title | caseUcfirst }}Exception( - map["message"] as? String ?: "", + map["message"] as? String ?: "", (map["code"] as Number).toInt(), - map["type"] as? String ?: "", + map["type"] as? String ?: "", body ) } else { @@ -440,19 +446,19 @@ class Client @JvmOverloads constructor( } when { responseType == Boolean::class.java -> { - it.resume(true as T) + it.resume(Response(true)) return } responseType == ByteArray::class.java -> { - it.resume(response.body!! + val data = response.body!! .byteStream() .buffered() - .use(BufferedInputStream::readBytes) as T - ) + .use(BufferedInputStream::readBytes) + it.resume(Response(data)) return } response.body == null -> { - it.resume(true as T) + it.resume(Response(true)) return } } @@ -461,7 +467,7 @@ class Client @JvmOverloads constructor( .buffered() .use(BufferedReader::readText) if (body.isEmpty()) { - it.resume(true as T) + it.resume(Response(true)) return } val map = gson.fromJson>( @@ -469,7 +475,7 @@ class Client @JvmOverloads constructor( object : TypeToken>(){}.type ) it.resume( - converter?.invoke(map) ?: map as T + Response(map) ) } }) diff --git a/templates/android/library/src/main/java/io/appwrite/Response.kt.twig b/templates/kotlin/src/main/kotlin/io/appwrite/Response.kt.twig similarity index 100% rename from templates/android/library/src/main/java/io/appwrite/Response.kt.twig rename to templates/kotlin/src/main/kotlin/io/appwrite/Response.kt.twig diff --git a/templates/android/library/src/test/java/io/appwrite/IDTest.kt.twig b/templates/kotlin/src/test/kotlin/io/appwrite/IDTest.kt.twig similarity index 100% rename from templates/android/library/src/test/java/io/appwrite/IDTest.kt.twig rename to templates/kotlin/src/test/kotlin/io/appwrite/IDTest.kt.twig diff --git a/templates/android/library/src/test/java/io/appwrite/PermissionTest.kt.twig b/templates/kotlin/src/test/kotlin/io/appwrite/PermissionTest.kt.twig similarity index 100% rename from templates/android/library/src/test/java/io/appwrite/PermissionTest.kt.twig rename to templates/kotlin/src/test/kotlin/io/appwrite/PermissionTest.kt.twig diff --git a/templates/android/library/src/test/java/io/appwrite/QueryTest.kt.twig b/templates/kotlin/src/test/kotlin/io/appwrite/QueryTest.kt.twig similarity index 100% rename from templates/android/library/src/test/java/io/appwrite/QueryTest.kt.twig rename to templates/kotlin/src/test/kotlin/io/appwrite/QueryTest.kt.twig diff --git a/templates/android/library/src/test/java/io/appwrite/RoleTest.kt.twig b/templates/kotlin/src/test/kotlin/io/appwrite/RoleTest.kt.twig similarity index 100% rename from templates/android/library/src/test/java/io/appwrite/RoleTest.kt.twig rename to templates/kotlin/src/test/kotlin/io/appwrite/RoleTest.kt.twig diff --git a/templates/android/library/src/test/java/io/appwrite/cookies/CookiesTest.kt.twig b/templates/kotlin/src/test/kotlin/io/appwrite/cookies/CookiesTest.kt.twig similarity index 96% rename from templates/android/library/src/test/java/io/appwrite/cookies/CookiesTest.kt.twig rename to templates/kotlin/src/test/kotlin/io/appwrite/cookies/CookiesTest.kt.twig index 10ab2422aa..99dc6aa99a 100644 --- a/templates/android/library/src/test/java/io/appwrite/cookies/CookiesTest.kt.twig +++ b/templates/kotlin/src/test/kotlin/io/appwrite/cookies/CookiesTest.kt.twig @@ -1,8 +1,8 @@ package {{ sdk.namespace | caseDot }}.cookies import java.net.HttpCookie -import kotlin.test.assertEquals import org.junit.Test +import kotlin.test.assertEquals class CookiesTest { @Test diff --git a/templates/android/library/src/test/java/io/appwrite/models/ModelTest.kt.twig b/templates/kotlin/src/test/kotlin/io/appwrite/models/ModelTest.kt.twig similarity index 100% rename from templates/android/library/src/test/java/io/appwrite/models/ModelTest.kt.twig rename to templates/kotlin/src/test/kotlin/io/appwrite/models/ModelTest.kt.twig