Skip to content

Add inc/dec #50

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1 +1,29 @@
# Change Log
# Change Log

## 9.1.0

* Add `incrementDocumentAttribute` and `decrementDocumentAttribute` support to `Databases` service
* Add `dart38` and `flutter332` support to runtime models
* Add `gif` support to `ImageFormat` enum
* Add `encrypt` support to `StringAttribute` model
* Add `sequence` support to `Document` model

## 9.0.0

* Add `<REGION>` to doc examples due to the new multi region endpoints
* Add doc examples and methods for bulk api transactions: `createDocuments`, `deleteDocuments` etc.
* Add doc examples, class and methods for new `Sites` service
* Add doc examples, class and methods for new `Tokens` service
* Add enums for `BuildRuntime `, `Adapter`, `Framework`, `DeploymentDownloadType` and `VCSDeploymentType`
* Update enum for `runtimes` with Pythonml312, Dart219, Flutter327 and Flutter329
* Add `token` param to `getFilePreview` and `getFileView` for File tokens usage
* Add `queries` and `search` params to `listMemberships` method
* Remove `search` param from `listExecutions` method

## 8.0.0

* Fix requests failing by removing `Content-Type` header from `GET` and `HEAD` requests

## 7.0.0

* Fix pong response & chunked upload
77 changes: 74 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![Maven Central](https://img.shields.io/maven-central/v/io.appwrite/sdk-for-kotlin.svg?color=green&style=flat-square)
![License](https://img.shields.io/github/license/appwrite/sdk-for-kotlin.svg?style=flat-square)
![Version](https://img.shields.io/badge/api%20version-1.7.0-blue.svg?style=flat-square)
![Version](https://img.shields.io/badge/api%20version-1.7.4-blue.svg?style=flat-square)
[![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite)
[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord)

Expand Down Expand Up @@ -39,7 +39,7 @@ repositories {
Next, add the dependency to your project's `build.gradle(.kts)` file:

```groovy
implementation("io.appwrite:sdk-for-kotlin:9.0.0")
implementation("io.appwrite:sdk-for-kotlin:9.1.0")
```

### Maven
Expand All @@ -50,7 +50,7 @@ Add this to your project's `pom.xml` file:
<dependency>
<groupId>io.appwrite</groupId>
<artifactId>sdk-for-kotlin</artifactId>
<version>9.0.0</version>
<version>9.1.0</version>
</dependency>
</dependencies>
```
Expand Down Expand Up @@ -115,6 +115,77 @@ suspend fun main() {
}
```

### Type Safety with Models

The Appwrite Kotlin SDK provides type safety when working with database documents through generic methods. Methods like `listDocuments`, `getDocument`, and others accept a `nestedType` parameter that allows you to specify your custom model type for full type safety.

```kotlin
data class Book(
val name: String,
val author: String,
val releaseYear: String? = null,
val category: String? = null,
val genre: List<String>? = null,
val isCheckedOut: Boolean
)

val databases = Databases(client)

try {
val documents = databases.listDocuments(
databaseId = "your-database-id",
collectionId = "your-collection-id",
nestedType = Book::class.java // Pass in your custom model type
)

for (book in documents.documents) {
Log.d("Appwrite", "Book: ${book.name} by ${book.author}") // Now you have full type safety
}
} catch (e: AppwriteException) {
Log.e("Appwrite", e.message ?: "Unknown error")
}
```

**Tip**: You can use the `appwrite types` command to automatically generate model definitions based on your Appwrite database schema. Learn more about [type generation](https://appwrite.io/docs/products/databases/type-generation).

### Working with Model Methods

All Appwrite models come with built-in methods for data conversion and manipulation:

**`toMap()`** - Converts a model instance to a Map format, useful for debugging or manual data manipulation:
```kotlin
val account = Account(client)
val user = account.get()
val userMap = user.toMap()
Log.d("Appwrite", userMap.toString()) // Prints all user properties as a Map
```

**`from(map:, nestedType:)`** - Creates a model instance from a Map, useful when working with raw data:
```kotlin
val userData: Map<String, Any> = mapOf(
"\$id" to "123",
"name" to "John",
"email" to "[email protected]"
)
val user = User.from(userData, User::class.java)
```

**JSON Serialization** - Models can be easily converted to/from JSON using Gson (which the SDK uses internally):
```kotlin
import com.google.gson.Gson

val account = Account(client)
val user = account.get()

// Convert to JSON
val gson = Gson()
val jsonString = gson.toJson(user)
Log.d("Appwrite", "User JSON: $jsonString")

// Convert from JSON
val userFromJson = gson.fromJson(jsonString, User::class.java)
```

### Error Handling

The Appwrite Kotlin SDK raises `AppwriteException` object with `message`, `code` and `response` properties. You can handle any errors by catching `AppwriteException` and present the `message` to the user or handle it yourself based on the provided error information. Below is an example.
Expand Down
5 changes: 2 additions & 3 deletions docs/examples/java/databases/create-document.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import io.appwrite.services.Databases;

Client client = new Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setSession("") // The user session to authenticate with
.setKey("<YOUR_API_KEY>") // Your secret API key
.setJWT("<YOUR_JWT>"); // Your secret JSON Web Token
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setSession(""); // The user session to authenticate with

Databases databases = new Databases(client);

Expand Down
1 change: 1 addition & 0 deletions docs/examples/java/databases/create-documents.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.appwrite.services.Databases;

Client client = new Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>"); // Your secret API key

Databases databases = new Databases(client);
Expand Down
28 changes: 28 additions & 0 deletions docs/examples/java/databases/decrement-document-attribute.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;

Client client = new Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>"); // Your secret API key

Databases databases = new Databases(client);

databases.decrementDocumentAttribute(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
"<DOCUMENT_ID>", // documentId
"", // attribute
0, // value (optional)
0, // min (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

System.out.println(result);
})
);

28 changes: 28 additions & 0 deletions docs/examples/java/databases/increment-document-attribute.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;

Client client = new Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>"); // Your secret API key

Databases databases = new Databases(client);

databases.incrementDocumentAttribute(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
"<DOCUMENT_ID>", // documentId
"", // attribute
0, // value (optional)
0, // max (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

System.out.println(result);
})
);

27 changes: 27 additions & 0 deletions docs/examples/java/databases/upsert-document.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Databases;

Client client = new Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setSession(""); // The user session to authenticate with

Databases databases = new Databases(client);

databases.upsertDocument(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
"<DOCUMENT_ID>", // documentId
mapOf( "a" to "b" ), // data
listOf("read("any")"), // permissions (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

System.out.println(result);
})
);

2 changes: 1 addition & 1 deletion docs/examples/java/databases/upsert-documents.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Databases databases = new Databases(client);
databases.upsertDocuments(
"<DATABASE_ID>", // databaseId
"<COLLECTION_ID>", // collectionId
listOf(), // documents (optional)
listOf(), // documents
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
Expand Down
3 changes: 1 addition & 2 deletions docs/examples/kotlin/databases/create-document.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import io.appwrite.services.Databases

val client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setSession("") // The user session to authenticate with
.setKey("<YOUR_API_KEY>") // Your secret API key
.setJWT("<YOUR_JWT>") // Your secret JSON Web Token

val databases = Databases(client)

Expand Down
1 change: 1 addition & 0 deletions docs/examples/kotlin/databases/create-documents.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.appwrite.services.Databases

val client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>") // Your secret API key

val databases = Databases(client)
Expand Down
19 changes: 19 additions & 0 deletions docs/examples/kotlin/databases/decrement-document-attribute.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases

val client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>") // Your secret API key

val databases = Databases(client)

val response = databases.decrementDocumentAttribute(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documentId = "<DOCUMENT_ID>",
attribute = "",
value = 0, // optional
min = 0 // optional
)
19 changes: 19 additions & 0 deletions docs/examples/kotlin/databases/increment-document-attribute.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases

val client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setKey("<YOUR_API_KEY>") // Your secret API key

val databases = Databases(client)

val response = databases.incrementDocumentAttribute(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documentId = "<DOCUMENT_ID>",
attribute = "",
value = 0, // optional
max = 0 // optional
)
18 changes: 18 additions & 0 deletions docs/examples/kotlin/databases/upsert-document.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import io.appwrite.Client
import io.appwrite.coroutines.CoroutineCallback
import io.appwrite.services.Databases

val client = Client()
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>") // Your project ID
.setSession("") // The user session to authenticate with

val databases = Databases(client)

val response = databases.upsertDocument(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documentId = "<DOCUMENT_ID>",
data = mapOf( "a" to "b" ),
permissions = listOf("read("any")") // optional
)
2 changes: 1 addition & 1 deletion docs/examples/kotlin/databases/upsert-documents.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ val databases = Databases(client)
val response = databases.upsertDocuments(
databaseId = "<DATABASE_ID>",
collectionId = "<COLLECTION_ID>",
documents = listOf() // optional
documents = listOf()
)
4 changes: 2 additions & 2 deletions src/main/kotlin/io/appwrite/Client.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ class Client @JvmOverloads constructor(
init {
headers = mutableMapOf(
"content-type" to "application/json",
"user-agent" to "AppwriteKotlinSDK/9.0.0 ${System.getProperty("http.agent")}",
"user-agent" to "AppwriteKotlinSDK/9.1.0 ${System.getProperty("http.agent")}",
"x-sdk-name" to "Kotlin",
"x-sdk-platform" to "server",
"x-sdk-language" to "kotlin",
"x-sdk-version" to "9.0.0",
"x-sdk-version" to "9.1.0",
"x-appwrite-response-format" to "1.7.0",
)

Expand Down
6 changes: 5 additions & 1 deletion src/main/kotlin/io/appwrite/enums/BuildRuntime.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ enum class BuildRuntime(val value: String) {
DART_3_3("dart-3.3"),
@SerializedName("dart-3.5")
DART_3_5("dart-3.5"),
@SerializedName("dart-3.8")
DART_3_8("dart-3.8"),
@SerializedName("dotnet-6.0")
DOTNET_6_0("dotnet-6.0"),
@SerializedName("dotnet-7.0")
Expand Down Expand Up @@ -128,7 +130,9 @@ enum class BuildRuntime(val value: String) {
@SerializedName("flutter-3.27")
FLUTTER_3_27("flutter-3.27"),
@SerializedName("flutter-3.29")
FLUTTER_3_29("flutter-3.29");
FLUTTER_3_29("flutter-3.29"),
@SerializedName("flutter-3.32")
FLUTTER_3_32("flutter-3.32");

override fun toString() = value
}
4 changes: 3 additions & 1 deletion src/main/kotlin/io/appwrite/enums/ImageFormat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ enum class ImageFormat(val value: String) {
@SerializedName("heic")
HEIC("heic"),
@SerializedName("avif")
AVIF("avif");
AVIF("avif"),
@SerializedName("gif")
GIF("gif");

override fun toString() = value
}
Loading