diff --git a/src/SDK/Language/Kotlin.php b/src/SDK/Language/Kotlin.php index 80be2e7075..0ee1fae191 100644 --- a/src/SDK/Language/Kotlin.php +++ b/src/SDK/Language/Kotlin.php @@ -236,7 +236,7 @@ public function getParamExample(Schema|Parameter $param, string $lang = 'kotlin' if ($this->isPermissionString($example)) { $output .= $this->getPermissionExample($example, $lang); } else { - $output .= $this->getArrayExample($example, $lang); + $output .= $this->getArrayExample($example, $lang, $this->getArrayLeafType($param)); } break; case self::TYPE_BOOLEAN: @@ -337,7 +337,7 @@ protected function getJavaMapExample(array $data, int $indentLevel = 0): string * @param string $example Array example like '[1, 2, 3]' or '[{"key": "value"}]' * @param string $lang Language variant: 'kotlin' or 'java' */ - protected function getArrayExample(string $example, string $lang = 'kotlin'): string + protected function getArrayExample(string $example, string $lang = 'kotlin', ?string $leafType = null): string { // Try to decode as JSON to handle arrays of objects $decoded = json_decode($example, true); @@ -352,7 +352,7 @@ protected function getArrayExample(string $example, string $lang = 'kotlin'): st $arrayItems[] = $lang === 'java' ? $this->getJavaMapExample($item) : $this->getKotlinMapExample($item); } else { // It's a nested array, recursively convert it - $arrayItems[] = $this->getArrayExample(json_encode($item), $lang); + $arrayItems[] = $this->getArrayExample(json_encode($item), $lang, $leafType); } } elseif (is_string($item)) { // Primitive value @@ -361,6 +361,8 @@ protected function getArrayExample(string $example, string $lang = 'kotlin'): st $arrayItems[] = $item ? 'true' : 'false'; } elseif (is_null($item)) { $arrayItems[] = 'null'; + } elseif ((is_int($item) || is_float($item)) && ($leafType === self::TYPE_INTEGER || $leafType === self::TYPE_NUMBER)) { + $arrayItems[] = $this->getNumberLiteral($item, $leafType, $lang); } else { $arrayItems[] = (string)$item; } @@ -382,6 +384,16 @@ protected function getArrayExample(string $example, string $lang = 'kotlin'): st : 'listOf(' . $example . ')'; } + protected function getArrayLeafType(Schema|Parameter $param): ?string + { + $items = $this->getArraySchema($param); + while ($items instanceof ArraySchema) { + $items = $items->items; + } + + return $items instanceof Schema ? $this->getSchemaType($items) : null; + } + /** * Generate permission example for the given language * diff --git a/templates/android/docs/java/example.md.twig b/templates/android/docs/java/example.md.twig index a8882708ca..03c991df64 100644 --- a/templates/android/docs/java/example.md.twig +++ b/templates/android/docs/java/example.md.twig @@ -1,8 +1,13 @@ +{% set examples = [] %} +{% for parameter in (method | parameters('all')) %} +{% set examples = examples | merge([(parameter | enumValues) | length > 0 ? (parameter | javaEnumExample) : (parameter | javaParamExample)]) %} +{% endfor %} ```java import android.util.Log; import {{ sdk.namespace | caseDot }}.Client; import {{ sdk.namespace | caseDot }}.coroutines.CoroutineCallback; +import {{ sdk.namespace | caseDot }}.exceptions.{{ spec.info.title | caseUcfirst }}Exception; {% if (method | parameters('all')) | filter((param) => (param | schemaType) == 'file') | length > 0 %} import {{ sdk.namespace | caseDot }}.models.InputFile; {% endif %} @@ -20,44 +25,41 @@ import {{ sdk.namespace | caseDot }}.enums.{{ (parameter | enumName) | caseUcfir {% endif %} {% endif %} {% endfor %} +{% if 'List.of(' in (examples | join) %} +import java.util.List; +{% endif %} +{% if 'Map.of(' in (examples | join) %} +import java.util.Map; +{% endif %} +{% set schemes = method | securitySchemes %} Client client = new Client(context) - {%~ if [(method | securitySchemes)]|length > 0 %} - .setEndpoint("{{ endpointDocs | raw }}") // Your API Endpoint - {%~ for node in [(method | securitySchemes)] %} - {%~ for key,header in node|keys %} - .set{{header | caseUcfirst}}("{{node[header].extensions['x-appwrite']['demo'] | raw }}"){% if loop.last %};{% endif %} // {{ node[header].description }} - {%~ endfor %} - {%~ endfor %} - {%~ endif %} + .setEndpoint("{{ endpointDocs | raw }}"){% if schemes is empty %};{% endif %} // Your API Endpoint +{% for header in schemes | keys %} + .set{{ header | caseUcfirst }}("{{ schemes[header].extensions['x-appwrite']['demo'] | raw }}"){% if loop.last %};{% endif %} // {{ schemes[header].description }} +{% endfor %} {{ service.name | caseUcfirst }} {{ service.name | caseCamel }} = new {{ service.name | caseUcfirst }}(client); -{{ service.name | caseCamel }}.{{ (method | methodName) | caseCamel }}({% if (method | parameters('all')) | length == 0 %}new CoroutineCallback<>((result, error) -> { - if (error != null) { - error.printStackTrace(); - return; - } - - Log.d("{{ spec.info.title | caseUcfirst }}", result.toString()); -}));{% endif %} - -{% for parameter in (method | parameters('all')) %} - {% if (parameter | enumValues) is not empty %}{{ (parameter | enumName) | caseUcfirst }}.{{ ((parameter | enumKeys)[0] ?? (parameter | enumValues)[0]) | caseEnumKey }}, // {{ parameter.name }} {% if not parameter.required %}(optional){% endif %} -{% else %}{{ parameter | javaParamExample }}, // {{ parameter.name }} {% if not parameter.required %}(optional){% endif %} -{% endif %} -{%~ if loop.last %} - - new CoroutineCallback<>((result, error) -> { - if (error != null) { - error.printStackTrace(); - return; - } +try { + {{ service.name | caseCamel }}.{{ (method | methodName) | caseCamel }}( + {%~ if (method | methodType) == 'webAuth' %} + activity, // activity + {%~ endif %} + {%~ for parameter in (method | parameters('all')) %} + {{ examples[loop.index0] | replace({"\n": "\n "}) | raw }}, // {{ parameter.name }}{% if not parameter.required %} (optional){% endif %} - Log.d("{{ spec.info.title | caseUcfirst }}", result.toString()); - }) -); -{% endif %} + {%~ endfor %} + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } -{% endfor %} + Log.d("{{ spec.info.title | caseUcfirst }}", result.toString()); + }) + ); +} catch ({{ spec.info.title | caseUcfirst }}Exception e) { + e.printStackTrace(); +} ``` diff --git a/templates/android/library/src/main/java/io/package/Channel.kt.twig b/templates/android/library/src/main/java/io/package/Channel.kt.twig index f92fdacc7e..73254afd33 100644 --- a/templates/android/library/src/main/java/io/package/Channel.kt.twig +++ b/templates/android/library/src/main/java/io/package/Channel.kt.twig @@ -61,39 +61,55 @@ class Channel private constructor( override fun toString(): String = segments.joinToString(".") companion object { + @JvmStatic fun database(id: String): Channel<_Database> = Channel(listOf("databases", normalize(id))) + @JvmStatic fun tablesdb(id: String): Channel<_TablesDB> = Channel(listOf("tablesdb", normalize(id))) + @JvmStatic fun bucket(id: String): Channel<_Bucket> = Channel(listOf("buckets", normalize(id))) + @JvmStatic fun execution(id: String): Channel<_Execution> = Channel(listOf("executions", normalize(id))) + @JvmStatic fun function(id: String): Channel<_Func> = Channel(listOf("functions", normalize(id))) + @JvmStatic fun team(id: String): Channel<_Team> = Channel(listOf("teams", normalize(id))) + @JvmStatic fun membership(id: String): Channel<_Membership> = Channel(listOf("memberships", normalize(id))) + @JvmStatic fun presence(id: String): Channel<_Presence> = Channel(listOf("presences", normalize(id))) + @JvmStatic fun account(): String = "account" // Global events + @JvmStatic fun documents(): String = "documents" + @JvmStatic fun rows(): String = "rows" + @JvmStatic fun files(): String = "files" + @JvmStatic fun executions(): String = "executions" + @JvmStatic fun teams(): String = "teams" + @JvmStatic fun memberships(): String = "memberships" + @JvmStatic fun presences(): String = "presences" } } diff --git a/templates/android/library/src/main/java/io/package/ID.kt.twig b/templates/android/library/src/main/java/io/package/ID.kt.twig index e5579f16d2..10c34fd18f 100644 --- a/templates/android/library/src/main/java/io/package/ID.kt.twig +++ b/templates/android/library/src/main/java/io/package/ID.kt.twig @@ -19,6 +19,7 @@ class ID { return hexTimestamp } + @JvmStatic fun custom(id: String): String = id @@ -28,6 +29,8 @@ class ID { * @param padding The number of characters to add to the ID * @returns The unique ID */ + @JvmStatic + @JvmOverloads fun unique(padding: Int = 7): String { val baseId = hexTimestamp() val randomPadding = (1..padding) diff --git a/templates/android/library/src/main/java/io/package/Operator.kt.twig b/templates/android/library/src/main/java/io/package/Operator.kt.twig index 512d78b10d..9d35bebdf0 100644 --- a/templates/android/library/src/main/java/io/package/Operator.kt.twig +++ b/templates/android/library/src/main/java/io/package/Operator.kt.twig @@ -30,6 +30,8 @@ class Operator( fun toJson(): String = toMap().toJson() companion object { + @JvmStatic + @JvmOverloads fun increment(value: Number = 1, max: Number? = null): String { require(!value.toDouble().isNaN() && !value.toDouble().isInfinite()) { "Value cannot be NaN or Infinity" } max?.let { require(!it.toDouble().isNaN() && !it.toDouble().isInfinite()) { "Max cannot be NaN or Infinity" } } @@ -38,6 +40,8 @@ class Operator( return Operator("increment", values).toJson() } + @JvmStatic + @JvmOverloads fun decrement(value: Number = 1, min: Number? = null): String { require(!value.toDouble().isNaN() && !value.toDouble().isInfinite()) { "Value cannot be NaN or Infinity" } min?.let { require(!it.toDouble().isNaN() && !it.toDouble().isInfinite()) { "Min cannot be NaN or Infinity" } } @@ -46,6 +50,8 @@ class Operator( return Operator("decrement", values).toJson() } + @JvmStatic + @JvmOverloads fun multiply(factor: Number, max: Number? = null): String { require(!factor.toDouble().isNaN() && !factor.toDouble().isInfinite()) { "Factor cannot be NaN or Infinity" } max?.let { require(!it.toDouble().isNaN() && !it.toDouble().isInfinite()) { "Max cannot be NaN or Infinity" } } @@ -54,6 +60,8 @@ class Operator( return Operator("multiply", values).toJson() } + @JvmStatic + @JvmOverloads fun divide(divisor: Number, min: Number? = null): String { require(!divisor.toDouble().isNaN() && !divisor.toDouble().isInfinite()) { "Divisor cannot be NaN or Infinity" } min?.let { require(!it.toDouble().isNaN() && !it.toDouble().isInfinite()) { "Min cannot be NaN or Infinity" } } @@ -63,12 +71,15 @@ class Operator( return Operator("divide", values).toJson() } + @JvmStatic fun modulo(divisor: Number): String { require(!divisor.toDouble().isNaN() && !divisor.toDouble().isInfinite()) { "Divisor cannot be NaN or Infinity" } require(divisor.toDouble() != 0.0) { "Divisor cannot be zero" } return Operator("modulo", listOf(divisor)).toJson() } + @JvmStatic + @JvmOverloads fun power(exponent: Number, max: Number? = null): String { require(!exponent.toDouble().isNaN() && !exponent.toDouble().isInfinite()) { "Exponent cannot be NaN or Infinity" } max?.let { require(!it.toDouble().isNaN() && !it.toDouble().isInfinite()) { "Max cannot be NaN or Infinity" } } @@ -77,59 +88,74 @@ class Operator( return Operator("power", values).toJson() } + @JvmStatic fun arrayAppend(values: List): String { return Operator("arrayAppend", values).toJson() } + @JvmStatic fun arrayPrepend(values: List): String { return Operator("arrayPrepend", values).toJson() } + @JvmStatic fun arrayInsert(index: Int, value: Any): String { return Operator("arrayInsert", listOf(index, value)).toJson() } + @JvmStatic fun arrayRemove(value: Any): String { return Operator("arrayRemove", listOf(value)).toJson() } + @JvmStatic fun arrayUnique(): String { return Operator("arrayUnique", emptyList()).toJson() } + @JvmStatic fun arrayIntersect(values: List): String { return Operator("arrayIntersect", values).toJson() } + @JvmStatic fun arrayDiff(values: List): String { return Operator("arrayDiff", values).toJson() } + @JvmStatic + @JvmOverloads fun arrayFilter(condition: Condition, value: Any? = null): String { val values = listOf(condition.value, value) return Operator("arrayFilter", values).toJson() } + @JvmStatic fun stringConcat(value: Any): String { return Operator("stringConcat", listOf(value)).toJson() } + @JvmStatic fun stringReplace(search: String, replace: String): String { return Operator("stringReplace", listOf(search, replace)).toJson() } + @JvmStatic fun toggle(): String { return Operator("toggle", emptyList()).toJson() } + @JvmStatic fun dateAddDays(days: Int): String { return Operator("dateAddDays", listOf(days)).toJson() } + @JvmStatic fun dateSubDays(days: Int): String { return Operator("dateSubDays", listOf(days)).toJson() } + @JvmStatic fun dateSetNow(): String { return Operator("dateSetNow", emptyList()).toJson() } diff --git a/templates/android/library/src/main/java/io/package/Permission.kt.twig b/templates/android/library/src/main/java/io/package/Permission.kt.twig index 3af74e7de0..4b678ac118 100644 --- a/templates/android/library/src/main/java/io/package/Permission.kt.twig +++ b/templates/android/library/src/main/java/io/package/Permission.kt.twig @@ -12,6 +12,7 @@ class Permission { * @param role The role for which to generate the permission. * @returns The read permission string. */ + @JvmStatic fun read(role: String): String { return "read(\"${role}\")" } @@ -25,6 +26,7 @@ class Permission { * @param role The role for which to generate the permission. * @returns The write permission string. */ + @JvmStatic fun write(role: String): String { return "write(\"${role}\")" } @@ -35,6 +37,7 @@ class Permission { * @param role The role for which to generate the permission. * @returns The create permission string. */ + @JvmStatic fun create(role: String): String { return "create(\"${role}\")" } @@ -45,6 +48,7 @@ class Permission { * @param role The role for which to generate the permission. * @returns The update permission string. */ + @JvmStatic fun update(role: String): String { return "update(\"${role}\")" } @@ -55,6 +59,7 @@ class Permission { * @param role The role for which to generate the permission. * @returns The delete permission string. */ + @JvmStatic fun delete(role: String): String { return "delete(\"${role}\")" } diff --git a/templates/android/library/src/main/java/io/package/Query.kt.twig b/templates/android/library/src/main/java/io/package/Query.kt.twig index f080250e88..29f3d376a0 100644 --- a/templates/android/library/src/main/java/io/package/Query.kt.twig +++ b/templates/android/library/src/main/java/io/package/Query.kt.twig @@ -35,6 +35,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun equal(attribute: String, value: Any) = Query("equal", attribute, parseValue(value)).toJson() /** @@ -44,6 +45,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun notEqual(attribute: String, value: Any) = Query("notEqual", attribute, parseValue(value)).toJson() /** @@ -53,6 +55,7 @@ class Query( * @param pattern The regular expression pattern to match. * @returns The query string. */ + @JvmStatic fun regex(attribute: String, pattern: String) = Query("regex", attribute, parseValue(pattern)).toJson() /** @@ -62,6 +65,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun lessThan(attribute: String, value: Any) = Query("lessThan", attribute, parseValue(value)).toJson() /** @@ -71,6 +75,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun lessThanEqual(attribute: String, value: Any) = Query("lessThanEqual", attribute, parseValue(value)).toJson() /** @@ -80,6 +85,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun greaterThan(attribute: String, value: Any) = Query("greaterThan", attribute, parseValue(value)).toJson() /** @@ -89,6 +95,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun greaterThanEqual(attribute: String, value: Any) = Query("greaterThanEqual", attribute, parseValue(value)).toJson() /** @@ -98,6 +105,7 @@ class Query( * @param value The search value to match against. * @returns The query string. */ + @JvmStatic fun search(attribute: String, value: String) = Query("search", attribute, listOf(value)).toJson() /** @@ -106,6 +114,7 @@ class Query( * @param attribute The attribute to filter on. * @returns The query string. */ + @JvmStatic fun isNull(attribute: String) = Query("isNull", attribute).toJson() /** @@ -114,6 +123,7 @@ class Query( * @param attribute The attribute to filter on. * @returns The query string. */ + @JvmStatic fun isNotNull(attribute: String) = Query("isNotNull", attribute).toJson() /** @@ -122,6 +132,7 @@ class Query( * @param attributes The list of attributes that must exist. * @returns The query string. */ + @JvmStatic fun exists(attributes: List) = Query("exists", null, attributes).toJson() /** @@ -130,6 +141,7 @@ class Query( * @param attributes The list of attributes that must not exist. * @returns The query string. */ + @JvmStatic fun notExists(attributes: List) = Query("notExists", null, attributes).toJson() /** @@ -140,6 +152,7 @@ class Query( * @param end The end value of the range. * @returns The query string. */ + @JvmStatic fun between(attribute: String, start: Any, end: Any) = Query("between", attribute, listOf(start, end)).toJson() /** @@ -149,6 +162,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun startsWith(attribute: String, value: String) = Query("startsWith", attribute, listOf(value)).toJson() /** @@ -158,6 +172,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun endsWith(attribute: String, value: String) = Query("endsWith", attribute, listOf(value)).toJson() /** @@ -166,6 +181,7 @@ class Query( * @param attributes The list of attributes to select. * @returns The query string. */ + @JvmStatic fun select(attributes: List) = Query("select", null, attributes).toJson() /** @@ -174,6 +190,7 @@ class Query( * @param attribute The attribute to sort by. * @returns The query string. */ + @JvmStatic fun orderAsc(attribute: String) = Query("orderAsc", attribute).toJson() /** @@ -182,6 +199,7 @@ class Query( * @param attribute The attribute to sort by. * @returns The query string. */ + @JvmStatic fun orderDesc(attribute: String) = Query("orderDesc", attribute).toJson() /** @@ -189,6 +207,7 @@ class Query( * * @returns The query string. */ + @JvmStatic fun orderRandom() = Query("orderRandom").toJson() /** @@ -197,6 +216,7 @@ class Query( * @param documentId The document ID to use as cursor. * @returns The query string. */ + @JvmStatic fun cursorBefore(documentId: String) = Query("cursorBefore", null, listOf(documentId)).toJson() /** @@ -205,6 +225,7 @@ class Query( * @param documentId The document ID to use as cursor. * @returns The query string. */ + @JvmStatic fun cursorAfter(documentId: String) = Query("cursorAfter", null, listOf(documentId)).toJson() /** @@ -213,6 +234,7 @@ class Query( * @param limit The number of results to return. * @returns The query string. */ + @JvmStatic fun limit(limit: Int) = Query("limit", null, listOf(limit)).toJson() /** @@ -221,6 +243,7 @@ class Query( * @param offset The number of results to skip. * @returns The query string. */ + @JvmStatic fun offset(offset: Int) = Query("offset", null, listOf(offset)).toJson() /** @@ -232,6 +255,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun contains(attribute: String, value: Any) = Query("contains", attribute, parseValue(value)).toJson() /** @@ -243,6 +267,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun containsAny(attribute: String, value: List) = Query("containsAny", attribute, value).toJson() /** @@ -254,6 +279,7 @@ class Query( * @param value The values to match against. * @returns The query string. */ + @JvmStatic fun containsAll(attribute: String, value: List) = Query("containsAll", attribute, value).toJson() /** @@ -263,6 +289,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun notContains(attribute: String, value: Any) = Query("notContains", attribute, parseValue(value)).toJson() /** @@ -272,6 +299,7 @@ class Query( * @param value The search value to match against. * @returns The query string. */ + @JvmStatic fun notSearch(attribute: String, value: String) = Query("notSearch", attribute, listOf(value)).toJson() /** @@ -282,6 +310,7 @@ class Query( * @param end The end value of the range. * @returns The query string. */ + @JvmStatic fun notBetween(attribute: String, start: Any, end: Any) = Query("notBetween", attribute, listOf(start, end)).toJson() /** @@ -291,6 +320,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun notStartsWith(attribute: String, value: String) = Query("notStartsWith", attribute, listOf(value)).toJson() /** @@ -300,6 +330,7 @@ class Query( * @param value The value to compare against. * @returns The query string. */ + @JvmStatic fun notEndsWith(attribute: String, value: String) = Query("notEndsWith", attribute, listOf(value)).toJson() /** @@ -308,6 +339,7 @@ class Query( * @param value The date value to compare against. * @returns The query string. */ + @JvmStatic fun createdBefore(value: String) = lessThan("\$createdAt", value) /** @@ -316,6 +348,7 @@ class Query( * @param value The date value to compare against. * @returns The query string. */ + @JvmStatic fun createdAfter(value: String) = greaterThan("\$createdAt", value) /** @@ -325,6 +358,7 @@ class Query( * @param end The end date value. * @returns The query string. */ + @JvmStatic fun createdBetween(start: String, end: String) = between("\$createdAt", start, end) /** @@ -333,6 +367,7 @@ class Query( * @param value The date value to compare against. * @returns The query string. */ + @JvmStatic fun updatedBefore(value: String) = lessThan("\$updatedAt", value) /** @@ -341,6 +376,7 @@ class Query( * @param value The date value to compare against. * @returns The query string. */ + @JvmStatic fun updatedAfter(value: String) = greaterThan("\$updatedAt", value) /** @@ -350,6 +386,7 @@ class Query( * @param end The end date value. * @returns The query string. */ + @JvmStatic fun updatedBetween(start: String, end: String) = between("\$updatedAt", start, end) /** @@ -358,6 +395,7 @@ class Query( * @param queries The list of query strings to combine. * @returns The query string. */ + @JvmStatic fun or(queries: List) = Query("or", null, queries.map { it.fromJson>() }).toJson() /** @@ -366,6 +404,7 @@ class Query( * @param queries The list of query strings to combine. * @returns The query string. */ + @JvmStatic fun and(queries: List) = Query("and", null, queries.map { it.fromJson>() }).toJson() /** @@ -375,6 +414,7 @@ class Query( * @param queries The list of query strings to match against array elements. * @returns The query string. */ + @JvmStatic fun elemMatch(attribute: String, queries: List) = Query("elemMatch", attribute, queries.map { it.fromJson>() }).toJson() /** @@ -384,6 +424,7 @@ class Query( * @param queries Filter, order, select, and pagination queries applied to related documents. * @returns The query string. */ + @JvmStatic fun relationship(attribute: String, queries: List) = Query("relationship", attribute, queries.map { it.fromJson>() }).toJson() /** @@ -395,6 +436,8 @@ class Query( * @param meters Whether the distance is in meters. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun distanceEqual(attribute: String, values: List, distance: Number, meters: Boolean = true) = Query("distanceEqual", attribute, listOf(listOf(values, distance, meters))).toJson() /** @@ -406,6 +449,8 @@ class Query( * @param meters Whether the distance is in meters. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun distanceNotEqual(attribute: String, values: List, distance: Number, meters: Boolean = true) = Query("distanceNotEqual", attribute, listOf(listOf(values, distance, meters))).toJson() /** @@ -417,6 +462,8 @@ class Query( * @param meters Whether the distance is in meters. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun distanceGreaterThan(attribute: String, values: List, distance: Number, meters: Boolean = true) = Query("distanceGreaterThan", attribute, listOf(listOf(values, distance, meters))).toJson() /** @@ -428,6 +475,8 @@ class Query( * @param meters Whether the distance is in meters. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun distanceLessThan(attribute: String, values: List, distance: Number, meters: Boolean = true) = Query("distanceLessThan", attribute, listOf(listOf(values, distance, meters))).toJson() /** @@ -437,6 +486,7 @@ class Query( * @param vector The query vector. * @returns The query string. */ + @JvmStatic fun vectorDot(attribute: String, vector: List) = Query("vectorDot", attribute, listOf(vector)).toJson() /** @@ -446,6 +496,7 @@ class Query( * @param vector The query vector. * @returns The query string. */ + @JvmStatic fun vectorCosine(attribute: String, vector: List) = Query("vectorCosine", attribute, listOf(vector)).toJson() /** @@ -455,6 +506,7 @@ class Query( * @param vector The query vector. * @returns The query string. */ + @JvmStatic fun vectorEuclidean(attribute: String, vector: List) = Query("vectorEuclidean", attribute, listOf(vector)).toJson() /** @@ -464,6 +516,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun intersects(attribute: String, values: List) = Query("intersects", attribute, listOf(values)).toJson() /** @@ -473,6 +526,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun notIntersects(attribute: String, values: List) = Query("notIntersects", attribute, listOf(values)).toJson() /** @@ -482,6 +536,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun crosses(attribute: String, values: List) = Query("crosses", attribute, listOf(values)).toJson() /** @@ -491,6 +546,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun notCrosses(attribute: String, values: List) = Query("notCrosses", attribute, listOf(values)).toJson() /** @@ -500,6 +556,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun overlaps(attribute: String, values: List) = Query("overlaps", attribute, listOf(values)).toJson() /** @@ -509,6 +566,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun notOverlaps(attribute: String, values: List) = Query("notOverlaps", attribute, listOf(values)).toJson() /** @@ -518,6 +576,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun touches(attribute: String, values: List) = Query("touches", attribute, listOf(values)).toJson() /** @@ -527,6 +586,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun notTouches(attribute: String, values: List) = Query("notTouches", attribute, listOf(values)).toJson() /** @@ -536,6 +596,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun count(attribute: String = "*", alias: String = "") = Query("count", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -545,6 +607,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun countDistinct(attribute: String, alias: String = "") = Query("countDistinct", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -554,6 +618,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun sum(attribute: String, alias: String = "") = Query("sum", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -563,6 +629,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun avg(attribute: String, alias: String = "") = Query("avg", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -572,6 +640,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun min(attribute: String, alias: String = "") = Query("min", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -581,6 +651,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun max(attribute: String, alias: String = "") = Query("max", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -590,6 +662,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun stddev(attribute: String, alias: String = "") = Query("stddev", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -599,6 +673,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun stddevPop(attribute: String, alias: String = "") = Query("stddevPop", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -608,6 +684,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun stddevSamp(attribute: String, alias: String = "") = Query("stddevSamp", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -617,6 +695,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun variance(attribute: String, alias: String = "") = Query("variance", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -626,6 +706,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun varPop(attribute: String, alias: String = "") = Query("varPop", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -635,6 +717,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun varSamp(attribute: String, alias: String = "") = Query("varSamp", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -644,6 +728,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun bitAnd(attribute: String, alias: String = "") = Query("bitAnd", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -653,6 +739,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun bitOr(attribute: String, alias: String = "") = Query("bitOr", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -662,6 +750,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun bitXor(attribute: String, alias: String = "") = Query("bitXor", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -670,6 +760,7 @@ class Query( * @param attributes Attributes to group by. * @returns The query string. */ + @JvmStatic fun groupBy(attributes: List) = Query("groupBy", null, attributes).toJson() /** @@ -678,6 +769,7 @@ class Query( * @param queries Nested query strings. * @returns The query string. */ + @JvmStatic fun having(queries: List) = Query("having", null, queries.map { it.fromJson>() }).toJson() /** @@ -685,6 +777,7 @@ class Query( * * @returns The query string. */ + @JvmStatic fun distinct() = Query("distinct").toJson() /** @@ -695,6 +788,8 @@ class Query( * @param operator Comparison operator. Defaults to `=`. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun on(left: String, right: String, operator: String = "=") = Query("on", values = listOf(left, operator, right)).toJson() /** @@ -707,6 +802,8 @@ class Query( * @param alias Optional table alias. Defaults to the table ID when that is a valid alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun join(table: String, left: String, right: String, operator: String = "=", alias: String = "") = joinQuery("join", table, left, right, operator, alias) /** @@ -716,6 +813,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun join(table: String, on: List) = nestedJoin("join", table, "", on) /** @@ -726,6 +824,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun join(table: String, alias: String, on: List) = nestedJoin("join", table, alias, on) /** @@ -738,6 +837,8 @@ class Query( * @param alias Optional table alias. Defaults to the table ID when that is a valid alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun leftJoin(table: String, left: String, right: String, operator: String = "=", alias: String = "") = joinQuery("leftJoin", table, left, right, operator, alias) /** @@ -747,6 +848,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun leftJoin(table: String, on: List) = nestedJoin("leftJoin", table, "", on) /** @@ -757,6 +859,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun leftJoin(table: String, alias: String, on: List) = nestedJoin("leftJoin", table, alias, on) /** @@ -769,6 +872,8 @@ class Query( * @param alias Optional table alias. Defaults to the table ID when that is a valid alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun rightJoin(table: String, left: String, right: String, operator: String = "=", alias: String = "") = joinQuery("rightJoin", table, left, right, operator, alias) /** @@ -778,6 +883,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun rightJoin(table: String, on: List) = nestedJoin("rightJoin", table, "", on) /** @@ -788,6 +894,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun rightJoin(table: String, alias: String, on: List) = nestedJoin("rightJoin", table, alias, on) /** @@ -800,6 +907,8 @@ class Query( * @param alias Optional table alias. Defaults to the table ID when that is a valid alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun fullOuterJoin(table: String, left: String, right: String, operator: String = "=", alias: String = "") = joinQuery("fullOuterJoin", table, left, right, operator, alias) /** @@ -809,6 +918,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun fullOuterJoin(table: String, on: List) = nestedJoin("fullOuterJoin", table, "", on) /** @@ -819,6 +929,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun fullOuterJoin(table: String, alias: String, on: List) = nestedJoin("fullOuterJoin", table, alias, on) /** @@ -828,6 +939,8 @@ class Query( * @param alias Optional table alias. Defaults to the table ID when that is a valid alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun crossJoin(table: String, alias: String = "") = Query("crossJoin", table, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -837,6 +950,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun covers(attribute: String, values: List) = Query("covers", attribute, listOf(values)).toJson() /** @@ -846,6 +960,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun notCovers(attribute: String, values: List) = Query("notCovers", attribute, listOf(values)).toJson() /** @@ -855,6 +970,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun spatialEquals(attribute: String, values: List) = Query("spatialEquals", attribute, listOf(values)).toJson() /** @@ -864,6 +980,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun notSpatialEquals(attribute: String, values: List) = Query("notSpatialEquals", attribute, listOf(values)).toJson() /** @@ -873,6 +990,8 @@ class Query( * @param perPage Rows per page. Defaults to 25. * @returns Limit and offset query strings. */ + @JvmStatic + @JvmOverloads fun page(page: Int, perPage: Int = 25): List { require(page >= 1) { "Page must be >= 1, got $page" } require(perPage >= 1) { "Per page must be >= 1, got $perPage" } @@ -884,6 +1003,7 @@ class Query( * * @returns A new query builder. */ + @JvmStatic fun builder() = Builder() private fun joinQuery(method: String, table: String, left: String, right: String, operator: String, alias: String): String { diff --git a/templates/android/library/src/main/java/io/package/Role.kt.twig b/templates/android/library/src/main/java/io/package/Role.kt.twig index 8451ef3c7f..fd9cb5c3b3 100644 --- a/templates/android/library/src/main/java/io/package/Role.kt.twig +++ b/templates/android/library/src/main/java/io/package/Role.kt.twig @@ -11,6 +11,7 @@ class Role { * * This includes authenticated and unauthenticated users. */ + @JvmStatic fun any(): String = "any" /** @@ -19,6 +20,8 @@ class Role { * You can optionally pass verified or unverified for * [status] to target specific types of users. */ + @JvmStatic + @JvmOverloads fun user(id: String, status: String = ""): String = if (status.isEmpty()) { "user:$id" } else { @@ -31,6 +34,8 @@ class Role { * You can optionally pass verified or unverified for * [status] to target specific types of users. */ + @JvmStatic + @JvmOverloads fun users(status: String = ""): String = if (status.isEmpty()) { "users" } else { @@ -42,6 +47,7 @@ class Role { * * Authenticated users don't have access to this role. */ + @JvmStatic fun guests(): String = "guests" /** @@ -50,6 +56,8 @@ class Role { * You can optionally pass a role for [role] to target * team members with the specified role. */ + @JvmStatic + @JvmOverloads fun team(id: String, role: String = ""): String = if (role.isEmpty()) { "team:$id" } else { @@ -62,11 +70,13 @@ class Role { * When the member is removed from the team, they will * no longer have access. */ + @JvmStatic fun member(id: String): String = "member:$id" /** * Grants access to a user with the specified label. */ + @JvmStatic fun label(name: String): String = "label:$name" } } diff --git a/templates/android/library/src/main/java/io/package/models/InputFile.kt.twig b/templates/android/library/src/main/java/io/package/models/InputFile.kt.twig index 482a83fd60..d0d105db96 100644 --- a/templates/android/library/src/main/java/io/package/models/InputFile.kt.twig +++ b/templates/android/library/src/main/java/io/package/models/InputFile.kt.twig @@ -12,6 +12,7 @@ class InputFile private constructor() { lateinit var data: Any companion object { + @JvmStatic fun fromFile(file: File) = InputFile().apply { path = file.canonicalPath filename = file.name @@ -19,10 +20,13 @@ class InputFile private constructor() { sourceType = "file" } + @JvmStatic fun fromPath(path: String): InputFile = fromFile(File(path)).apply { sourceType = "path" } + @JvmStatic + @JvmOverloads fun fromBytes(bytes: ByteArray, filename: String = "", mimeType: String = "") = InputFile().apply { this.filename = filename this.mimeType = mimeType diff --git a/templates/android/library/src/main/java/io/package/services/Service.kt.twig b/templates/android/library/src/main/java/io/package/services/Service.kt.twig index 9c31f17ef9..baeca3f913 100644 --- a/templates/android/library/src/main/java/io/package/services/Service.kt.twig +++ b/templates/android/library/src/main/java/io/package/services/Service.kt.twig @@ -52,9 +52,10 @@ class {{ service.name | caseUcfirst }}(client: Client) : Service(client) { ) {%~ endif %} {%~ endif %} - {%~ if (method | parameters('all')) | reduce((carry, param) => carry or not param.required) %} + {%~ if (method | parameters('all')) | reduce((carry, param) => carry or not param.required) or 'multipart/form-data' in (method | consumes) %} @JvmOverloads {%~ endif %} + @Throws({{ spec.info.title | caseUcfirst }}Exception::class) {%~ if allParameters is empty and (method | methodType) != "webAuth" and not ((method | responseModel) | hasGenericType(spec)) and 'multipart/form-data' not in (method | consumes) %} suspend fun {{ (method | methodName) | caseCamel }}(): {{ method | returnType(spec, sdk.namespace | caseDot) | raw }} { {%~ else %} @@ -279,7 +280,7 @@ class {{ service.name | caseUcfirst }}(client: Client) : Service(client) { ) {%~ endif %} {%~ endif %} - {%~ if (method | parameters('all')) | reduce((carry, param) => carry or not param.required) %} + {%~ if (method | parameters('all')) | reduce((carry, param) => carry or not param.required) or 'multipart/form-data' in (method | consumes) %} @JvmOverloads {%~ endif %} @Throws({{ spec.info.title | caseUcfirst }}Exception::class) diff --git a/templates/kotlin/docs/java/example.md.twig b/templates/kotlin/docs/java/example.md.twig index a192b2652f..ecfaae159b 100644 --- a/templates/kotlin/docs/java/example.md.twig +++ b/templates/kotlin/docs/java/example.md.twig @@ -1,6 +1,11 @@ +{% set examples = [] %} +{% for parameter in (method | parameters('all')) %} +{% set examples = examples | merge([(parameter | enumValues) | length > 0 ? (parameter | javaEnumExample) : (parameter | javaParamExample)]) %} +{% endfor %} ```java import {{ sdk.namespace | caseDot }}.Client; import {{ sdk.namespace | caseDot }}.coroutines.CoroutineCallback; +import {{ sdk.namespace | caseDot }}.exceptions.{{ spec.info.title | caseUcfirst }}Exception; {% if (method | parameters('all')) | filter((param) => (param | schemaType) == 'file') | length > 0 %} import {{ sdk.namespace | caseDot }}.models.InputFile; {% endif %} @@ -18,40 +23,38 @@ import {{ sdk.namespace | caseDot }}.enums.{{ (parameter | enumName) | caseUcfir {% endif %} {% endif %} {% endfor %} +{% if 'List.of(' in (examples | join) %} +import java.util.List; +{% endif %} +{% if 'Map.of(' in (examples | join) %} +import java.util.Map; +{% endif %} +{% set schemes = method | securitySchemes %} Client client = new Client() -{% if [(method | securitySchemes)]|length > 0 %} - .setEndpoint("{{ endpointDocs | raw }}") // Your API Endpoint -{% for node in [(method | securitySchemes)] %} -{% for key,header in node|keys %} - .set{{header | caseUcfirst}}("{{node[header].extensions['x-appwrite']['demo'] | raw }}"){% if loop.last %};{% endif %} // {{node[header].description}} -{% endfor %}{% endfor %}{% endif %} + .setEndpoint("{{ endpointDocs | raw }}"){% if schemes is empty %};{% endif %} // Your API Endpoint +{% for header in schemes | keys %} + .set{{ header | caseUcfirst }}("{{ schemes[header].extensions['x-appwrite']['demo'] | raw }}"){% if loop.last %};{% endif %} // {{ schemes[header].description }} +{% endfor %} {{ service.name | caseUcfirst }} {{ service.name | caseCamel }} = new {{ service.name | caseUcfirst }}(client); -{{ service.name | caseCamel }}.{{ (method | methodName) | caseCamel }}({% if (method | parameters('all')) | length == 0 %}new CoroutineCallback<>((result, error) -> { - if (error != null) { - error.printStackTrace(); - return; - } - - System.out.println(result); -}));{% endif %} - +try { + {{ service.name | caseCamel }}.{{ (method | methodName) | caseCamel }}( {%~ for parameter in (method | parameters('all')) %} - {% if (parameter | enumValues) | length > 0%}{{ parameter | javaEnumExample }}{% else %}{{ parameter | javaParamExample }}{% endif %}, // {{ parameter.name }}{% if not parameter.required %} (optional){% endif %} - {%~ if loop.last %} - - new CoroutineCallback<>((result, error) -> { - if (error != null) { - error.printStackTrace(); - return; - } - - System.out.println(result); - }) -); -{% endif %} - -{% endfor %} + {{ examples[loop.index0] | replace({"\n": "\n "}) | raw }}, // {{ parameter.name }}{% if not parameter.required %} (optional){% endif %} + + {%~ endfor %} + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + System.out.println(result); + }) + ); +} catch ({{ spec.info.title | caseUcfirst }}Exception e) { + e.printStackTrace(); +} ``` diff --git a/templates/kotlin/src/main/kotlin/io/appwrite/ID.kt.twig b/templates/kotlin/src/main/kotlin/io/appwrite/ID.kt.twig index a9b59a825a..6ccbde2961 100644 --- a/templates/kotlin/src/main/kotlin/io/appwrite/ID.kt.twig +++ b/templates/kotlin/src/main/kotlin/io/appwrite/ID.kt.twig @@ -18,9 +18,12 @@ class ID { return hexTimestamp } + @JvmStatic fun custom(id: String): String = id // Generate a unique ID with padding to have a longer ID + @JvmStatic + @JvmOverloads fun unique(padding: Int = 7): String { val baseId = ID.hexTimestamp() val randomPadding = (1..padding) diff --git a/templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig b/templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig index a58312f433..91d6388cbd 100644 --- a/templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig +++ b/templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig @@ -23,6 +23,8 @@ class Operator( override fun toString() = this.toJson() companion object { + @JvmStatic + @JvmOverloads fun increment(value: Number = 1, max: Number? = null): String { require(!value.toDouble().isNaN() && !value.toDouble().isInfinite()) { "Value cannot be NaN or Infinity" } max?.let { require(!it.toDouble().isNaN() && !it.toDouble().isInfinite()) { "Max cannot be NaN or Infinity" } } @@ -31,6 +33,8 @@ class Operator( return Operator("increment", values).toJson() } + @JvmStatic + @JvmOverloads fun decrement(value: Number = 1, min: Number? = null): String { require(!value.toDouble().isNaN() && !value.toDouble().isInfinite()) { "Value cannot be NaN or Infinity" } min?.let { require(!it.toDouble().isNaN() && !it.toDouble().isInfinite()) { "Min cannot be NaN or Infinity" } } @@ -39,6 +43,8 @@ class Operator( return Operator("decrement", values).toJson() } + @JvmStatic + @JvmOverloads fun multiply(factor: Number, max: Number? = null): String { require(!factor.toDouble().isNaN() && !factor.toDouble().isInfinite()) { "Factor cannot be NaN or Infinity" } max?.let { require(!it.toDouble().isNaN() && !it.toDouble().isInfinite()) { "Max cannot be NaN or Infinity" } } @@ -47,6 +53,8 @@ class Operator( return Operator("multiply", values).toJson() } + @JvmStatic + @JvmOverloads fun divide(divisor: Number, min: Number? = null): String { require(!divisor.toDouble().isNaN() && !divisor.toDouble().isInfinite()) { "Divisor cannot be NaN or Infinity" } min?.let { require(!it.toDouble().isNaN() && !it.toDouble().isInfinite()) { "Min cannot be NaN or Infinity" } } @@ -56,12 +64,15 @@ class Operator( return Operator("divide", values).toJson() } + @JvmStatic fun modulo(divisor: Number): String { require(!divisor.toDouble().isNaN() && !divisor.toDouble().isInfinite()) { "Divisor cannot be NaN or Infinity" } require(divisor.toDouble() != 0.0) { "Divisor cannot be zero" } return Operator("modulo", listOf(divisor)).toJson() } + @JvmStatic + @JvmOverloads fun power(exponent: Number, max: Number? = null): String { require(!exponent.toDouble().isNaN() && !exponent.toDouble().isInfinite()) { "Exponent cannot be NaN or Infinity" } max?.let { require(!it.toDouble().isNaN() && !it.toDouble().isInfinite()) { "Max cannot be NaN or Infinity" } } @@ -70,59 +81,74 @@ class Operator( return Operator("power", values).toJson() } + @JvmStatic fun arrayAppend(values: List): String { return Operator("arrayAppend", values).toJson() } + @JvmStatic fun arrayPrepend(values: List): String { return Operator("arrayPrepend", values).toJson() } + @JvmStatic fun arrayInsert(index: Int, value: Any): String { return Operator("arrayInsert", listOf(index, value)).toJson() } + @JvmStatic fun arrayRemove(value: Any): String { return Operator("arrayRemove", listOf(value)).toJson() } + @JvmStatic fun arrayUnique(): String { return Operator("arrayUnique", emptyList()).toJson() } + @JvmStatic fun arrayIntersect(values: List): String { return Operator("arrayIntersect", values).toJson() } + @JvmStatic fun arrayDiff(values: List): String { return Operator("arrayDiff", values).toJson() } + @JvmStatic + @JvmOverloads fun arrayFilter(condition: Condition, value: Any? = null): String { val values = listOf(condition.value, value) return Operator("arrayFilter", values).toJson() } + @JvmStatic fun stringConcat(value: Any): String { return Operator("stringConcat", listOf(value)).toJson() } + @JvmStatic fun stringReplace(search: String, replace: String): String { return Operator("stringReplace", listOf(search, replace)).toJson() } + @JvmStatic fun toggle(): String { return Operator("toggle", emptyList()).toJson() } + @JvmStatic fun dateAddDays(days: Int): String { return Operator("dateAddDays", listOf(days)).toJson() } + @JvmStatic fun dateSubDays(days: Int): String { return Operator("dateSubDays", listOf(days)).toJson() } + @JvmStatic fun dateSetNow(): String { return Operator("dateSetNow", emptyList()).toJson() } diff --git a/templates/kotlin/src/main/kotlin/io/appwrite/Permission.kt.twig b/templates/kotlin/src/main/kotlin/io/appwrite/Permission.kt.twig index 2540ae0cb0..796fdd0f6a 100644 --- a/templates/kotlin/src/main/kotlin/io/appwrite/Permission.kt.twig +++ b/templates/kotlin/src/main/kotlin/io/appwrite/Permission.kt.twig @@ -2,18 +2,23 @@ package {{ sdk.namespace | caseDot }} class Permission { companion object { + @JvmStatic fun read(role: String): String { return "read(\"${role}\")" } + @JvmStatic fun write(role: String): String { return "write(\"${role}\")" } + @JvmStatic fun create(role: String): String { return "create(\"${role}\")" } + @JvmStatic fun update(role: String): String { return "update(\"${role}\")" } + @JvmStatic fun delete(role: String): String { return "delete(\"${role}\")" } diff --git a/templates/kotlin/src/main/kotlin/io/appwrite/Query.kt.twig b/templates/kotlin/src/main/kotlin/io/appwrite/Query.kt.twig index e9d9753214..245c59543e 100644 --- a/templates/kotlin/src/main/kotlin/io/appwrite/Query.kt.twig +++ b/templates/kotlin/src/main/kotlin/io/appwrite/Query.kt.twig @@ -11,8 +11,10 @@ class Query( override fun toString() = this.toJson() companion object { + @JvmStatic fun equal(attribute: String, value: Any) = Query("equal", attribute, parseValue(value)).toJson() + @JvmStatic fun notEqual(attribute: String, value: Any) = Query("notEqual", attribute, parseValue(value)).toJson() /** @@ -22,20 +24,28 @@ class Query( * @param pattern The regular expression pattern to match. * @returns The query string. */ + @JvmStatic fun regex(attribute: String, pattern: String) = Query("regex", attribute, parseValue(pattern)).toJson() + @JvmStatic fun lessThan(attribute: String, value: Any) = Query("lessThan", attribute, parseValue(value)).toJson() + @JvmStatic fun lessThanEqual(attribute: String, value: Any) = Query("lessThanEqual", attribute, parseValue(value)).toJson() + @JvmStatic fun greaterThan(attribute: String, value: Any) = Query("greaterThan", attribute, parseValue(value)).toJson() + @JvmStatic fun greaterThanEqual(attribute: String, value: Any) = Query("greaterThanEqual", attribute, parseValue(value)).toJson() + @JvmStatic fun search(attribute: String, value: String) = Query("search", attribute, listOf(value)).toJson() + @JvmStatic fun isNull(attribute: String) = Query("isNull", attribute).toJson() + @JvmStatic fun isNotNull(attribute: String) = Query("isNotNull", attribute).toJson() /** @@ -44,6 +54,7 @@ class Query( * @param attributes The list of attributes that must exist. * @returns The query string. */ + @JvmStatic fun exists(attributes: List) = Query("exists", null, attributes).toJson() /** @@ -52,28 +63,40 @@ class Query( * @param attributes The list of attributes that must not exist. * @returns The query string. */ + @JvmStatic fun notExists(attributes: List) = Query("notExists", null, attributes).toJson() + @JvmStatic fun between(attribute: String, start: Any, end: Any) = Query("between", attribute, listOf(start, end)).toJson() + @JvmStatic fun startsWith(attribute: String, value: String) = Query("startsWith", attribute, listOf(value)).toJson() + @JvmStatic fun endsWith(attribute: String, value: String) = Query("endsWith", attribute, listOf(value)).toJson() + @JvmStatic fun select(attributes: List) = Query("select", null, attributes).toJson() + @JvmStatic fun orderAsc(attribute: String) = Query("orderAsc", attribute).toJson() + @JvmStatic fun orderDesc(attribute: String) = Query("orderDesc", attribute).toJson() + @JvmStatic fun orderRandom() = Query("orderRandom").toJson() + @JvmStatic fun cursorBefore(documentId: String) = Query("cursorBefore", null, listOf(documentId)).toJson() + @JvmStatic fun cursorAfter(documentId: String) = Query("cursorAfter", null, listOf(documentId)).toJson() + @JvmStatic fun limit(limit: Int) = Query("limit", null, listOf(limit)).toJson() + @JvmStatic fun offset(offset: Int) = Query("offset", null, listOf(offset)).toJson() /** @@ -82,6 +105,7 @@ class Query( * * Note: For array attributes, use containsAny or containsAll instead. */ + @JvmStatic fun contains(attribute: String, value: Any) = Query("contains", attribute, parseValue(value)).toJson() /** @@ -89,6 +113,7 @@ class Query( * For array and relationship attributes, matches documents where the attribute * contains at least one of the given values. */ + @JvmStatic fun containsAny(attribute: String, value: List) = Query("containsAny", attribute, value).toJson() /** @@ -96,32 +121,46 @@ class Query( * For array and relationship attributes, matches documents where the attribute * contains every one of the given values. */ + @JvmStatic fun containsAll(attribute: String, value: List) = Query("containsAll", attribute, value).toJson() + @JvmStatic fun notContains(attribute: String, value: Any) = Query("notContains", attribute, parseValue(value)).toJson() + @JvmStatic fun notSearch(attribute: String, value: String) = Query("notSearch", attribute, listOf(value)).toJson() + @JvmStatic fun notBetween(attribute: String, start: Any, end: Any) = Query("notBetween", attribute, listOf(start, end)).toJson() + @JvmStatic fun notStartsWith(attribute: String, value: String) = Query("notStartsWith", attribute, listOf(value)).toJson() + @JvmStatic fun notEndsWith(attribute: String, value: String) = Query("notEndsWith", attribute, listOf(value)).toJson() + @JvmStatic fun createdBefore(value: String) = lessThan("\$createdAt", value) + @JvmStatic fun createdAfter(value: String) = greaterThan("\$createdAt", value) + @JvmStatic fun createdBetween(start: String, end: String) = between("\$createdAt", start, end) + @JvmStatic fun updatedBefore(value: String) = lessThan("\$updatedAt", value) + @JvmStatic fun updatedAfter(value: String) = greaterThan("\$updatedAt", value) + @JvmStatic fun updatedBetween(start: String, end: String) = between("\$updatedAt", start, end) + @JvmStatic fun or(queries: List) = Query("or", null, queries.map { it.fromJson() }).toJson() + @JvmStatic fun and(queries: List) = Query("and", null, queries.map { it.fromJson() }).toJson() /** @@ -131,6 +170,7 @@ class Query( * @param queries The list of query strings to match against array elements. * @returns The query string. */ + @JvmStatic fun elemMatch(attribute: String, queries: List) = Query("elemMatch", attribute, queries.map { it.fromJson() }).toJson() /** @@ -140,6 +180,7 @@ class Query( * @param queries Filter, order, select, and pagination queries applied to related documents. * @returns The query string. */ + @JvmStatic fun relationship(attribute: String, queries: List) = Query("relationship", attribute, queries.map { it.fromJson() }).toJson() /** @@ -151,6 +192,8 @@ class Query( * @param meters Whether the distance is in meters. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun distanceEqual(attribute: String, values: List, distance: Number, meters: Boolean = true) = Query("distanceEqual", attribute, listOf(listOf(values, distance, meters))).toJson() /** @@ -162,6 +205,8 @@ class Query( * @param meters Whether the distance is in meters. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun distanceNotEqual(attribute: String, values: List, distance: Number, meters: Boolean = true) = Query("distanceNotEqual", attribute, listOf(listOf(values, distance, meters))).toJson() /** @@ -173,6 +218,8 @@ class Query( * @param meters Whether the distance is in meters. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun distanceGreaterThan(attribute: String, values: List, distance: Number, meters: Boolean = true) = Query("distanceGreaterThan", attribute, listOf(listOf(values, distance, meters))).toJson() /** @@ -184,6 +231,8 @@ class Query( * @param meters Whether the distance is in meters. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun distanceLessThan(attribute: String, values: List, distance: Number, meters: Boolean = true) = Query("distanceLessThan", attribute, listOf(listOf(values, distance, meters))).toJson() /** @@ -193,6 +242,7 @@ class Query( * @param vector The query vector. * @returns The query string. */ + @JvmStatic fun vectorDot(attribute: String, vector: List) = Query("vectorDot", attribute, listOf(vector)).toJson() /** @@ -202,6 +252,7 @@ class Query( * @param vector The query vector. * @returns The query string. */ + @JvmStatic fun vectorCosine(attribute: String, vector: List) = Query("vectorCosine", attribute, listOf(vector)).toJson() /** @@ -211,22 +262,31 @@ class Query( * @param vector The query vector. * @returns The query string. */ + @JvmStatic fun vectorEuclidean(attribute: String, vector: List) = Query("vectorEuclidean", attribute, listOf(vector)).toJson() + @JvmStatic fun intersects(attribute: String, values: List) = Query("intersects", attribute, listOf(values)).toJson() + @JvmStatic fun notIntersects(attribute: String, values: List) = Query("notIntersects", attribute, listOf(values)).toJson() + @JvmStatic fun crosses(attribute: String, values: List) = Query("crosses", attribute, listOf(values)).toJson() + @JvmStatic fun notCrosses(attribute: String, values: List) = Query("notCrosses", attribute, listOf(values)).toJson() + @JvmStatic fun overlaps(attribute: String, values: List) = Query("overlaps", attribute, listOf(values)).toJson() + @JvmStatic fun notOverlaps(attribute: String, values: List) = Query("notOverlaps", attribute, listOf(values)).toJson() + @JvmStatic fun touches(attribute: String, values: List) = Query("touches", attribute, listOf(values)).toJson() + @JvmStatic fun notTouches(attribute: String, values: List) = Query("notTouches", attribute, listOf(values)).toJson() /** @@ -236,6 +296,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun count(attribute: String = "*", alias: String = "") = Query("count", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -245,6 +307,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun countDistinct(attribute: String, alias: String = "") = Query("countDistinct", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -254,6 +318,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun sum(attribute: String, alias: String = "") = Query("sum", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -263,6 +329,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun avg(attribute: String, alias: String = "") = Query("avg", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -272,6 +340,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun min(attribute: String, alias: String = "") = Query("min", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -281,6 +351,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun max(attribute: String, alias: String = "") = Query("max", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -290,6 +362,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun stddev(attribute: String, alias: String = "") = Query("stddev", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -299,6 +373,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun stddevPop(attribute: String, alias: String = "") = Query("stddevPop", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -308,6 +384,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun stddevSamp(attribute: String, alias: String = "") = Query("stddevSamp", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -317,6 +395,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun variance(attribute: String, alias: String = "") = Query("variance", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -326,6 +406,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun varPop(attribute: String, alias: String = "") = Query("varPop", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -335,6 +417,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun varSamp(attribute: String, alias: String = "") = Query("varSamp", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -344,6 +428,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun bitAnd(attribute: String, alias: String = "") = Query("bitAnd", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -353,6 +439,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun bitOr(attribute: String, alias: String = "") = Query("bitOr", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -362,6 +450,8 @@ class Query( * @param alias Optional result alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun bitXor(attribute: String, alias: String = "") = Query("bitXor", attribute, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -370,6 +460,7 @@ class Query( * @param attributes Attributes to group by. * @returns The query string. */ + @JvmStatic fun groupBy(attributes: List) = Query("groupBy", null, attributes).toJson() /** @@ -378,6 +469,7 @@ class Query( * @param queries Nested query strings. * @returns The query string. */ + @JvmStatic fun having(queries: List) = Query("having", null, queries.map { it.fromJson() }).toJson() /** @@ -385,6 +477,7 @@ class Query( * * @returns The query string. */ + @JvmStatic fun distinct() = Query("distinct").toJson() /** @@ -395,6 +488,8 @@ class Query( * @param operator Comparison operator. Defaults to `=`. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun on(left: String, right: String, operator: String = "=") = Query("on", values = listOf(left, operator, right)).toJson() /** @@ -407,6 +502,8 @@ class Query( * @param alias Optional table alias. Defaults to the table ID when that is a valid alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun join(table: String, left: String, right: String, operator: String = "=", alias: String = "") = joinQuery("join", table, left, right, operator, alias) /** @@ -416,6 +513,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun join(table: String, on: List) = nestedJoin("join", table, "", on) /** @@ -426,6 +524,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun join(table: String, alias: String, on: List) = nestedJoin("join", table, alias, on) /** @@ -438,6 +537,8 @@ class Query( * @param alias Optional table alias. Defaults to the table ID when that is a valid alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun leftJoin(table: String, left: String, right: String, operator: String = "=", alias: String = "") = joinQuery("leftJoin", table, left, right, operator, alias) /** @@ -447,6 +548,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun leftJoin(table: String, on: List) = nestedJoin("leftJoin", table, "", on) /** @@ -457,6 +559,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun leftJoin(table: String, alias: String, on: List) = nestedJoin("leftJoin", table, alias, on) /** @@ -469,6 +572,8 @@ class Query( * @param alias Optional table alias. Defaults to the table ID when that is a valid alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun rightJoin(table: String, left: String, right: String, operator: String = "=", alias: String = "") = joinQuery("rightJoin", table, left, right, operator, alias) /** @@ -478,6 +583,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun rightJoin(table: String, on: List) = nestedJoin("rightJoin", table, "", on) /** @@ -488,6 +594,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun rightJoin(table: String, alias: String, on: List) = nestedJoin("rightJoin", table, alias, on) /** @@ -500,6 +607,8 @@ class Query( * @param alias Optional table alias. Defaults to the table ID when that is a valid alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun fullOuterJoin(table: String, left: String, right: String, operator: String = "=", alias: String = "") = joinQuery("fullOuterJoin", table, left, right, operator, alias) /** @@ -509,6 +618,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun fullOuterJoin(table: String, on: List) = nestedJoin("fullOuterJoin", table, "", on) /** @@ -519,6 +629,7 @@ class Query( * @param on Nested ON queries, including [on]. * @returns The query string. */ + @JvmStatic fun fullOuterJoin(table: String, alias: String, on: List) = nestedJoin("fullOuterJoin", table, alias, on) /** @@ -528,6 +639,8 @@ class Query( * @param alias Optional table alias. Defaults to the table ID when that is a valid alias. * @returns The query string. */ + @JvmStatic + @JvmOverloads fun crossJoin(table: String, alias: String = "") = Query("crossJoin", table, if (alias.isNotEmpty()) listOf(alias) else null).toJson() /** @@ -537,6 +650,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun covers(attribute: String, values: List) = Query("covers", attribute, listOf(values)).toJson() /** @@ -546,6 +660,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun notCovers(attribute: String, values: List) = Query("notCovers", attribute, listOf(values)).toJson() /** @@ -555,6 +670,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun spatialEquals(attribute: String, values: List) = Query("spatialEquals", attribute, listOf(values)).toJson() /** @@ -564,6 +680,7 @@ class Query( * @param values The coordinate values. * @returns The query string. */ + @JvmStatic fun notSpatialEquals(attribute: String, values: List) = Query("notSpatialEquals", attribute, listOf(values)).toJson() /** @@ -573,6 +690,8 @@ class Query( * @param perPage Rows per page. Defaults to 25. * @returns Limit and offset query strings. */ + @JvmStatic + @JvmOverloads fun page(page: Int, perPage: Int = 25): List { require(page >= 1) { "Page must be >= 1, got $page" } require(perPage >= 1) { "Per page must be >= 1, got $perPage" } @@ -584,6 +703,7 @@ class Query( * * @returns A new query builder. */ + @JvmStatic fun builder() = Builder() private fun joinQuery(method: String, table: String, left: String, right: String, operator: String, alias: String): String { diff --git a/templates/kotlin/src/main/kotlin/io/appwrite/Role.kt.twig b/templates/kotlin/src/main/kotlin/io/appwrite/Role.kt.twig index 8451ef3c7f..fd9cb5c3b3 100644 --- a/templates/kotlin/src/main/kotlin/io/appwrite/Role.kt.twig +++ b/templates/kotlin/src/main/kotlin/io/appwrite/Role.kt.twig @@ -11,6 +11,7 @@ class Role { * * This includes authenticated and unauthenticated users. */ + @JvmStatic fun any(): String = "any" /** @@ -19,6 +20,8 @@ class Role { * You can optionally pass verified or unverified for * [status] to target specific types of users. */ + @JvmStatic + @JvmOverloads fun user(id: String, status: String = ""): String = if (status.isEmpty()) { "user:$id" } else { @@ -31,6 +34,8 @@ class Role { * You can optionally pass verified or unverified for * [status] to target specific types of users. */ + @JvmStatic + @JvmOverloads fun users(status: String = ""): String = if (status.isEmpty()) { "users" } else { @@ -42,6 +47,7 @@ class Role { * * Authenticated users don't have access to this role. */ + @JvmStatic fun guests(): String = "guests" /** @@ -50,6 +56,8 @@ class Role { * You can optionally pass a role for [role] to target * team members with the specified role. */ + @JvmStatic + @JvmOverloads fun team(id: String, role: String = ""): String = if (role.isEmpty()) { "team:$id" } else { @@ -62,11 +70,13 @@ class Role { * When the member is removed from the team, they will * no longer have access. */ + @JvmStatic fun member(id: String): String = "member:$id" /** * Grants access to a user with the specified label. */ + @JvmStatic fun label(name: String): String = "label:$name" } } diff --git a/templates/kotlin/src/main/kotlin/io/appwrite/models/InputFile.kt.twig b/templates/kotlin/src/main/kotlin/io/appwrite/models/InputFile.kt.twig index d73609f368..6bd7e78642 100644 --- a/templates/kotlin/src/main/kotlin/io/appwrite/models/InputFile.kt.twig +++ b/templates/kotlin/src/main/kotlin/io/appwrite/models/InputFile.kt.twig @@ -14,6 +14,7 @@ class InputFile private constructor() { lateinit var data: Any companion object { + @JvmStatic fun fromFile(file: File) = InputFile().apply { path = file.canonicalPath filename = file.name @@ -23,10 +24,13 @@ class InputFile private constructor() { sourceType = "file" } + @JvmStatic fun fromPath(path: String): InputFile = fromFile(File(path)).apply { sourceType = "path" } + @JvmStatic + @JvmOverloads fun fromBytes(bytes: ByteArray, filename: String = "", mimeType: String = "") = InputFile().apply { this.filename = filename this.mimeType = mimeType diff --git a/templates/kotlin/src/main/kotlin/io/appwrite/services/ServiceTemplate.kt.twig b/templates/kotlin/src/main/kotlin/io/appwrite/services/ServiceTemplate.kt.twig index 1556391edb..fc48b577f6 100644 --- a/templates/kotlin/src/main/kotlin/io/appwrite/services/ServiceTemplate.kt.twig +++ b/templates/kotlin/src/main/kotlin/io/appwrite/services/ServiceTemplate.kt.twig @@ -45,7 +45,7 @@ class {{ service.name | caseUcfirst }}(client: Client) : Service(client) { ) {%~ endif %} {%~ endif %} - {%~ if (method | parameters('all')) | reduce((carry, param) => carry or not param.required) %} + {%~ if (method | parameters('all')) | reduce((carry, param) => carry or not param.required) or 'multipart/form-data' in (method | consumes) %} @JvmOverloads {%~ endif %} @Throws({{ spec.info.title | caseUcfirst }}Exception::class) @@ -159,7 +159,7 @@ class {{ service.name | caseUcfirst }}(client: Client) : Service(client) { ) {%~ endif %} {%~ endif %} - {%~ if (method | parameters('all')) | reduce((carry, param) => carry or not param.required) %} + {%~ if (method | parameters('all')) | reduce((carry, param) => carry or not param.required) or 'multipart/form-data' in (method | consumes) %} @JvmOverloads {%~ endif %} @Throws({{ spec.info.title | caseUcfirst }}Exception::class) diff --git a/tests/e2e/Android16Java17Test.php b/tests/e2e/Android16Java17Test.php index 3755fcfcf6..5e9cd3ee12 100644 --- a/tests/e2e/Android16Java17Test.php +++ b/tests/e2e/Android16Java17Test.php @@ -26,6 +26,10 @@ final class Android16Java17Test extends Base protected array $build = [ 'mkdir -p tests/e2e/sdks/android/library/src/test/java', 'cp tests/e2e/languages/android/Tests.kt tests/e2e/sdks/android/library/src/test/java/Tests.kt', + 'mkdir -p tests/e2e/sdks/android/library/src/test/java/io/appwrite', + 'cp tests/e2e/languages/kotlin/JavaInterop.java tests/e2e/sdks/android/library/src/test/java/io/appwrite/JavaInterop.java', + 'cp tests/e2e/languages/android/ChannelInterop.java tests/e2e/sdks/android/library/src/test/java/io/appwrite/ChannelInterop.java', + 'php tests/e2e/languages/kotlin/java-examples.php tests/e2e/sdks/android/docs/examples/java tests/e2e/sdks/android/library/src/test/java/examples "android.content.Context context, androidx.activity.ComponentActivity activity"', 'cp tests/e2e/languages/android/r8-rules.pro tests/e2e/sdks/android/library/r8-rules.pro', 'cat tests/e2e/languages/android/r8.gradle.kts >> tests/e2e/sdks/android/library/build.gradle.kts', 'cat tests/e2e/languages/android/lint.gradle.kts >> tests/e2e/sdks/android/library/build.gradle.kts', @@ -63,6 +67,8 @@ final class Android16Java17Test extends Base Base::QUERY_TRANSPORT_RESPONSE, ...Base::PERMISSION_HELPER_RESPONSES, ...Base::ID_HELPER_RESPONSES, + ...Base::JAVA_INTEROP_RESPONSES, + ...Base::ANDROID_JAVA_INTEROP_RESPONSES, ...Base::TOPIC_HELPER_RESPONSES, ...Base::CHANNEL_HELPER_RESPONSES, ...Base::OPERATOR_HELPER_RESPONSES, diff --git a/tests/e2e/Android5Java17Test.php b/tests/e2e/Android5Java17Test.php index 7363b3320c..fc5f6081d2 100644 --- a/tests/e2e/Android5Java17Test.php +++ b/tests/e2e/Android5Java17Test.php @@ -26,6 +26,10 @@ final class Android5Java17Test extends Base protected array $build = [ 'mkdir -p tests/e2e/sdks/android/library/src/test/java', 'cp tests/e2e/languages/android/Tests.kt tests/e2e/sdks/android/library/src/test/java/Tests.kt', + 'mkdir -p tests/e2e/sdks/android/library/src/test/java/io/appwrite', + 'cp tests/e2e/languages/kotlin/JavaInterop.java tests/e2e/sdks/android/library/src/test/java/io/appwrite/JavaInterop.java', + 'cp tests/e2e/languages/android/ChannelInterop.java tests/e2e/sdks/android/library/src/test/java/io/appwrite/ChannelInterop.java', + 'php tests/e2e/languages/kotlin/java-examples.php tests/e2e/sdks/android/docs/examples/java tests/e2e/sdks/android/library/src/test/java/examples "android.content.Context context, androidx.activity.ComponentActivity activity"', 'chmod +x tests/e2e/sdks/android/gradlew', ]; #[Override] @@ -60,6 +64,8 @@ final class Android5Java17Test extends Base Base::QUERY_TRANSPORT_RESPONSE, ...Base::PERMISSION_HELPER_RESPONSES, ...Base::ID_HELPER_RESPONSES, + ...Base::JAVA_INTEROP_RESPONSES, + ...Base::ANDROID_JAVA_INTEROP_RESPONSES, ...Base::TOPIC_HELPER_RESPONSES, ...Base::CHANNEL_HELPER_RESPONSES, ...Base::OPERATOR_HELPER_RESPONSES, diff --git a/tests/e2e/Base.php b/tests/e2e/Base.php index b13ff729d1..c8111eb4ee 100644 --- a/tests/e2e/Base.php +++ b/tests/e2e/Base.php @@ -517,6 +517,22 @@ abstract class Base extends TestCase 'custom_id' ]; + protected const ANDROID_JAVA_INTEROP_RESPONSES = [ + 'databases.db1', + 'account', + ]; + + protected const JAVA_INTEROP_RESPONSES = [ + 'unique()', + 'read("any")', + '{"method":"limit","values":[1]}', + '{"method":"count","attribute":"*"}', + '{"method":"increment","values":[1]}', + '{"method":"increment","values":[5]}', + 'Missing required parameter: "id"', + 'PUT:/v1/mock/tests/general/upload-generic:passed', + ]; + protected const TOPIC_HELPER_RESPONSES = [ 'user/123/notification', 'org/42/user/123/notification', diff --git a/tests/e2e/KotlinJava17Test.php b/tests/e2e/KotlinJava17Test.php index d4fcaaae93..80865eeb55 100644 --- a/tests/e2e/KotlinJava17Test.php +++ b/tests/e2e/KotlinJava17Test.php @@ -26,6 +26,9 @@ final class KotlinJava17Test extends Base protected array $build = [ 'mkdir -p tests/e2e/sdks/kotlin/src/test/kotlin', 'cp tests/e2e/languages/kotlin/Tests.kt tests/e2e/sdks/kotlin/src/test/kotlin/Tests.kt', + 'mkdir -p tests/e2e/sdks/kotlin/src/test/java/io/appwrite', + 'cp tests/e2e/languages/kotlin/JavaInterop.java tests/e2e/sdks/kotlin/src/test/java/io/appwrite/JavaInterop.java', + 'php tests/e2e/languages/kotlin/java-examples.php tests/e2e/sdks/kotlin/docs/examples/java tests/e2e/sdks/kotlin/src/test/java/examples', 'chmod +x tests/e2e/sdks/kotlin/gradlew', ]; #[Override] @@ -59,6 +62,7 @@ final class KotlinJava17Test extends Base Base::QUERY_TRANSPORT_RESPONSE, ...Base::PERMISSION_HELPER_RESPONSES, ...Base::ID_HELPER_RESPONSES, + ...Base::JAVA_INTEROP_RESPONSES, ...Base::TOPIC_HELPER_RESPONSES, ...Base::OPERATOR_HELPER_RESPONSES ]; diff --git a/tests/e2e/languages/android/ChannelInterop.java b/tests/e2e/languages/android/ChannelInterop.java new file mode 100644 index 0000000000..abe1b46de8 --- /dev/null +++ b/tests/e2e/languages/android/ChannelInterop.java @@ -0,0 +1,13 @@ +package io.appwrite; + +import java.util.Arrays; +import java.util.List; + +public final class ChannelInterop { + private ChannelInterop() { + } + + public static List run() { + return Arrays.asList(Channel.database("db1").toString(), Channel.account()); + } +} diff --git a/tests/e2e/languages/android/Tests.kt b/tests/e2e/languages/android/Tests.kt index ba83e0de7a..6e9172f430 100644 --- a/tests/e2e/languages/android/Tests.kt +++ b/tests/e2e/languages/android/Tests.kt @@ -516,6 +516,9 @@ class ServiceTest { writeToFile(ID.unique()) writeToFile(ID.custom("custom_id")) + JavaInterop.run(general, "../../../../resources/file.png").forEach { writeToFile(it) } + ChannelInterop.run().forEach { writeToFile(it) } + // Topic helper tests writeToFile(Topic.path(listOf("user", "123", "notification")).toString()) writeToFile(Topic.path(listOf("org", "42", "user", "123")).path(listOf("notification")).toString()) diff --git a/tests/e2e/languages/kotlin/JavaInterop.java b/tests/e2e/languages/kotlin/JavaInterop.java new file mode 100644 index 0000000000..16822b2091 --- /dev/null +++ b/tests/e2e/languages/kotlin/JavaInterop.java @@ -0,0 +1,57 @@ +package io.appwrite; + +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.exceptions.AppwriteException; +import io.appwrite.models.InputFile; +import io.appwrite.models.Profile; +import io.appwrite.services.General; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import kotlin.coroutines.intrinsics.IntrinsicsKt; + +public final class JavaInterop { + private JavaInterop() { + } + + public static List run(General general, String file) throws Exception { + List lines = new ArrayList<>(); + + lines.add(ID.unique()); + lines.add(Permission.read(Role.any())); + lines.add(Query.limit(1)); + lines.add(Query.count()); + lines.add(Operator.increment()); + lines.add(Operator.increment(5)); + + try { + general.validatePath("0", "", new CoroutineCallback<>((result, error) -> { + })); + lines.add("Empty path parameter was accepted"); + } catch (AppwriteException e) { + lines.add(e.getMessage()); + } + + CompletableFuture> profile = new CompletableFuture<>(); + try { + Object returned = general.uploadGeneric(InputFile.fromPath(file), Map.class, new CoroutineCallback<>((result, error) -> { + if (error != null) { + profile.completeExceptionally(error); + } else { + profile.complete(result); + } + })); + if (returned != IntrinsicsKt.getCOROUTINE_SUSPENDED()) { + profile.complete((Profile) returned); + } + } catch (AppwriteException e) { + profile.completeExceptionally(e); + } + Map data = (Map) profile.get(30, TimeUnit.SECONDS).getPrefs().getData(); + lines.add((String) data.get("result")); + + return lines; + } +} diff --git a/tests/e2e/languages/kotlin/Tests.kt b/tests/e2e/languages/kotlin/Tests.kt index b3a84e7367..c16b4e7759 100644 --- a/tests/e2e/languages/kotlin/Tests.kt +++ b/tests/e2e/languages/kotlin/Tests.kt @@ -361,6 +361,8 @@ class ServiceTest { writeToFile(ID.unique()) writeToFile(ID.custom("custom_id")) + JavaInterop.run(general, "../../../resources/file.png").forEach { writeToFile(it) } + // Topic helper tests writeToFile(Topic.path(listOf("user", "123", "notification")).toString()) writeToFile(Topic.path(listOf("org", "42", "user", "123")).path(listOf("notification")).toString()) diff --git a/tests/e2e/languages/kotlin/java-examples.php b/tests/e2e/languages/kotlin/java-examples.php new file mode 100644 index 0000000000..ce07c5fb27 --- /dev/null +++ b/tests/e2e/languages/kotlin/java-examples.php @@ -0,0 +1,58 @@ +getExtension() === 'md' && !in_array(substr((string) $file->getPathname(), strlen($source) + 1), UNSUPPORTED, true)) { + $paths[] = $file->getPathname(); + } +} +sort($paths); + +if ($paths === []) { + fwrite(STDERR, "No Java examples found in {$source}\n"); + exit(1); +} + +if (!is_dir($destination) && !mkdir($destination, 0777, true)) { + exit(1); +} + +foreach ($paths as $index => $path) { + if (!preg_match('/```java\n(.*?)```/s', (string) file_get_contents($path), $match)) { + fwrite(STDERR, "No Java block in {$path}\n"); + exit(1); + } + + $imports = []; + $statements = []; + foreach (explode("\n", $match[1]) as $line) { + if (str_starts_with($line, 'import ')) { + $imports[] = $line; + } else { + $statements[] = ' ' . $line; + } + } + + $class = 'Example' . $index; + file_put_contents( + "{$destination}/{$class}.java", + "package examples;\n\n" + . implode("\n", $imports) + . "\n\npublic class {$class} {\n public void run({$parameters}) {\n" + . implode("\n", $statements) + . "\n }\n}\n" + ); +}