diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 273eef84e..828d7d732 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -4,8 +4,10 @@
name: Publish
on:
- release:
- types: [ prereleased, released ]
+ ## do not upstream ##
+ push:
+ branches: [ master, snapshot ]
+ ## ############### ##
env:
sonatypeUsername: ${{ secrets.SONATYPEUSERNAME }}
@@ -23,6 +25,11 @@ jobs:
with:
distribution: 'zulu'
java-version: '17'
+ ## do no upstream ##
+ - name: replace -SNAPSHOT with -run_number-SNAPSHOT
+ run: sed -i '' 's/-SNAPSHOT/-${{github.run_number}}-SNAPSHOT/g' gradle.properties
+ shell: bash
+ ## ############## ##
- uses: gradle/actions/setup-gradle@v4
- name: Setup versions
run: ./gradlew :updateVersions
diff --git a/README.md b/README.md
index f92376210..cb7b1175e 100644
--- a/README.md
+++ b/README.md
@@ -16,17 +16,17 @@ The following libraries are available for the various Firebase products.
| Service or Product | Gradle Dependency | API Coverage |
|---------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [Analytics](https://firebase.google.com/docs/analytics) | [`dev.gitlive:firebase-analytics:2.0.0`](https://search.maven.org/artifact/dev.gitlive/firebase-analytics/2.0.0/pom) | [![80%](https://img.shields.io/badge/-80%25-green?style=flat-square)](/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt) |
-| [Authentication](https://firebase.google.com/docs/auth) | [`dev.gitlive:firebase-auth:2.0.0`](https://search.maven.org/artifact/dev.gitlive/firebase-auth/2.0.0/pom) | [![80%](https://img.shields.io/badge/-80%25-green?style=flat-square)](/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt) |
-| [Realtime Database](https://firebase.google.com/docs/database) | [`dev.gitlive:firebase-database:2.0.0`](https://search.maven.org/artifact/dev.gitlive/firebase-database/2.0.0/pom) | [![70%](https://img.shields.io/badge/-70%25-orange?style=flat-square)](/firebase-database/src/commonMain/kotlin/dev/gitlive/firebase/database/database.kt) |
-| [Cloud Firestore](https://firebase.google.com/docs/firestore) | [`dev.gitlive:firebase-firestore:2.0.0`](https://search.maven.org/artifact/dev.gitlive/firebase-firestore/2.0.0/pom) | [![60%](https://img.shields.io/badge/-60%25-orange?style=flat-square)](/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt) |
-| [Cloud Functions](https://firebase.google.com/docs/functions) | [`dev.gitlive:firebase-functions:2.0.0`](https://search.maven.org/artifact/dev.gitlive/firebase-functions/2.0.0/pom) | [![80%](https://img.shields.io/badge/-80%25-green?style=flat-square)](/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt) |
-| [Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) | [`dev.gitlive:firebase-messaging:2.0.0`](https://search.maven.org/artifact/dev.gitlive/firebase-messaging/2.0.0/pom) | [![1%](https://img.shields.io/badge/-10%25-orange?style=flat-square)](/firebase-messaging/src/commonMain/kotlin/dev/gitlive/firebase/messaging/messaging.kt) |
-| [Cloud Storage](https://firebase.google.com/docs/storage) | [`dev.gitlive:firebase-storage:2.0.0`](https://search.maven.org/artifact/dev.gitlive/firebase-storage/2.0.0/pom) | [![40%](https://img.shields.io/badge/-40%25-orange?style=flat-square)](/firebase-storage/src/commonMain/kotlin/dev/gitlive/firebase/storage/storage.kt) |
-| [Installations](https://firebase.google.com/docs/projects/manage-installations) | [`dev.gitlive:firebase-installations:2.0.0`](https://search.maven.org/artifact/dev.gitlive/firebase-installations/2.0.0/pom) | [![90%](https://img.shields.io/badge/-90%25-green?style=flat-square)](/firebase-installations/src/commonMain/kotlin/dev/gitlive/firebase/installations/installations.kt) |
-| [Remote Config](https://firebase.google.com/docs/remote-config) | [`dev.gitlive:firebase-config:2.0.0`](https://search.maven.org/artifact/dev.gitlive/firebase-config/2.0.0/pom) | [![20%](https://img.shields.io/badge/-20%25-orange?style=flat-square)](/firebase-config/src/commonMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt) |
-| [Performance](https://firebase.google.com/docs/perf-mon) | [`dev.gitlive:firebase-perf:2.0.0`](https://search.maven.org/artifact/dev.gitlive/firebase-perf/2.0.0/pom) | [![1%](https://img.shields.io/badge/-10%25-orange?style=flat-square)](/firebase-perf/src/commonMain/kotlin/dev/gitlive/firebase/perf/performance.kt) |
-| [Crashlytics](https://firebase.google.com/docs/crashlytics) | [`dev.gitlive:firebase-crashlytics:2.0.0`](https://search.maven.org/artifact/dev.gitlive/firebase-crashlytics/2.0.0/pom) | [![80%](https://img.shields.io/badge/-10%25-orange?style=flat-square)](/firebase-crashlytics/src/commonMain/kotlin/dev/gitlive/firebase/crashlytics/crashlytics.kt) |
+| [Analytics](https://firebase.google.com/docs/analytics) | [`dev.gitlive:firebase-analytics:2.1.0`](https://search.maven.org/artifact/dev.gitlive/firebase-analytics/2.1.0/pom) | [![80%](https://img.shields.io/badge/-80%25-green?style=flat-square)](/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt) |
+| [Authentication](https://firebase.google.com/docs/auth) | [`dev.gitlive:firebase-auth:2.1.0`](https://search.maven.org/artifact/dev.gitlive/firebase-auth/2.1.0/pom) | [![80%](https://img.shields.io/badge/-80%25-green?style=flat-square)](/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt) |
+| [Realtime Database](https://firebase.google.com/docs/database) | [`dev.gitlive:firebase-database:2.1.0`](https://search.maven.org/artifact/dev.gitlive/firebase-database/2.1.0/pom) | [![70%](https://img.shields.io/badge/-70%25-orange?style=flat-square)](/firebase-database/src/commonMain/kotlin/dev/gitlive/firebase/database/database.kt) |
+| [Cloud Firestore](https://firebase.google.com/docs/firestore) | [`dev.gitlive:firebase-firestore:2.1.0`](https://search.maven.org/artifact/dev.gitlive/firebase-firestore/2.1.0/pom) | [![60%](https://img.shields.io/badge/-60%25-orange?style=flat-square)](/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt) |
+| [Cloud Functions](https://firebase.google.com/docs/functions) | [`dev.gitlive:firebase-functions:2.1.0`](https://search.maven.org/artifact/dev.gitlive/firebase-functions/2.1.0/pom) | [![80%](https://img.shields.io/badge/-80%25-green?style=flat-square)](/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt) |
+| [Cloud Messaging](https://firebase.google.com/docs/cloud-messaging) | [`dev.gitlive:firebase-messaging:2.1.0`](https://search.maven.org/artifact/dev.gitlive/firebase-messaging/2.1.0/pom) | [![1%](https://img.shields.io/badge/-10%25-orange?style=flat-square)](/firebase-messaging/src/commonMain/kotlin/dev/gitlive/firebase/messaging/messaging.kt) |
+| [Cloud Storage](https://firebase.google.com/docs/storage) | [`dev.gitlive:firebase-storage:2.1.0`](https://search.maven.org/artifact/dev.gitlive/firebase-storage/2.1.0/pom) | [![40%](https://img.shields.io/badge/-40%25-orange?style=flat-square)](/firebase-storage/src/commonMain/kotlin/dev/gitlive/firebase/storage/storage.kt) |
+| [Installations](https://firebase.google.com/docs/projects/manage-installations) | [`dev.gitlive:firebase-installations:2.1.0`](https://search.maven.org/artifact/dev.gitlive/firebase-installations/2.1.0/pom) | [![90%](https://img.shields.io/badge/-90%25-green?style=flat-square)](/firebase-installations/src/commonMain/kotlin/dev/gitlive/firebase/installations/installations.kt) |
+| [Remote Config](https://firebase.google.com/docs/remote-config) | [`dev.gitlive:firebase-config:2.1.0`](https://search.maven.org/artifact/dev.gitlive/firebase-config/2.1.0/pom) | [![20%](https://img.shields.io/badge/-20%25-orange?style=flat-square)](/firebase-config/src/commonMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt) |
+| [Performance](https://firebase.google.com/docs/perf-mon) | [`dev.gitlive:firebase-perf:2.1.0`](https://search.maven.org/artifact/dev.gitlive/firebase-perf/2.1.0/pom) | [![1%](https://img.shields.io/badge/-10%25-orange?style=flat-square)](/firebase-perf/src/commonMain/kotlin/dev/gitlive/firebase/perf/performance.kt) |
+| [Crashlytics](https://firebase.google.com/docs/crashlytics) | [`dev.gitlive:firebase-crashlytics:2.1.0`](https://search.maven.org/artifact/dev.gitlive/firebase-crashlytics/2.1.0/pom) | [![80%](https://img.shields.io/badge/-10%25-orange?style=flat-square)](/firebase-crashlytics/src/commonMain/kotlin/dev/gitlive/firebase/crashlytics/crashlytics.kt) |
Is the Firebase library or API you need missing? [Create an issue](https://github.com/GitLiveApp/firebase-kotlin-sdk/issues/new?labels=API+coverage&template=increase-api-coverage.md&title=Add+%5Bclass+name%5D.%5Bfunction+name%5D+to+%5Blibrary+name%5D+for+%5Bplatform+names%5D) to request additional API coverage or be awesome and [submit a PR](https://github.com/GitLiveApp/firebase-kotlin-sdk/fork)
@@ -250,6 +250,15 @@ citiesRef.where {
}
```
+Similar methods exist for `update` methods in the Firestore module:
+
+```kotlin
+documentRef.update {
+ "field" to "value"
+ "otherField".to(IntAsStringSerializer(), 1)
+}
+```
+
In cases where it makes sense, such as Firebase Functions HTTPS Callable, operator overloading is used:
@@ -278,9 +287,13 @@ These properties are only accessible from the equivalent target's source set. Fo
.build()
```
+### Running on Android
+
+On android, some modules (`config`) require you to enable [Core library desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring) if you have a *minSDK lower than API 26*.
+
### Running on iOS
-On iOS the official [Firebase iOS SDK](https://github.com/firebase/firebase-ios-sdk) in not linked as a transtive dependency. Therefore, any project using this SDK needs to link the actual Firestore SDK as well. This can be done through your preferred installation method (Cocoapods/SPM).
+On iOS the official [Firebase iOS SDK](https://github.com/firebase/firebase-ios-sdk) in not linked as a transitive dependency. Therefore, any project using this SDK needs to link the actual Firestore SDK as well. This can be done through your preferred installation method (Cocoapods/SPM).
Similarly, tests require linking as well. Make sure to add the required frameworks to the search path of your test targets. This can be done by specifying a `cocoapods` block in your `build.gradle`:
```kotlin
diff --git a/build.gradle.kts b/build.gradle.kts
index ac5150679..7f92541d9 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -70,7 +70,9 @@ tasks.withType().configureEach {
subprojects {
- group = "dev.gitlive"
+ //// do not upstream ////
+ group = "com.splendo.firebase"
+ //// /////////////// ////
val nonDocumentationList = listOf("test-utils", "firebase-common", "firebase-common-internal")
val skipDocumentation = nonDocumentationList.contains(project.name)
@@ -196,7 +198,10 @@ subprojects {
repositories {
maven {
- url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2")
+ //// do not upstream ////
+ this.name = "snapshot"
+ url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
+ //// /////////////// ////
credentials {
username = project.findProperty("sonatypeUsername") as String? ?: System.getenv("sonatypeUsername")
diff --git a/firebase-analytics/package.json b/firebase-analytics/package.json
index da4f8da37..4db9c7135 100644
--- a/firebase-analytics/package.json
+++ b/firebase-analytics/package.json
@@ -1,6 +1,6 @@
{
"name": "@gitlive/firebase-analytics",
- "version": "2.0.0",
+ "version": "2.2.0-SNAPSHOT",
"description": "Wrapper around firebase for usage in Kotlin Multiplatform projects",
"main": "firebase-analytics.js",
"scripts": {
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk",
"dependencies": {
- "@gitlive/firebase-app": "2.0.0",
+ "@gitlive/firebase-app": "2.2.0-SNAPSHOT",
"firebase": "9.19.1",
"kotlin": "1.6.10",
"kotlinx-coroutines-core": "1.6.1-native-mt"
diff --git a/firebase-app/package.json b/firebase-app/package.json
index 9fceec0af..575fc918a 100644
--- a/firebase-app/package.json
+++ b/firebase-app/package.json
@@ -1,6 +1,6 @@
{
"name": "@gitlive/firebase-app",
- "version": "2.0.0",
+ "version": "2.2.0-SNAPSHOT",
"description": "Wrapper around firebase for usage in Kotlin Multiplatform projects",
"main": "firebase-app.js",
"scripts": {
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk",
"dependencies": {
- "@gitlive/firebase-common": "2.0.0",
+ "@gitlive/firebase-common": "2.2.0-SNAPSHOT",
"firebase": "9.19.1",
"kotlin": "1.8.20",
"kotlinx-coroutines-core": "1.6.4"
diff --git a/firebase-auth/api/android/firebase-auth.api b/firebase-auth/api/android/firebase-auth.api
index a5ac17791..d997bf223 100644
--- a/firebase-auth/api/android/firebase-auth.api
+++ b/firebase-auth/api/android/firebase-auth.api
@@ -51,6 +51,14 @@ public final class dev/gitlive/firebase/auth/ActionCodeSettings {
public fun toString ()Ljava/lang/String;
}
+public final class dev/gitlive/firebase/auth/AdditionalUserInfo {
+ public fun (Lcom/google/firebase/auth/AdditionalUserInfo;)V
+ public final fun getProfile ()Ljava/util/Map;
+ public final fun getProviderId ()Ljava/lang/String;
+ public final fun getUsername ()Ljava/lang/String;
+ public final fun isNewUser ()Z
+}
+
public final class dev/gitlive/firebase/auth/AndroidPackageName {
public fun (Ljava/lang/String;ZLjava/lang/String;)V
public synthetic fun (Ljava/lang/String;ZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -74,6 +82,9 @@ public class dev/gitlive/firebase/auth/AuthCredential {
}
public final class dev/gitlive/firebase/auth/AuthResult {
+ public fun (Lcom/google/firebase/auth/AuthResult;)V
+ public final fun getAdditionalUserInfo ()Ldev/gitlive/firebase/auth/AdditionalUserInfo;
+ public final fun getCredential ()Ldev/gitlive/firebase/auth/AuthCredential;
public final fun getUser ()Ldev/gitlive/firebase/auth/FirebaseUser;
}
@@ -278,6 +289,7 @@ public final class dev/gitlive/firebase/auth/UserMetaData {
public final class dev/gitlive/firebase/auth/android {
public static final fun auth (Ldev/gitlive/firebase/Firebase;Ldev/gitlive/firebase/FirebaseApp;)Ldev/gitlive/firebase/auth/FirebaseAuth;
+ public static final fun getAndroid (Ldev/gitlive/firebase/auth/AdditionalUserInfo;)Lcom/google/firebase/auth/AdditionalUserInfo;
public static final fun getAndroid (Ldev/gitlive/firebase/auth/AuthResult;)Lcom/google/firebase/auth/AuthResult;
public static final fun getAndroid (Ldev/gitlive/firebase/auth/AuthTokenResult;)Lcom/google/firebase/auth/GetTokenResult;
public static final fun getAndroid (Ldev/gitlive/firebase/auth/FirebaseAuth;)Lcom/google/firebase/auth/FirebaseAuth;
diff --git a/firebase-auth/api/jvm/firebase-auth.api b/firebase-auth/api/jvm/firebase-auth.api
index 170ac9afa..f629f1f01 100644
--- a/firebase-auth/api/jvm/firebase-auth.api
+++ b/firebase-auth/api/jvm/firebase-auth.api
@@ -51,6 +51,14 @@ public final class dev/gitlive/firebase/auth/ActionCodeSettings {
public fun toString ()Ljava/lang/String;
}
+public final class dev/gitlive/firebase/auth/AdditionalUserInfo {
+ public fun ()V
+ public final fun getProfile ()Ljava/util/Map;
+ public final fun getProviderId ()Ljava/lang/String;
+ public final fun getUsername ()Ljava/lang/String;
+ public final fun isNewUser ()Z
+}
+
public final class dev/gitlive/firebase/auth/AndroidPackageName {
public fun (Ljava/lang/String;ZLjava/lang/String;)V
public synthetic fun (Ljava/lang/String;ZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -74,6 +82,9 @@ public class dev/gitlive/firebase/auth/AuthCredential {
}
public final class dev/gitlive/firebase/auth/AuthResult {
+ public fun (Lcom/google/firebase/auth/AuthResult;)V
+ public final fun getAdditionalUserInfo ()Ldev/gitlive/firebase/auth/AdditionalUserInfo;
+ public final fun getCredential ()Ldev/gitlive/firebase/auth/AuthCredential;
public final fun getUser ()Ldev/gitlive/firebase/auth/FirebaseUser;
}
diff --git a/firebase-auth/package.json b/firebase-auth/package.json
index 23da53f91..364873210 100644
--- a/firebase-auth/package.json
+++ b/firebase-auth/package.json
@@ -1,6 +1,6 @@
{
"name": "@gitlive/firebase-auth",
- "version": "2.0.0",
+ "version": "2.2.0-SNAPSHOT",
"description": "Wrapper around firebase for usage in Kotlin Multiplatform projects",
"main": "firebase-auth.js",
"scripts": {
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk",
"dependencies": {
- "@gitlive/firebase-app": "2.0.0",
+ "@gitlive/firebase-app": "2.2.0-SNAPSHOT",
"firebase": "9.19.1",
"kotlin": "1.8.20",
"kotlinx-coroutines-core": "1.6.4"
diff --git a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt
index fec2e73a0..cc4f2957d 100644
--- a/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt
+++ b/firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt
@@ -118,9 +118,29 @@ public actual class FirebaseAuth internal constructor(internal val android: com.
public val AuthResult.android: com.google.firebase.auth.AuthResult get() = android
-public actual class AuthResult internal constructor(internal val android: com.google.firebase.auth.AuthResult) {
+public actual class AuthResult(internal val android: com.google.firebase.auth.AuthResult) {
public actual val user: FirebaseUser?
get() = android.user?.let { FirebaseUser(it) }
+ public actual val credential: AuthCredential?
+ get() = android.credential?.let { AuthCredential(it) }
+ public actual val additionalUserInfo: AdditionalUserInfo?
+ get() = android.additionalUserInfo?.let { AdditionalUserInfo(it) }
+}
+
+public val AdditionalUserInfo.android: com.google.firebase.auth.AdditionalUserInfo
+ get() = android
+
+public actual class AdditionalUserInfo(
+ internal val android: com.google.firebase.auth.AdditionalUserInfo,
+) {
+ public actual val providerId: String?
+ get() = android.providerId
+ public actual val username: String?
+ get() = android.username
+ public actual val profile: Map?
+ get() = android.profile
+ public actual val isNewUser: Boolean
+ get() = android.isNewUser
}
public val AuthTokenResult.android: com.google.firebase.auth.GetTokenResult get() = android
diff --git a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt
index f66ce3c03..2665d2eb8 100644
--- a/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt
+++ b/firebase-auth/src/commonMain/kotlin/dev/gitlive/firebase/auth/auth.kt
@@ -41,6 +41,15 @@ public expect class FirebaseAuth {
public expect class AuthResult {
public val user: FirebaseUser?
+ public val credential: AuthCredential?
+ public val additionalUserInfo: AdditionalUserInfo?
+}
+
+public expect class AdditionalUserInfo {
+ public val providerId: String?
+ public val username: String?
+ public val profile: Map?
+ public val isNewUser: Boolean
}
public expect class AuthTokenResult {
diff --git a/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt
index 47db21755..96f259176 100644
--- a/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt
+++ b/firebase-auth/src/commonTest/kotlin/dev/gitlive/firebase/auth/auth.kt
@@ -112,6 +112,22 @@ class FirebaseAuthTest {
assertEquals(uid, result.user!!.uid)
}
+ @Test
+ fun testAuthResultStructure() = runTest {
+ val uid = getTestUid("test@test.com", "test123")
+ val result = auth.signInWithEmailAndPassword("test@test.com", "test123")
+ assertNotNull(result.user, "User does not exist.")
+ assertEquals(uid, result.user!!.uid, "uid does not match.")
+ assertNull(result.credential, "Credential throws.")
+ // Just test if it does not throw
+ result.additionalUserInfo?.let { additionalUserInfo ->
+ additionalUserInfo.providerId
+ additionalUserInfo.username
+ additionalUserInfo.profile
+ additionalUserInfo.isNewUser
+ }
+ }
+
@Test
fun testIsSignInWithEmailLink() {
val validLink = "http://localhost:9099/emulator/action?mode=signIn&lang=en&oobCode=_vr0QcFcxcVeLZbrcU-GpTaZiuxlHquqdC8MSy0YM_vzWCTAQgV9Jq&apiKey=fake-api-key&continueUrl=https%3A%2F%2Fexample.com%2Fsignin"
diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt
index b659b0c68..30ff27bc1 100644
--- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt
+++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt
@@ -17,6 +17,7 @@ import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.Flow
import platform.Foundation.NSError
+import platform.Foundation.NSString
import platform.Foundation.NSURL
public val FirebaseAuth.ios: FIRAuth get() = FIRAuth.auth()
@@ -31,7 +32,7 @@ public actual fun Firebase.auth(app: FirebaseApp): FirebaseAuth = FirebaseAuth(
public actual class FirebaseAuth internal constructor(internal val ios: FIRAuth) {
public actual val currentUser: FirebaseUser?
- get() = ios.currentUser?.let { FirebaseUser(it) }
+ get() = ios.currentUser()?.let { FirebaseUser(it) }
public actual val authStateChanged: Flow get() = callbackFlow {
val handle = ios.addAuthStateDidChangeListener { _, user -> trySend(user?.let { FirebaseUser(it) }) }
@@ -44,7 +45,7 @@ public actual class FirebaseAuth internal constructor(internal val ios: FIRAuth)
}
public actual var languageCode: String
- get() = ios.languageCode ?: ""
+ get() = ios.languageCode() ?: ""
set(value) {
ios.setLanguageCode(value)
}
@@ -90,25 +91,53 @@ public actual class FirebaseAuth internal constructor(internal val ios: FIRAuth)
public actual suspend fun checkActionCode(code: String): T {
val result: FIRActionCodeInfo = ios.awaitResult { checkActionCode(code, it) }
@Suppress("UNCHECKED_CAST")
- return when (result.operation) {
+ return when (result.operation()) {
FIRActionCodeOperationEmailLink -> SignInWithEmailLink
- FIRActionCodeOperationVerifyEmail -> VerifyEmail(result.email!!)
- FIRActionCodeOperationPasswordReset -> PasswordReset(result.email!!)
- FIRActionCodeOperationRecoverEmail -> RecoverEmail(result.email!!, result.previousEmail!!)
- FIRActionCodeOperationVerifyAndChangeEmail -> VerifyBeforeChangeEmail(result.email!!, result.previousEmail!!)
- FIRActionCodeOperationRevertSecondFactorAddition -> RevertSecondFactorAddition(result.email!!, null)
- FIRActionCodeOperationUnknown -> throw UnsupportedOperationException(result.operation.toString())
- else -> throw UnsupportedOperationException(result.operation.toString())
+ FIRActionCodeOperationVerifyEmail -> VerifyEmail(result.email())
+ FIRActionCodeOperationPasswordReset -> PasswordReset(result.email())
+ FIRActionCodeOperationRecoverEmail -> RecoverEmail(result.email(), result.previousEmail()!!)
+ FIRActionCodeOperationVerifyAndChangeEmail -> VerifyBeforeChangeEmail(result.email(), result.previousEmail()!!)
+ FIRActionCodeOperationRevertSecondFactorAddition -> RevertSecondFactorAddition(result.email(), null)
+ FIRActionCodeOperationUnknown -> throw UnsupportedOperationException(result.operation().toString())
+ else -> throw UnsupportedOperationException(result.operation().toString())
} as T
}
public actual fun useEmulator(host: String, port: Int): Unit = ios.useEmulatorWithHost(host, port.toLong())
}
+
public val AuthResult.ios: FIRAuthDataResult get() = ios
-public actual class AuthResult internal constructor(internal val ios: FIRAuthDataResult) {
+public actual class AuthResult(internal val ios: FIRAuthDataResult) {
public actual val user: FirebaseUser?
- get() = FirebaseUser(ios.user)
+ get() = FirebaseUser(ios.user())
+ public actual val credential: AuthCredential?
+ get() = ios.credential()?.let { AuthCredential(it) }
+ public actual val additionalUserInfo: AdditionalUserInfo?
+ get() = ios.additionalUserInfo()?.let { AdditionalUserInfo(it) }
+}
+
+public val AdditionalUserInfo.ios: FIRAdditionalUserInfo get() = ios
+
+public actual class AdditionalUserInfo(
+ internal val ios: FIRAdditionalUserInfo,
+) {
+ public actual val providerId: String?
+ get() = ios.providerID()
+ public actual val username: String?
+ get() = ios.username()
+ public actual val profile: Map?
+ get() = ios.profile()
+ ?.mapNotNull { (key, value) ->
+ if (key is NSString && value != null) {
+ key.toString() to value
+ } else {
+ null
+ }
+ }
+ ?.toMap()
+ public actual val isNewUser: Boolean
+ get() = ios.newUser()
}
public val AuthTokenResult.ios: FIRAuthTokenResult get() = ios
@@ -116,23 +145,23 @@ public actual class AuthTokenResult(internal val ios: FIRAuthTokenResult) {
// actual val authTimestamp: Long
// get() = ios.authDate
public actual val claims: Map
- get() = ios.claims.map { it.key.toString() to it.value as Any }.toMap()
+ get() = ios.claims().map { it.key.toString() to it.value as Any }.toMap()
// actual val expirationTimestamp: Long
// get() = ios.expirationDate
// actual val issuedAtTimestamp: Long
// get() = ios.issuedAtDate
public actual val signInProvider: String?
- get() = ios.signInProvider
+ get() = ios.signInProvider()
public actual val token: String?
- get() = ios.token
+ get() = ios.token()
}
internal fun ActionCodeSettings.toIos() = FIRActionCodeSettings().also {
- it.URL = NSURL.URLWithString(url)
+ it.setURL(NSURL.URLWithString(url))
androidPackageName?.run { it.setAndroidPackageName(packageName, installIfNotAvailable, minimumVersion) }
- it.dynamicLinkDomain = dynamicLinkDomain
- it.handleCodeInApp = canHandleCodeInApp
+ it.setDynamicLinkDomain(dynamicLinkDomain)
+ it.setHandleCodeInApp(canHandleCodeInApp)
iOSBundleId?.run { it.setIOSBundleID(this) }
}
@@ -184,47 +213,55 @@ internal suspend inline fun T.await(function: T.(callback: (NSError?) -> Uni
}
private fun NSError.toException() = when (domain) {
+ // codes from AuthErrors.swift: https://github.com/firebase/firebase-ios-sdk/blob/
+ // 2f6ac4c2c61cd57c7ea727009e187b7e1163d613/FirebaseAuth/Sources/Swift/Utilities/
+ // AuthErrors.swift#L51
FIRAuthErrorDomain -> when (code) {
- FIRAuthErrorCodeInvalidActionCode,
- FIRAuthErrorCodeExpiredActionCode,
+ 17030L, // AuthErrorCode.invalidActionCode
+ 17029L, // AuthErrorCode.expiredActionCode
-> FirebaseAuthActionCodeException(toString())
- FIRAuthErrorCodeInvalidEmail -> FirebaseAuthEmailException(toString())
-
- FIRAuthErrorCodeCaptchaCheckFailed,
- FIRAuthErrorCodeInvalidPhoneNumber,
- FIRAuthErrorCodeMissingPhoneNumber,
- FIRAuthErrorCodeInvalidVerificationID,
- FIRAuthErrorCodeInvalidVerificationCode,
- FIRAuthErrorCodeMissingVerificationID,
- FIRAuthErrorCodeMissingVerificationCode,
- FIRAuthErrorCodeUserTokenExpired,
- FIRAuthErrorCodeInvalidCredential,
+ 17008L, // AuthErrorCode.invalidEmail
+ -> FirebaseAuthEmailException(toString())
+
+ 17056L, // AuthErrorCode.captchaCheckFailed
+ 17042L, // AuthErrorCode.invalidPhoneNumber
+ 17041L, // AuthErrorCode.missingPhoneNumber
+ 17046L, // AuthErrorCode.invalidVerificationID
+ 17044L, // AuthErrorCode.invalidVerificationCode
+ 17045L, // AuthErrorCode.missingVerificationID
+ 17043L, // AuthErrorCode.missingVerificationCode
+ 17021L, // AuthErrorCode.userTokenExpired
+ 17004L, // AuthErrorCode.invalidCredential
-> FirebaseAuthInvalidCredentialsException(toString())
- FIRAuthErrorCodeWeakPassword -> FirebaseAuthWeakPasswordException(toString())
+ 17026L, // AuthErrorCode.weakPassword
+ -> FirebaseAuthWeakPasswordException(toString())
- FIRAuthErrorCodeInvalidUserToken -> FirebaseAuthInvalidUserException(toString())
+ 17017L, // AuthErrorCode.invalidUserToken
+ -> FirebaseAuthInvalidUserException(toString())
- FIRAuthErrorCodeRequiresRecentLogin -> FirebaseAuthRecentLoginRequiredException(toString())
+ 17014L, // AuthErrorCode.requiresRecentLogin
+ -> FirebaseAuthRecentLoginRequiredException(toString())
- FIRAuthErrorCodeSecondFactorAlreadyEnrolled,
- FIRAuthErrorCodeSecondFactorRequired,
- FIRAuthErrorCodeMaximumSecondFactorCountExceeded,
- FIRAuthErrorCodeMultiFactorInfoNotFound,
+ 17087L, // AuthErrorCode.secondFactorAlreadyEnrolled
+ 17078L, // AuthErrorCode.secondFactorRequired
+ 17088L, // AuthErrorCode.maximumSecondFactorCountExceeded
+ 17084L, // AuthErrorCode.multiFactorInfoNotFound
-> FirebaseAuthMultiFactorException(toString())
- FIRAuthErrorCodeEmailAlreadyInUse,
- FIRAuthErrorCodeAccountExistsWithDifferentCredential,
- FIRAuthErrorCodeCredentialAlreadyInUse,
+ 17007L, // AuthErrorCode.emailAlreadyInUse
+ 17012L, // AuthErrorCode.accountExistsWithDifferentCredential
+ 17025L, // AuthErrorCode.credentialAlreadyInUse
-> FirebaseAuthUserCollisionException(toString())
- FIRAuthErrorCodeWebContextAlreadyPresented,
- FIRAuthErrorCodeWebContextCancelled,
- FIRAuthErrorCodeWebInternalError,
+ 17057L, // AuthErrorCode.webContextAlreadyPresented
+ 17058L, // AuthErrorCode.webContextCancelled
+ 17062L, // AuthErrorCode.webInternalError
-> FirebaseAuthWebException(toString())
- FIRAuthErrorCodeNetworkError -> FirebaseNetworkException(toString())
+ 17020L, // AuthErrorCode.networkError
+ -> FirebaseNetworkException(toString())
else -> FirebaseAuthException(toString())
}
diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt
index 08387a0e1..5a2084bb9 100644
--- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt
+++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/credentials.kt
@@ -8,7 +8,7 @@ import cocoapods.FirebaseAuth.*
public actual open class AuthCredential(public open val ios: FIRAuthCredential) {
public actual val providerId: String
- get() = ios.provider
+ get() = ios.provider()
}
public actual class PhoneAuthCredential(override val ios: FIRPhoneAuthCredential) : AuthCredential(ios)
diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt
index f389b6abb..3d2c814e5 100644
--- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt
+++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt
@@ -10,7 +10,7 @@ public val MultiFactor.ios: FIRMultiFactor get() = ios
public actual class MultiFactor(internal val ios: FIRMultiFactor) {
public actual val enrolledFactors: List
- get() = ios.enrolledFactors.mapNotNull { info -> (info as? FIRMultiFactorInfo)?.let { MultiFactorInfo(it) } }
+ get() = ios.enrolledFactors().mapNotNull { info -> (info as? FIRMultiFactorInfo)?.let { MultiFactorInfo(it) } }
public actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?): Unit = ios.await { enrollWithAssertion(multiFactorAssertion.ios, displayName, it) }
public actual suspend fun getSession(): MultiFactorSession = MultiFactorSession(ios.awaitResult { getSessionWithCompletion(completion = it) })
public actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo): Unit = ios.await { unenrollWithInfo(multiFactorInfo.ios, it) }
@@ -21,20 +21,20 @@ public val MultiFactorInfo.ios: FIRMultiFactorInfo get() = ios
public actual class MultiFactorInfo(internal val ios: FIRMultiFactorInfo) {
public actual val displayName: String?
- get() = ios.displayName
+ get() = ios.displayName()
public actual val enrollmentTime: Double
- get() = ios.enrollmentDate.timeIntervalSinceReferenceDate
+ get() = ios.enrollmentDate().timeIntervalSinceReferenceDate
public actual val factorId: String
- get() = ios.factorID
+ get() = ios.factorID()
public actual val uid: String
- get() = ios.UID
+ get() = ios.UID()
}
public val MultiFactorAssertion.ios: FIRMultiFactorAssertion get() = ios
public actual class MultiFactorAssertion(internal val ios: FIRMultiFactorAssertion) {
public actual val factorId: String
- get() = ios.factorID
+ get() = ios.factorID()
}
public val MultiFactorSession.ios: FIRMultiFactorSession get() = ios
@@ -44,9 +44,9 @@ public actual class MultiFactorSession(internal val ios: FIRMultiFactorSession)
public val MultiFactorResolver.ios: FIRMultiFactorResolver get() = ios
public actual class MultiFactorResolver(internal val ios: FIRMultiFactorResolver) {
- public actual val auth: FirebaseAuth = FirebaseAuth(ios.auth)
- public actual val hints: List = ios.hints.mapNotNull { hint -> (hint as? FIRMultiFactorInfo)?.let { MultiFactorInfo(it) } }
- public actual val session: MultiFactorSession = MultiFactorSession(ios.session)
+ public actual val auth: FirebaseAuth = FirebaseAuth(ios.auth())
+ public actual val hints: List = ios.hints().mapNotNull { hint -> (hint as? FIRMultiFactorInfo)?.let { MultiFactorInfo(it) } }
+ public actual val session: MultiFactorSession = MultiFactorSession(ios.session())
public actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = AuthResult(ios.awaitResult { resolveSignInWithAssertion(assertion.ios, it) })
}
diff --git a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt
index f2f6c67cc..d37fc20c0 100644
--- a/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt
+++ b/firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/user.kt
@@ -14,27 +14,27 @@ public val FirebaseUser.ios: FIRUser get() = ios
public actual class FirebaseUser internal constructor(internal val ios: FIRUser) {
public actual val uid: String
- get() = ios.uid
+ get() = ios.uid()
public actual val displayName: String?
- get() = ios.displayName
+ get() = ios.displayName()
public actual val email: String?
- get() = ios.email
+ get() = ios.email()
public actual val phoneNumber: String?
- get() = ios.phoneNumber
+ get() = ios.phoneNumber()
public actual val photoURL: String?
- get() = ios.photoURL?.absoluteString
+ get() = ios.photoURL()?.absoluteString
public actual val isAnonymous: Boolean
- get() = ios.anonymous
+ get() = ios.anonymous()
public actual val isEmailVerified: Boolean
- get() = ios.emailVerified
+ get() = ios.emailVerified()
public actual val metaData: UserMetaData?
- get() = UserMetaData(ios.metadata)
+ get() = UserMetaData(ios.metadata())
public actual val multiFactor: MultiFactor
- get() = MultiFactor(ios.multiFactor)
+ get() = MultiFactor(ios.multiFactor())
public actual val providerData: List
- get() = ios.providerData.mapNotNull { provider -> (provider as? FIRUserInfoProtocol)?.let { UserInfo(it) } }
+ get() = ios.providerData().mapNotNull { provider -> (provider as? FIRUserInfoProtocol)?.let { UserInfo(it) } }
public actual val providerId: String
- get() = ios.providerID
+ get() = ios.providerID()
public actual suspend fun delete(): Unit = ios.await { deleteWithCompletion(it) }
@@ -85,24 +85,24 @@ public val UserInfo.ios: FIRUserInfoProtocol get() = ios
public actual class UserInfo(internal val ios: FIRUserInfoProtocol) {
public actual val displayName: String?
- get() = ios.displayName
+ get() = ios.displayName()
public actual val email: String?
- get() = ios.email
+ get() = ios.email()
public actual val phoneNumber: String?
- get() = ios.phoneNumber
+ get() = ios.phoneNumber()
public actual val photoURL: String?
- get() = ios.photoURL?.absoluteString
+ get() = ios.photoURL()?.absoluteString
public actual val providerId: String
- get() = ios.providerID
+ get() = ios.providerID()
public actual val uid: String
- get() = ios.uid
+ get() = ios.uid()
}
public val UserMetaData.ios: FIRUserMetadata get() = ios
public actual class UserMetaData(internal val ios: FIRUserMetadata) {
public actual val creationTime: Double?
- get() = ios.creationDate?.timeIntervalSinceReferenceDate
+ get() = ios.creationDate()?.timeIntervalSinceReferenceDate
public actual val lastSignInTime: Double?
- get() = ios.lastSignInDate?.timeIntervalSinceReferenceDate
+ get() = ios.lastSignInDate()?.timeIntervalSinceReferenceDate
}
diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt
index a222d4d6e..4d0223d28 100644
--- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt
+++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt
@@ -33,8 +33,10 @@ import kotlinx.coroutines.await
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
+import kotlin.js.Json
import kotlin.js.json
import dev.gitlive.firebase.auth.externals.AuthResult as JsAuthResult
+import dev.gitlive.firebase.auth.externals.AdditionalUserInfo as JsAdditionalUserInfo
public actual val Firebase.auth: FirebaseAuth
get() = rethrow { FirebaseAuth(getAuth()) }
@@ -133,9 +135,34 @@ public actual class FirebaseAuth internal constructor(internal val js: Auth) {
public val AuthResult.js: JsAuthResult get() = js
-public actual class AuthResult internal constructor(internal val js: JsAuthResult) {
+public actual class AuthResult(internal val js: JsAuthResult) {
public actual val user: FirebaseUser?
get() = rethrow { js.user?.let { FirebaseUser(it) } }
+ public actual val credential: AuthCredential?
+ get() = rethrow { js.credential?.let { AuthCredential(it) } }
+ public actual val additionalUserInfo: AdditionalUserInfo?
+ get() = rethrow { js.additionalUserInfo?.let { AdditionalUserInfo(it) } }
+}
+
+public val AdditionalUserInfo.js: JsAdditionalUserInfo get() = js
+
+public actual class AdditionalUserInfo(
+ internal val js: JsAdditionalUserInfo,
+) {
+ public actual val providerId: String?
+ get() = js.providerId
+ public actual val username: String?
+ get() = js.username
+ public actual val profile: Map?
+ get() = rethrow {
+ val profile = js.profile ?: return@rethrow null
+ val entries = js("Object.entries") as (Json) -> Array>
+ return@rethrow entries
+ .invoke(profile)
+ .associate { entry -> entry[0] as String to entry[1] }
+ }
+ public actual val isNewUser: Boolean
+ get() = js.newUser
}
public val AuthTokenResult.js: IdTokenResult get() = js
diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals/auth.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals/auth.kt
index e535e6c22..20c3f14c3 100644
--- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals/auth.kt
+++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals/auth.kt
@@ -170,6 +170,14 @@ public external interface AuthResult {
public val credential: AuthCredential?
public val operationType: String?
public val user: User?
+ public val additionalUserInfo: AdditionalUserInfo?
+}
+
+public external interface AdditionalUserInfo {
+ public val providerId: String?
+ public val username: String?
+ public val profile: Json?
+ public val newUser: Boolean
}
public external interface AuthCredential {
diff --git a/firebase-auth/src/jvmMain/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/jvmMain/kotlin/dev/gitlive/firebase/auth/auth.kt
index 3eda71f6b..21043d4d4 100644
--- a/firebase-auth/src/jvmMain/kotlin/dev/gitlive/firebase/auth/auth.kt
+++ b/firebase-auth/src/jvmMain/kotlin/dev/gitlive/firebase/auth/auth.kt
@@ -18,7 +18,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.tasks.await
-public actual val Firebase.auth
+public actual val Firebase.auth: FirebaseAuth
get() = FirebaseAuth(com.google.firebase.auth.FirebaseAuth.getInstance())
public actual fun Firebase.auth(app: FirebaseApp) =
@@ -127,9 +127,24 @@ public actual class FirebaseAuth internal constructor(internal val android: com.
public val AuthResult.android: com.google.firebase.auth.AuthResult get() = android
-public actual class AuthResult internal constructor(internal val android: com.google.firebase.auth.AuthResult) {
+public actual class AuthResult(internal val android: com.google.firebase.auth.AuthResult) {
public actual val user: FirebaseUser?
get() = android.user?.let { FirebaseUser(it) }
+ public actual val credential: AuthCredential?
+ get() = throw NotImplementedError()
+ public actual val additionalUserInfo: AdditionalUserInfo?
+ get() = throw NotImplementedError()
+}
+
+public actual class AdditionalUserInfo {
+ public actual val providerId: String?
+ get() = throw NotImplementedError()
+ public actual val username: String?
+ get() = throw NotImplementedError()
+ public actual val profile: Map?
+ get() = throw NotImplementedError()
+ public actual val isNewUser: Boolean
+ get() = throw NotImplementedError()
}
public val AuthTokenResult.android: com.google.firebase.auth.GetTokenResult get() = android
diff --git a/firebase-common-internal/package.json b/firebase-common-internal/package.json
index c1a555b9e..2d0738776 100644
--- a/firebase-common-internal/package.json
+++ b/firebase-common-internal/package.json
@@ -1,6 +1,6 @@
{
"name": "@gitlive/firebase-common-internal",
- "version": "2.0.0",
+ "version": "2.2.0-SNAPSHOT",
"description": "Wrapper around firebase for usage in Kotlin Multiplatform projects",
"main": "firebase-common-internal.js",
"scripts": {
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/GitLiveApp/firebase-kotlin-multiplatform-sdk",
"dependencies": {
- "@gitlive/firebase-common": "2.0.0",
+ "@gitlive/firebase-common": "2.2.0-SNAPSHOT",
"firebase": "9.19.1",
"kotlin": "1.8.20",
"kotlinx-coroutines-core": "1.6.4",
diff --git a/firebase-common-internal/src/commonMain/kotlin/dev/gitlive/firebase/internal/encoders.kt b/firebase-common-internal/src/commonMain/kotlin/dev/gitlive/firebase/internal/encoders.kt
index 474aeea57..767688ad0 100644
--- a/firebase-common-internal/src/commonMain/kotlin/dev/gitlive/firebase/internal/encoders.kt
+++ b/firebase-common-internal/src/commonMain/kotlin/dev/gitlive/firebase/internal/encoders.kt
@@ -6,7 +6,6 @@ package dev.gitlive.firebase.internal
import dev.gitlive.firebase.EncodeSettings
import dev.gitlive.firebase.FirebaseEncoder
-import dev.gitlive.firebase.ValueWithSerializer
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.descriptors.SerialDescriptor
@@ -63,14 +62,7 @@ public inline fun encodeAsObject(value: T, buildSettings: Enco
@PublishedApi
internal inline fun encode(value: T, encodeSettings: EncodeSettings): Any? = value?.let {
FirebaseEncoderImpl(encodeSettings).apply {
- if (it is ValueWithSerializer<*> && it.value is T) {
- @Suppress("UNCHECKED_CAST")
- (it as ValueWithSerializer).let {
- encodeSerializableValue(it.serializer, it.value)
- }
- } else {
- encodeSerializableValue(it.firebaseSerializer(), it)
- }
+ encodeSerializableValue(it.firebaseSerializer(), it)
}.value
}
@@ -164,12 +156,6 @@ internal open class FirebaseCompositeEncoder(
private val set: (descriptor: SerialDescriptor, index: Int, value: Any?) -> Unit,
) : CompositeEncoder {
-// private fun SerializationStrategy.toFirebase(): SerializationStrategy = when(descriptor.kind) {
-// StructureKind.MAP -> FirebaseMapSerializer(descriptor.getElementDescriptor(1)) as SerializationStrategy
-// StructureKind.LIST -> FirebaseListSerializer(descriptor.getElementDescriptor(0)) as SerializationStrategy
-// else -> this
-// }
-
override val serializersModule: SerializersModule = settings.serializersModule
override fun endStructure(descriptor: SerialDescriptor): Unit = end()
diff --git a/firebase-common-internal/src/commonTest/kotlin/dev/gitlive/firebase/internal/EncodersTest.kt b/firebase-common-internal/src/commonTest/kotlin/dev/gitlive/firebase/internal/EncodersTest.kt
index 145d57b74..2017f8dc6 100644
--- a/firebase-common-internal/src/commonTest/kotlin/dev/gitlive/firebase/internal/EncodersTest.kt
+++ b/firebase-common-internal/src/commonTest/kotlin/dev/gitlive/firebase/internal/EncodersTest.kt
@@ -262,6 +262,47 @@ class EncodersTest {
assertEquals(nestedClass, decoded)
}
+ @Test
+ fun encodeDecodeNestedClassWithEmptyCollections() {
+ val module = SerializersModule {
+ polymorphic(AbstractClass::class, AbstractClass.serializer()) {
+ subclass(ImplementedClass::class, ImplementedClass.serializer())
+ }
+ }
+
+ val testData = TestData(mapOf(), mapOf(), true, null, ValueClass(42))
+ val sealedClass: SealedClass = SealedClass.Test("value")
+ val abstractClass: AbstractClass = ImplementedClass("value", true)
+ val nestedClass = NestedClass(testData, sealedClass, abstractClass, listOf(), listOf(), listOf(), mapOf(), mapOf(), mapOf())
+ val encoded = encode(NestedClass.serializer(), nestedClass) {
+ encodeDefaults = true
+ serializersModule = module
+ }
+
+ val testDataEncoded = nativeMapOf("map" to nativeMapOf(), "otherMap" to nativeMapOf(), "bool" to true, "nullableBool" to null, "valueClass" to 42)
+ val sealedEncoded = nativeMapOf("type" to "test", "value" to "value")
+ val abstractEncoded = nativeMapOf("type" to "implemented", "abstractValue" to "value", "otherValue" to true)
+ nativeAssertEquals(
+ nativeMapOf(
+ "testData" to testDataEncoded,
+ "sealed" to sealedEncoded,
+ "abstract" to abstractEncoded,
+ "testDataList" to nativeListOf(),
+ "sealedList" to nativeListOf(),
+ "abstractList" to nativeListOf(),
+ "testDataMap" to nativeMapOf(),
+ "sealedMap" to nativeMapOf(),
+ "abstractMap" to nativeMapOf(),
+ ),
+ encoded,
+ )
+
+ val decoded = decode(NestedClass.serializer(), encoded) {
+ serializersModule = module
+ }
+ assertEquals(nestedClass, decoded)
+ }
+
@Test
fun reencodeTransformationList() {
val reencoded = reencodeTransformation>(nativeListOf("One", "Two", "Three")) {
diff --git a/firebase-common-internal/src/jsMain/kotlin/dev/gitlive/firebase/internal/_encoders.kt b/firebase-common-internal/src/jsMain/kotlin/dev/gitlive/firebase/internal/_encoders.kt
index 7121128d0..091d9c2da 100644
--- a/firebase-common-internal/src/jsMain/kotlin/dev/gitlive/firebase/internal/_encoders.kt
+++ b/firebase-common-internal/src/jsMain/kotlin/dev/gitlive/firebase/internal/_encoders.kt
@@ -28,7 +28,7 @@ internal actual fun FirebaseEncoderImpl.structureEncoder(descriptor: SerialDescr
else -> TODO("The firebase-kotlin-sdk does not support $descriptor for serialization yet")
}
-private fun FirebaseEncoderImpl.encodeAsList(descriptor: SerialDescriptor): FirebaseCompositeEncoder = Array(descriptor.elementsCount) { null }
+private fun FirebaseEncoderImpl.encodeAsList(descriptor: SerialDescriptor): FirebaseCompositeEncoder = Array(descriptor.elementsCount - 1) { null }
.also { value = it }
.let { FirebaseCompositeEncoder(settings) { _, index, value -> it[index] = value } }
private fun FirebaseEncoderImpl.encodeAsMap(descriptor: SerialDescriptor): FirebaseCompositeEncoder = json()
diff --git a/firebase-common/api/android/firebase-common.api b/firebase-common/api/android/firebase-common.api
index 9724b86d4..14df6bc61 100644
--- a/firebase-common/api/android/firebase-common.api
+++ b/firebase-common/api/android/firebase-common.api
@@ -51,20 +51,3 @@ public final class dev/gitlive/firebase/FirebaseEncoder$DefaultImpls {
public static fun encodeSerializableValue (Ldev/gitlive/firebase/FirebaseEncoder;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V
}
-public final class dev/gitlive/firebase/ValueWithSerializer {
- public fun (Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)V
- public final fun component1 ()Ljava/lang/Object;
- public final fun component2 ()Lkotlinx/serialization/SerializationStrategy;
- public final fun copy (Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)Ldev/gitlive/firebase/ValueWithSerializer;
- public static synthetic fun copy$default (Ldev/gitlive/firebase/ValueWithSerializer;Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;ILjava/lang/Object;)Ldev/gitlive/firebase/ValueWithSerializer;
- public fun equals (Ljava/lang/Object;)Z
- public final fun getSerializer ()Lkotlinx/serialization/SerializationStrategy;
- public final fun getValue ()Ljava/lang/Object;
- public fun hashCode ()I
- public fun toString ()Ljava/lang/String;
-}
-
-public final class dev/gitlive/firebase/ValueWithSerializerKt {
- public static final fun withSerializer (Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)Ljava/lang/Object;
-}
-
diff --git a/firebase-common/api/jvm/firebase-common.api b/firebase-common/api/jvm/firebase-common.api
index 9724b86d4..14df6bc61 100644
--- a/firebase-common/api/jvm/firebase-common.api
+++ b/firebase-common/api/jvm/firebase-common.api
@@ -51,20 +51,3 @@ public final class dev/gitlive/firebase/FirebaseEncoder$DefaultImpls {
public static fun encodeSerializableValue (Ldev/gitlive/firebase/FirebaseEncoder;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V
}
-public final class dev/gitlive/firebase/ValueWithSerializer {
- public fun (Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)V
- public final fun component1 ()Ljava/lang/Object;
- public final fun component2 ()Lkotlinx/serialization/SerializationStrategy;
- public final fun copy (Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)Ldev/gitlive/firebase/ValueWithSerializer;
- public static synthetic fun copy$default (Ldev/gitlive/firebase/ValueWithSerializer;Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;ILjava/lang/Object;)Ldev/gitlive/firebase/ValueWithSerializer;
- public fun equals (Ljava/lang/Object;)Z
- public final fun getSerializer ()Lkotlinx/serialization/SerializationStrategy;
- public final fun getValue ()Ljava/lang/Object;
- public fun hashCode ()I
- public fun toString ()Ljava/lang/String;
-}
-
-public final class dev/gitlive/firebase/ValueWithSerializerKt {
- public static final fun withSerializer (Ljava/lang/Object;Lkotlinx/serialization/SerializationStrategy;)Ljava/lang/Object;
-}
-
diff --git a/firebase-common/package.json b/firebase-common/package.json
index ac1374d45..b2edcd792 100644
--- a/firebase-common/package.json
+++ b/firebase-common/package.json
@@ -1,6 +1,6 @@
{
"name": "@gitlive/firebase-common",
- "version": "2.0.0",
+ "version": "2.2.0-SNAPSHOT",
"description": "Wrapper around firebase for usage in Kotlin Multiplatform projects",
"main": "firebase-common.js",
"scripts": {
diff --git a/firebase-common/src/commonMain/kotlin/dev/gitlive/firebase/ValueWithSerializer.kt b/firebase-common/src/commonMain/kotlin/dev/gitlive/firebase/ValueWithSerializer.kt
deleted file mode 100644
index 84ed4713b..000000000
--- a/firebase-common/src/commonMain/kotlin/dev/gitlive/firebase/ValueWithSerializer.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package dev.gitlive.firebase
-
-import kotlinx.serialization.SerializationStrategy
-
-/**
- * An extension which which serializer to use for value. Handy in updating fields by name or path
- * where using annotation is not possible
- * @return a value with a custom serializer.
- */
-public fun T.withSerializer(serializer: SerializationStrategy): Any = ValueWithSerializer(this, serializer)
-public data class ValueWithSerializer(val value: T, val serializer: SerializationStrategy)
diff --git a/firebase-config/build.gradle.kts b/firebase-config/build.gradle.kts
index a28086463..f942264e4 100644
--- a/firebase-config/build.gradle.kts
+++ b/firebase-config/build.gradle.kts
@@ -29,7 +29,6 @@ android {
}
compileOptions {
- isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
@@ -45,10 +44,6 @@ android {
}
}
-dependencies {
- coreLibraryDesugaring(libs.android.desugarjdk)
-}
-
val supportIosTarget = project.property("skipIosTarget") != "true"
kotlin {
diff --git a/firebase-config/package.json b/firebase-config/package.json
index 69582d9fc..c016fe275 100644
--- a/firebase-config/package.json
+++ b/firebase-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@gitlive/firebase-config",
- "version": "2.0.0",
+ "version": "2.2.0-SNAPSHOT",
"description": "Wrapper around firebase for usage in Kotlin Multiplatform projects",
"main": "firebase-config.js",
"scripts": {
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk",
"dependencies": {
- "@gitlive/firebase-app": "2.0.0",
+ "@gitlive/firebase-app": "2.2.0-SNAPSHOT",
"firebase": "9.19.1",
"kotlin": "1.8.20",
"kotlinx-coroutines-core": "1.6.4"
diff --git a/firebase-crashlytics/package.json b/firebase-crashlytics/package.json
index 989eda9b0..4c8a35d7f 100644
--- a/firebase-crashlytics/package.json
+++ b/firebase-crashlytics/package.json
@@ -1,6 +1,6 @@
{
"name": "@gitlive/firebase-crashlytics",
- "version": "2.0.0",
+ "version": "2.2.0-SNAPSHOT",
"description": "Wrapper around firebase for usage in Kotlin Multiplatform projects",
"main": "firebase-crashlytics.js",
"scripts": {
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk",
"dependencies": {
- "@gitlive/firebase-app": "2.0.0",
+ "@gitlive/firebase-app": "2.2.0-SNAPSHOT",
"firebase": "9.19.1",
"kotlin": "1.6.10",
"kotlinx-coroutines-core": "1.6.1-native-mt"
diff --git a/firebase-database/package.json b/firebase-database/package.json
index 228ba4282..7e01a2415 100644
--- a/firebase-database/package.json
+++ b/firebase-database/package.json
@@ -1,6 +1,6 @@
{
"name": "@gitlive/firebase-database",
- "version": "2.0.0",
+ "version": "2.2.0-SNAPSHOT",
"description": "Wrapper around firebase for usage in Kotlin Multiplatform projects",
"main": "firebase-database.js",
"scripts": {
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk",
"dependencies": {
- "@gitlive/firebase-app": "2.0.0",
+ "@gitlive/firebase-app": "2.2.0-SNAPSHOT",
"firebase": "9.19.1",
"kotlin": "1.8.20",
"kotlinx-coroutines-core": "1.6.4"
diff --git a/firebase-firestore/api/android/firebase-firestore.api b/firebase-firestore/api/android/firebase-firestore.api
index 8a0aa2e9a..9cf847e6b 100644
--- a/firebase-firestore/api/android/firebase-firestore.api
+++ b/firebase-firestore/api/android/firebase-firestore.api
@@ -68,16 +68,15 @@ public final class dev/gitlive/firebase/firestore/DocumentReference {
public final fun snapshots (Z)Lkotlinx/coroutines/flow/Flow;
public static synthetic fun snapshots$default (Ldev/gitlive/firebase/firestore/DocumentReference;ZILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
public fun toString ()Ljava/lang/String;
+ public final fun update (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun update (Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun update (Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun update$default (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public final fun updateEncoded (Ldev/gitlive/firebase/internal/EncodedObject;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
- public final fun updateEncodedFieldPathsAndValues (Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
- public final fun updateEncodedFieldsAndValues (Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
- public final fun updateFieldPaths ([Lkotlin/Pair;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
- public static synthetic fun updateFieldPaths$default (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
- public final fun updateFields ([Lkotlin/Pair;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
- public static synthetic fun updateFields$default (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
+ public final fun updateFieldPaths (Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+ public final fun updateFieldPaths ([Lkotlin/Pair;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+ public final fun updateFields (Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+ public final fun updateFields ([Lkotlin/Pair;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class dev/gitlive/firebase/firestore/DocumentReference$Companion {
@@ -161,6 +160,13 @@ public final class dev/gitlive/firebase/firestore/FieldValue$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
+public final class dev/gitlive/firebase/firestore/FieldValueBuilder {
+ public final fun addEncoded (Ljava/lang/Object;)V
+ public final fun addWithStrategy (Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V
+ public final fun getBuildSettings ()Lkotlin/jvm/functions/Function1;
+ public final fun setBuildSettings (Lkotlin/jvm/functions/Function1;)V
+}
+
public final class dev/gitlive/firebase/firestore/FieldValueSerializer : kotlinx/serialization/KSerializer {
public static final field INSTANCE Ldev/gitlive/firebase/firestore/FieldValueSerializer;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/gitlive/firebase/firestore/FieldValue;
@@ -170,6 +176,15 @@ public final class dev/gitlive/firebase/firestore/FieldValueSerializer : kotlinx
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
}
+public final class dev/gitlive/firebase/firestore/FieldsAndValuesBuilder {
+ public final fun getBuildSettings ()Lkotlin/jvm/functions/Function1;
+ public final fun setBuildSettings (Lkotlin/jvm/functions/Function1;)V
+ public final fun to (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V
+ public final fun to (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V
+ public final fun toEncoded (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)V
+ public final fun toEncoded (Ljava/lang/String;Ljava/lang/Object;)V
+}
+
public abstract class dev/gitlive/firebase/firestore/Filter {
}
@@ -182,6 +197,7 @@ public final class dev/gitlive/firebase/firestore/Filter$And : dev/gitlive/fireb
}
public final class dev/gitlive/firebase/firestore/Filter$Field : dev/gitlive/firebase/firestore/Filter$WithConstraint {
+ public fun (Ljava/lang/String;Ldev/gitlive/firebase/firestore/WhereConstraint;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ldev/gitlive/firebase/firestore/WhereConstraint;
public fun equals (Ljava/lang/Object;)Z
@@ -200,6 +216,7 @@ public final class dev/gitlive/firebase/firestore/Filter$Or : dev/gitlive/fireba
}
public final class dev/gitlive/firebase/firestore/Filter$Path : dev/gitlive/firebase/firestore/Filter$WithConstraint {
+ public fun (Ldev/gitlive/firebase/firestore/FieldPath;Ldev/gitlive/firebase/firestore/WhereConstraint;)V
public final fun component1 ()Ldev/gitlive/firebase/firestore/FieldPath;
public final fun component2 ()Ldev/gitlive/firebase/firestore/WhereConstraint;
public fun equals (Ljava/lang/Object;)Z
@@ -217,27 +234,33 @@ public final class dev/gitlive/firebase/firestore/FilterBuilder {
public final fun all ([Ldev/gitlive/firebase/firestore/Filter;)Ldev/gitlive/firebase/firestore/Filter;
public final fun and (Ldev/gitlive/firebase/firestore/Filter;Ldev/gitlive/firebase/firestore/Filter;)Ldev/gitlive/firebase/firestore/Filter$And;
public final fun any ([Ldev/gitlive/firebase/firestore/Filter;)Ldev/gitlive/firebase/firestore/Filter;
- public final fun contains (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun contains (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun containsAny (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun containsAny (Ljava/lang/String;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun equalTo (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun equalTo (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun greaterThan (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun greaterThan (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun greaterThanOrEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun greaterThanOrEqualTo (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun inArray (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun inArray (Ljava/lang/String;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun lessThan (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun lessThan (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun lessThanOrEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun lessThanOrEqualTo (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun notEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun notEqualTo (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun notInArray (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun notInArray (Ljava/lang/String;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun contains (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun contains (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun containsAny (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun containsAny (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun equalTo (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun equalTo (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun getBuildSettings ()Lkotlin/jvm/functions/Function1;
+ public final fun greaterThan (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun greaterThan (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun greaterThanOrEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun greaterThanOrEqualTo (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun inArray (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun inArray (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun isNotNull (Ldev/gitlive/firebase/firestore/FieldPath;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun isNotNull (Ljava/lang/String;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun isNull (Ldev/gitlive/firebase/firestore/FieldPath;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun isNull (Ljava/lang/String;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun lessThan (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun lessThan (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun lessThanOrEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun lessThanOrEqualTo (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun notEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun notEqualTo (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun notInArray (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun notInArray (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
public final fun or (Ldev/gitlive/firebase/firestore/Filter;Ldev/gitlive/firebase/firestore/Filter;)Ldev/gitlive/firebase/firestore/Filter$Or;
+ public final fun setBuildSettings (Lkotlin/jvm/functions/Function1;)V
}
public final class dev/gitlive/firebase/firestore/FirebaseFirestore {
@@ -333,12 +356,6 @@ public final class dev/gitlive/firebase/firestore/GeoPointSerializer : kotlinx/s
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
}
-public final class dev/gitlive/firebase/firestore/HelpersKt {
- public static final fun encodeFieldAndValue ([Lkotlin/Pair;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
- public static final fun performUpdateFieldPaths ([Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
- public static final fun performUpdateFields ([Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
-}
-
public abstract interface class dev/gitlive/firebase/firestore/LocalCacheSettings {
}
@@ -424,8 +441,12 @@ public final class dev/gitlive/firebase/firestore/MemoryGarbageCollectorSettings
public class dev/gitlive/firebase/firestore/Query {
public static final field Companion Ldev/gitlive/firebase/firestore/Query$Companion;
public final fun endAt (Ldev/gitlive/firebase/firestore/DocumentSnapshot;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun endAt (Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun endAt (Lkotlin/jvm/functions/Function1;[Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun endAt ([Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun endBefore (Ldev/gitlive/firebase/firestore/DocumentSnapshot;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun endBefore (Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun endBefore (Lkotlin/jvm/functions/Function1;[Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun endBefore ([Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun get (Ldev/gitlive/firebase/firestore/Source;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun get$default (Ldev/gitlive/firebase/firestore/Query;Ldev/gitlive/firebase/firestore/Source;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
@@ -438,8 +459,12 @@ public class dev/gitlive/firebase/firestore/Query {
public final fun snapshots (Z)Lkotlinx/coroutines/flow/Flow;
public static synthetic fun snapshots$default (Ldev/gitlive/firebase/firestore/Query;ZILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
public final fun startAfter (Ldev/gitlive/firebase/firestore/DocumentSnapshot;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun startAfter (Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun startAfter (Lkotlin/jvm/functions/Function1;[Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun startAfter ([Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun startAt (Ldev/gitlive/firebase/firestore/DocumentSnapshot;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun startAt (Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun startAt (Lkotlin/jvm/functions/Function1;[Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun startAt ([Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun where (Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Query;
}
@@ -556,17 +581,16 @@ public final class dev/gitlive/firebase/firestore/Transaction {
public fun toString ()Ljava/lang/String;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Transaction;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/lang/Object;Z)Ldev/gitlive/firebase/firestore/Transaction;
+ public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Transaction;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Transaction;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Z)Ldev/gitlive/firebase/firestore/Transaction;
public static synthetic fun update$default (Ldev/gitlive/firebase/firestore/Transaction;Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/Transaction;
public static synthetic fun update$default (Ldev/gitlive/firebase/firestore/Transaction;Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/Transaction;
public final fun updateEncoded (Ldev/gitlive/firebase/firestore/DocumentReference;Ldev/gitlive/firebase/internal/EncodedObject;)Ldev/gitlive/firebase/firestore/Transaction;
- public final fun updateEncodedFieldPathsAndValues (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Transaction;
- public final fun updateEncodedFieldsAndValues (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Transaction;
- public final fun updateFieldPaths (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Transaction;
- public static synthetic fun updateFieldPaths$default (Ldev/gitlive/firebase/firestore/Transaction;Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/Transaction;
- public final fun updateFields (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Transaction;
- public static synthetic fun updateFields$default (Ldev/gitlive/firebase/firestore/Transaction;Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/Transaction;
+ public final fun updateFieldPaths (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/Transaction;
+ public final fun updateFieldPaths (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/Transaction;
+ public final fun updateFields (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/Transaction;
+ public final fun updateFields (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/Transaction;
}
public final class dev/gitlive/firebase/firestore/Transaction$Companion {
@@ -576,117 +600,102 @@ public abstract interface class dev/gitlive/firebase/firestore/WhereConstraint {
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$ArrayContains : dev/gitlive/firebase/firestore/WhereConstraint$ForObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$ArrayContainsAny : dev/gitlive/firebase/firestore/WhereConstraint$ForArray {
+ public fun (Ljava/util/List;)V
public final fun component1 ()Ljava/util/List;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValues ()Ljava/util/List;
public fun getValues ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$EqualTo : dev/gitlive/firebase/firestore/WhereConstraint$ForNullableObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public abstract interface class dev/gitlive/firebase/firestore/WhereConstraint$ForArray : dev/gitlive/firebase/firestore/WhereConstraint {
- public abstract fun getSafeValues ()Ljava/util/List;
public abstract fun getValues ()Ljava/util/List;
}
-public final class dev/gitlive/firebase/firestore/WhereConstraint$ForArray$DefaultImpls {
- public static fun getSafeValues (Ldev/gitlive/firebase/firestore/WhereConstraint$ForArray;)Ljava/util/List;
-}
-
public abstract interface class dev/gitlive/firebase/firestore/WhereConstraint$ForNullableObject : dev/gitlive/firebase/firestore/WhereConstraint {
- public abstract fun getSafeValue ()Ljava/lang/Object;
public abstract fun getValue ()Ljava/lang/Object;
}
-public final class dev/gitlive/firebase/firestore/WhereConstraint$ForNullableObject$DefaultImpls {
- public static fun getSafeValue (Ldev/gitlive/firebase/firestore/WhereConstraint$ForNullableObject;)Ljava/lang/Object;
-}
-
public abstract interface class dev/gitlive/firebase/firestore/WhereConstraint$ForObject : dev/gitlive/firebase/firestore/WhereConstraint {
- public abstract fun getSafeValue ()Ljava/lang/Object;
public abstract fun getValue ()Ljava/lang/Object;
}
-public final class dev/gitlive/firebase/firestore/WhereConstraint$ForObject$DefaultImpls {
- public static fun getSafeValue (Ldev/gitlive/firebase/firestore/WhereConstraint$ForObject;)Ljava/lang/Object;
-}
-
public final class dev/gitlive/firebase/firestore/WhereConstraint$GreaterThan : dev/gitlive/firebase/firestore/WhereConstraint$ForObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$GreaterThanOrEqualTo : dev/gitlive/firebase/firestore/WhereConstraint$ForObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$InArray : dev/gitlive/firebase/firestore/WhereConstraint$ForArray {
+ public fun (Ljava/util/List;)V
public final fun component1 ()Ljava/util/List;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValues ()Ljava/util/List;
public fun getValues ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$LessThan : dev/gitlive/firebase/firestore/WhereConstraint$ForObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$LessThanOrEqualTo : dev/gitlive/firebase/firestore/WhereConstraint$ForObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$NotEqualTo : dev/gitlive/firebase/firestore/WhereConstraint$ForNullableObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$NotInArray : dev/gitlive/firebase/firestore/WhereConstraint$ForArray {
+ public fun (Ljava/util/List;)V
public final fun component1 ()Ljava/util/List;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValues ()Ljava/util/List;
public fun getValues ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
@@ -710,16 +719,15 @@ public final class dev/gitlive/firebase/firestore/WriteBatch {
public static synthetic fun set$default (Ldev/gitlive/firebase/firestore/WriteBatch;Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;[Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/WriteBatch;
public final fun setEncoded (Ldev/gitlive/firebase/firestore/DocumentReference;Ldev/gitlive/firebase/internal/EncodedObject;Ldev/gitlive/firebase/firestore/internal/SetOptions;)Ldev/gitlive/firebase/firestore/WriteBatch;
public fun toString ()Ljava/lang/String;
+ public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/WriteBatch;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/WriteBatch;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Z)Ldev/gitlive/firebase/firestore/WriteBatch;
public static synthetic fun update$default (Ldev/gitlive/firebase/firestore/WriteBatch;Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/WriteBatch;
public final fun updateEncoded (Ldev/gitlive/firebase/firestore/DocumentReference;Ldev/gitlive/firebase/internal/EncodedObject;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public final fun updateEncodedFieldPathsAndValues (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/util/List;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public final fun updateEncodedFieldsAndValues (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/util/List;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public final fun updateField (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public static synthetic fun updateField$default (Ldev/gitlive/firebase/firestore/WriteBatch;Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public final fun updateFieldPath (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public static synthetic fun updateFieldPath$default (Ldev/gitlive/firebase/firestore/WriteBatch;Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/WriteBatch;
+ public final fun updateField (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/WriteBatch;
+ public final fun updateField (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/WriteBatch;
+ public final fun updateFieldPath (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/WriteBatch;
+ public final fun updateFieldPath (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/WriteBatch;
}
public final class dev/gitlive/firebase/firestore/WriteBatch$Companion {
diff --git a/firebase-firestore/api/jvm/firebase-firestore.api b/firebase-firestore/api/jvm/firebase-firestore.api
index 33a64aef7..6b5abda69 100644
--- a/firebase-firestore/api/jvm/firebase-firestore.api
+++ b/firebase-firestore/api/jvm/firebase-firestore.api
@@ -68,16 +68,15 @@ public final class dev/gitlive/firebase/firestore/DocumentReference {
public final fun snapshots (Z)Lkotlinx/coroutines/flow/Flow;
public static synthetic fun snapshots$default (Ldev/gitlive/firebase/firestore/DocumentReference;ZILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
public fun toString ()Ljava/lang/String;
+ public final fun update (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun update (Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun update (Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun update$default (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public final fun updateEncoded (Ldev/gitlive/firebase/internal/EncodedObject;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
- public final fun updateEncodedFieldPathsAndValues (Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
- public final fun updateEncodedFieldsAndValues (Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
- public final fun updateFieldPaths ([Lkotlin/Pair;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
- public static synthetic fun updateFieldPaths$default (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
- public final fun updateFields ([Lkotlin/Pair;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
- public static synthetic fun updateFields$default (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
+ public final fun updateFieldPaths (Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+ public final fun updateFieldPaths ([Lkotlin/Pair;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+ public final fun updateFields (Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+ public final fun updateFields ([Lkotlin/Pair;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class dev/gitlive/firebase/firestore/DocumentReference$Companion {
@@ -161,6 +160,13 @@ public final class dev/gitlive/firebase/firestore/FieldValue$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
+public final class dev/gitlive/firebase/firestore/FieldValueBuilder {
+ public final fun addEncoded (Ljava/lang/Object;)V
+ public final fun addWithStrategy (Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V
+ public final fun getBuildSettings ()Lkotlin/jvm/functions/Function1;
+ public final fun setBuildSettings (Lkotlin/jvm/functions/Function1;)V
+}
+
public final class dev/gitlive/firebase/firestore/FieldValueSerializer : kotlinx/serialization/KSerializer {
public static final field INSTANCE Ldev/gitlive/firebase/firestore/FieldValueSerializer;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/gitlive/firebase/firestore/FieldValue;
@@ -170,6 +176,15 @@ public final class dev/gitlive/firebase/firestore/FieldValueSerializer : kotlinx
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
}
+public final class dev/gitlive/firebase/firestore/FieldsAndValuesBuilder {
+ public final fun getBuildSettings ()Lkotlin/jvm/functions/Function1;
+ public final fun setBuildSettings (Lkotlin/jvm/functions/Function1;)V
+ public final fun to (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V
+ public final fun to (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V
+ public final fun toEncoded (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)V
+ public final fun toEncoded (Ljava/lang/String;Ljava/lang/Object;)V
+}
+
public abstract class dev/gitlive/firebase/firestore/Filter {
}
@@ -182,6 +197,7 @@ public final class dev/gitlive/firebase/firestore/Filter$And : dev/gitlive/fireb
}
public final class dev/gitlive/firebase/firestore/Filter$Field : dev/gitlive/firebase/firestore/Filter$WithConstraint {
+ public fun (Ljava/lang/String;Ldev/gitlive/firebase/firestore/WhereConstraint;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ldev/gitlive/firebase/firestore/WhereConstraint;
public fun equals (Ljava/lang/Object;)Z
@@ -200,6 +216,7 @@ public final class dev/gitlive/firebase/firestore/Filter$Or : dev/gitlive/fireba
}
public final class dev/gitlive/firebase/firestore/Filter$Path : dev/gitlive/firebase/firestore/Filter$WithConstraint {
+ public fun (Ldev/gitlive/firebase/firestore/FieldPath;Ldev/gitlive/firebase/firestore/WhereConstraint;)V
public final fun component1 ()Ldev/gitlive/firebase/firestore/FieldPath;
public final fun component2 ()Ldev/gitlive/firebase/firestore/WhereConstraint;
public fun equals (Ljava/lang/Object;)Z
@@ -217,27 +234,33 @@ public final class dev/gitlive/firebase/firestore/FilterBuilder {
public final fun all ([Ldev/gitlive/firebase/firestore/Filter;)Ldev/gitlive/firebase/firestore/Filter;
public final fun and (Ldev/gitlive/firebase/firestore/Filter;Ldev/gitlive/firebase/firestore/Filter;)Ldev/gitlive/firebase/firestore/Filter$And;
public final fun any ([Ldev/gitlive/firebase/firestore/Filter;)Ldev/gitlive/firebase/firestore/Filter;
- public final fun contains (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun contains (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun containsAny (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun containsAny (Ljava/lang/String;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun equalTo (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun equalTo (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun greaterThan (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun greaterThan (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun greaterThanOrEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun greaterThanOrEqualTo (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun inArray (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun inArray (Ljava/lang/String;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun lessThan (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun lessThan (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun lessThanOrEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun lessThanOrEqualTo (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun notEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun notEqualTo (Ljava/lang/String;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun notInArray (Ldev/gitlive/firebase/firestore/FieldPath;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
- public final fun notInArray (Ljava/lang/String;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun contains (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun contains (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun containsAny (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun containsAny (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun equalTo (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun equalTo (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun getBuildSettings ()Lkotlin/jvm/functions/Function1;
+ public final fun greaterThan (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun greaterThan (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun greaterThanOrEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun greaterThanOrEqualTo (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun inArray (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun inArray (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun isNotNull (Ldev/gitlive/firebase/firestore/FieldPath;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun isNotNull (Ljava/lang/String;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun isNull (Ldev/gitlive/firebase/firestore/FieldPath;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun isNull (Ljava/lang/String;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun lessThan (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun lessThan (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun lessThanOrEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun lessThanOrEqualTo (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun notEqualTo (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun notEqualTo (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun notInArray (Ldev/gitlive/firebase/firestore/FieldPath;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
+ public final fun notInArray (Ljava/lang/String;Lkotlinx/serialization/SerializationStrategy;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Filter$WithConstraint;
public final fun or (Ldev/gitlive/firebase/firestore/Filter;Ldev/gitlive/firebase/firestore/Filter;)Ldev/gitlive/firebase/firestore/Filter$Or;
+ public final fun setBuildSettings (Lkotlin/jvm/functions/Function1;)V
}
public final class dev/gitlive/firebase/firestore/FirebaseFirestore {
@@ -333,12 +356,6 @@ public final class dev/gitlive/firebase/firestore/GeoPointSerializer : kotlinx/s
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
}
-public final class dev/gitlive/firebase/firestore/HelpersKt {
- public static final fun encodeFieldAndValue ([Lkotlin/Pair;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
- public static final fun performUpdateFieldPaths ([Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
- public static final fun performUpdateFields ([Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
-}
-
public abstract interface class dev/gitlive/firebase/firestore/LocalCacheSettings {
}
@@ -424,8 +441,12 @@ public final class dev/gitlive/firebase/firestore/MemoryGarbageCollectorSettings
public class dev/gitlive/firebase/firestore/Query {
public static final field Companion Ldev/gitlive/firebase/firestore/Query$Companion;
public final fun endAt (Ldev/gitlive/firebase/firestore/DocumentSnapshot;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun endAt (Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun endAt (Lkotlin/jvm/functions/Function1;[Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun endAt ([Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun endBefore (Ldev/gitlive/firebase/firestore/DocumentSnapshot;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun endBefore (Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun endBefore (Lkotlin/jvm/functions/Function1;[Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun endBefore ([Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun get (Ldev/gitlive/firebase/firestore/Source;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun get$default (Ldev/gitlive/firebase/firestore/Query;Ldev/gitlive/firebase/firestore/Source;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
@@ -438,8 +459,12 @@ public class dev/gitlive/firebase/firestore/Query {
public final fun snapshots (Z)Lkotlinx/coroutines/flow/Flow;
public static synthetic fun snapshots$default (Ldev/gitlive/firebase/firestore/Query;ZILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow;
public final fun startAfter (Ldev/gitlive/firebase/firestore/DocumentSnapshot;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun startAfter (Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun startAfter (Lkotlin/jvm/functions/Function1;[Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun startAfter ([Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun startAt (Ldev/gitlive/firebase/firestore/DocumentSnapshot;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun startAt (Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Query;
+ public final fun startAt (Lkotlin/jvm/functions/Function1;[Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun startAt ([Ljava/lang/Object;)Ldev/gitlive/firebase/firestore/Query;
public final fun where (Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Query;
}
@@ -556,17 +581,16 @@ public final class dev/gitlive/firebase/firestore/Transaction {
public fun toString ()Ljava/lang/String;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Transaction;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/lang/Object;Z)Ldev/gitlive/firebase/firestore/Transaction;
+ public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Transaction;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Transaction;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Z)Ldev/gitlive/firebase/firestore/Transaction;
public static synthetic fun update$default (Ldev/gitlive/firebase/firestore/Transaction;Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/Transaction;
public static synthetic fun update$default (Ldev/gitlive/firebase/firestore/Transaction;Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/Transaction;
public final fun updateEncoded (Ldev/gitlive/firebase/firestore/DocumentReference;Ldev/gitlive/firebase/internal/EncodedObject;)Ldev/gitlive/firebase/firestore/Transaction;
- public final fun updateEncodedFieldPathsAndValues (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Transaction;
- public final fun updateEncodedFieldsAndValues (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/util/List;)Ldev/gitlive/firebase/firestore/Transaction;
- public final fun updateFieldPaths (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Transaction;
- public static synthetic fun updateFieldPaths$default (Ldev/gitlive/firebase/firestore/Transaction;Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/Transaction;
- public final fun updateFields (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/Transaction;
- public static synthetic fun updateFields$default (Ldev/gitlive/firebase/firestore/Transaction;Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/Transaction;
+ public final fun updateFieldPaths (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/Transaction;
+ public final fun updateFieldPaths (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/Transaction;
+ public final fun updateFields (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/Transaction;
+ public final fun updateFields (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/Transaction;
}
public final class dev/gitlive/firebase/firestore/Transaction$Companion {
@@ -576,117 +600,102 @@ public abstract interface class dev/gitlive/firebase/firestore/WhereConstraint {
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$ArrayContains : dev/gitlive/firebase/firestore/WhereConstraint$ForObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$ArrayContainsAny : dev/gitlive/firebase/firestore/WhereConstraint$ForArray {
+ public fun (Ljava/util/List;)V
public final fun component1 ()Ljava/util/List;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValues ()Ljava/util/List;
public fun getValues ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$EqualTo : dev/gitlive/firebase/firestore/WhereConstraint$ForNullableObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public abstract interface class dev/gitlive/firebase/firestore/WhereConstraint$ForArray : dev/gitlive/firebase/firestore/WhereConstraint {
- public abstract fun getSafeValues ()Ljava/util/List;
public abstract fun getValues ()Ljava/util/List;
}
-public final class dev/gitlive/firebase/firestore/WhereConstraint$ForArray$DefaultImpls {
- public static fun getSafeValues (Ldev/gitlive/firebase/firestore/WhereConstraint$ForArray;)Ljava/util/List;
-}
-
public abstract interface class dev/gitlive/firebase/firestore/WhereConstraint$ForNullableObject : dev/gitlive/firebase/firestore/WhereConstraint {
- public abstract fun getSafeValue ()Ljava/lang/Object;
public abstract fun getValue ()Ljava/lang/Object;
}
-public final class dev/gitlive/firebase/firestore/WhereConstraint$ForNullableObject$DefaultImpls {
- public static fun getSafeValue (Ldev/gitlive/firebase/firestore/WhereConstraint$ForNullableObject;)Ljava/lang/Object;
-}
-
public abstract interface class dev/gitlive/firebase/firestore/WhereConstraint$ForObject : dev/gitlive/firebase/firestore/WhereConstraint {
- public abstract fun getSafeValue ()Ljava/lang/Object;
public abstract fun getValue ()Ljava/lang/Object;
}
-public final class dev/gitlive/firebase/firestore/WhereConstraint$ForObject$DefaultImpls {
- public static fun getSafeValue (Ldev/gitlive/firebase/firestore/WhereConstraint$ForObject;)Ljava/lang/Object;
-}
-
public final class dev/gitlive/firebase/firestore/WhereConstraint$GreaterThan : dev/gitlive/firebase/firestore/WhereConstraint$ForObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$GreaterThanOrEqualTo : dev/gitlive/firebase/firestore/WhereConstraint$ForObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$InArray : dev/gitlive/firebase/firestore/WhereConstraint$ForArray {
+ public fun (Ljava/util/List;)V
public final fun component1 ()Ljava/util/List;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValues ()Ljava/util/List;
public fun getValues ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$LessThan : dev/gitlive/firebase/firestore/WhereConstraint$ForObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$LessThanOrEqualTo : dev/gitlive/firebase/firestore/WhereConstraint$ForObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$NotEqualTo : dev/gitlive/firebase/firestore/WhereConstraint$ForNullableObject {
+ public fun (Ljava/lang/Object;)V
public final fun component1 ()Ljava/lang/Object;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValue ()Ljava/lang/Object;
public fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class dev/gitlive/firebase/firestore/WhereConstraint$NotInArray : dev/gitlive/firebase/firestore/WhereConstraint$ForArray {
+ public fun (Ljava/util/List;)V
public final fun component1 ()Ljava/util/List;
public fun equals (Ljava/lang/Object;)Z
- public fun getSafeValues ()Ljava/util/List;
public fun getValues ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
@@ -710,16 +719,15 @@ public final class dev/gitlive/firebase/firestore/WriteBatch {
public static synthetic fun set$default (Ldev/gitlive/firebase/firestore/WriteBatch;Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;[Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/WriteBatch;
public final fun setEncoded (Ldev/gitlive/firebase/firestore/DocumentReference;Ldev/gitlive/firebase/internal/EncodedObject;Ldev/gitlive/firebase/firestore/internal/SetOptions;)Ldev/gitlive/firebase/firestore/WriteBatch;
public fun toString ()Ljava/lang/String;
+ public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/WriteBatch;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/WriteBatch;
public final fun update (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Z)Ldev/gitlive/firebase/firestore/WriteBatch;
public static synthetic fun update$default (Ldev/gitlive/firebase/firestore/WriteBatch;Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/WriteBatch;
public final fun updateEncoded (Ldev/gitlive/firebase/firestore/DocumentReference;Ldev/gitlive/firebase/internal/EncodedObject;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public final fun updateEncodedFieldPathsAndValues (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/util/List;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public final fun updateEncodedFieldsAndValues (Ldev/gitlive/firebase/firestore/DocumentReference;Ljava/util/List;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public final fun updateField (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public static synthetic fun updateField$default (Ldev/gitlive/firebase/firestore/WriteBatch;Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public final fun updateFieldPath (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;)Ldev/gitlive/firebase/firestore/WriteBatch;
- public static synthetic fun updateFieldPath$default (Ldev/gitlive/firebase/firestore/WriteBatch;Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ldev/gitlive/firebase/firestore/WriteBatch;
+ public final fun updateField (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/WriteBatch;
+ public final fun updateField (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/WriteBatch;
+ public final fun updateFieldPath (Ldev/gitlive/firebase/firestore/DocumentReference;Lkotlin/jvm/functions/Function1;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/WriteBatch;
+ public final fun updateFieldPath (Ldev/gitlive/firebase/firestore/DocumentReference;[Lkotlin/Pair;)Ldev/gitlive/firebase/firestore/WriteBatch;
}
public final class dev/gitlive/firebase/firestore/WriteBatch$Companion {
diff --git a/firebase-firestore/package.json b/firebase-firestore/package.json
index 8efd2dd91..882cd52be 100644
--- a/firebase-firestore/package.json
+++ b/firebase-firestore/package.json
@@ -1,6 +1,6 @@
{
"name": "@gitlive/firebase-firestore",
- "version": "2.0.0",
+ "version": "2.2.0-SNAPSHOT",
"description": "Wrapper around firebase for usage in Kotlin Multiplatform projects",
"main": "firebase-firestore.js",
"scripts": {
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk",
"dependencies": {
- "@gitlive/firebase-app": "2.0.0",
+ "@gitlive/firebase-app": "2.2.0-SNAPSHOT",
"firebase": "9.19.1",
"kotlin": "1.8.20",
"kotlinx-coroutines-core": "1.6.4"
diff --git a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt
index cb91ffd74..2cc2047a0 100644
--- a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt
+++ b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt
@@ -2,7 +2,6 @@ package dev.gitlive.firebase.firestore.internal
import com.google.android.gms.tasks.TaskExecutors
import com.google.firebase.firestore.MetadataChanges
-import dev.gitlive.firebase.firestore.EncodedFieldPath
import dev.gitlive.firebase.firestore.NativeDocumentReferenceType
import dev.gitlive.firebase.firestore.NativeDocumentSnapshot
import dev.gitlive.firebase.firestore.Source
@@ -44,19 +43,12 @@ internal actual class NativeDocumentReference actual constructor(actual val nati
android.update(encodedData.android).await()
}
- actual suspend fun updateEncodedFieldsAndValues(encodedFieldsAndValues: List>) {
+ actual suspend fun updateEncoded(encodedFieldsAndValues: List) {
encodedFieldsAndValues.takeUnless { encodedFieldsAndValues.isEmpty() }?.let {
- android.update(encodedFieldsAndValues.toMap())
+ encodedFieldsAndValues.performUpdate(android::update, android::update)
}?.await()
}
- actual suspend fun updateEncodedFieldPathsAndValues(encodedFieldsAndValues: List>) {
- encodedFieldsAndValues.takeUnless { encodedFieldsAndValues.isEmpty() }
- ?.performUpdate { field, value, moreFieldsAndValues ->
- android.update(field, value, *moreFieldsAndValues)
- }?.await()
- }
-
actual suspend fun delete() {
android.delete().await()
}
diff --git a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeQueryWrapper.kt b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeQueryWrapper.kt
index 5dc17f72b..7505e09ef 100644
--- a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeQueryWrapper.kt
+++ b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeQueryWrapper.kt
@@ -59,7 +59,7 @@ internal actual open class NativeQueryWrapper internal actual constructor(actual
is WhereConstraint.EqualTo -> com.google.firebase.firestore.Filter::equalTo
is WhereConstraint.NotEqualTo -> com.google.firebase.firestore.Filter::notEqualTo
}
- modifier.invoke(field, constraint.safeValue)
+ modifier.invoke(field, constraint.value)
}
is WhereConstraint.ForObject -> {
val modifier: (String, Any) -> com.google.firebase.firestore.Filter = when (constraint) {
@@ -69,7 +69,7 @@ internal actual open class NativeQueryWrapper internal actual constructor(actual
is WhereConstraint.GreaterThanOrEqualTo -> com.google.firebase.firestore.Filter::greaterThanOrEqualTo
is WhereConstraint.ArrayContains -> com.google.firebase.firestore.Filter::arrayContains
}
- modifier.invoke(field, constraint.safeValue)
+ modifier.invoke(field, constraint.value)
}
is WhereConstraint.ForArray -> {
val modifier: (String, List) -> com.google.firebase.firestore.Filter = when (constraint) {
@@ -77,7 +77,7 @@ internal actual open class NativeQueryWrapper internal actual constructor(actual
is WhereConstraint.ArrayContainsAny -> com.google.firebase.firestore.Filter::arrayContainsAny
is WhereConstraint.NotInArray -> com.google.firebase.firestore.Filter::notInArray
}
- modifier.invoke(field, constraint.safeValues)
+ modifier.invoke(field, constraint.values)
}
}
}
@@ -88,7 +88,7 @@ internal actual open class NativeQueryWrapper internal actual constructor(actual
is WhereConstraint.EqualTo -> com.google.firebase.firestore.Filter::equalTo
is WhereConstraint.NotEqualTo -> com.google.firebase.firestore.Filter::notEqualTo
}
- modifier.invoke(path.android, constraint.safeValue)
+ modifier.invoke(path.android, constraint.value)
}
is WhereConstraint.ForObject -> {
val modifier: (FieldPath, Any) -> com.google.firebase.firestore.Filter = when (constraint) {
@@ -98,7 +98,7 @@ internal actual open class NativeQueryWrapper internal actual constructor(actual
is WhereConstraint.GreaterThanOrEqualTo -> com.google.firebase.firestore.Filter::greaterThanOrEqualTo
is WhereConstraint.ArrayContains -> com.google.firebase.firestore.Filter::arrayContains
}
- modifier.invoke(path.android, constraint.safeValue)
+ modifier.invoke(path.android, constraint.value)
}
is WhereConstraint.ForArray -> {
val modifier: (FieldPath, List) -> com.google.firebase.firestore.Filter = when (constraint) {
@@ -106,7 +106,7 @@ internal actual open class NativeQueryWrapper internal actual constructor(actual
is WhereConstraint.ArrayContainsAny -> com.google.firebase.firestore.Filter::arrayContainsAny
is WhereConstraint.NotInArray -> com.google.firebase.firestore.Filter::notInArray
}
- modifier.invoke(path.android, constraint.safeValues)
+ modifier.invoke(path.android, constraint.values)
}
}
}
diff --git a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeTransactionWrapper.kt b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeTransactionWrapper.kt
index 4b8219703..ea20d3f33 100644
--- a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeTransactionWrapper.kt
+++ b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeTransactionWrapper.kt
@@ -1,7 +1,6 @@
package dev.gitlive.firebase.firestore.internal
import dev.gitlive.firebase.firestore.DocumentReference
-import dev.gitlive.firebase.firestore.EncodedFieldPath
import dev.gitlive.firebase.firestore.NativeTransaction
import dev.gitlive.firebase.firestore.android
import dev.gitlive.firebase.firestore.performUpdate
@@ -23,19 +22,17 @@ internal actual class NativeTransactionWrapper internal actual constructor(actua
actual fun updateEncoded(documentRef: DocumentReference, encodedData: EncodedObject) = native.update(documentRef.android, encodedData.android).let { this }
- actual fun updateEncodedFieldsAndValues(
+ actual fun updateEncoded(
documentRef: DocumentReference,
- encodedFieldsAndValues: List>,
- ) = encodedFieldsAndValues.performUpdate { field, value, moreFieldsAndValues ->
- native.update(documentRef.android, field, value, *moreFieldsAndValues)
- }.let { this }
-
- actual fun updateEncodedFieldPathsAndValues(
- documentRef: DocumentReference,
- encodedFieldsAndValues: List>,
- ) = encodedFieldsAndValues.performUpdate { field, value, moreFieldsAndValues ->
- native.update(documentRef.android, field, value, *moreFieldsAndValues)
- }.let { this }
+ encodedFieldsAndValues: List,
+ ) = encodedFieldsAndValues.performUpdate(
+ updateAsField = { field, value, moreFieldsAndValues ->
+ native.update(documentRef.android, field, value, *moreFieldsAndValues)
+ },
+ updateAsFieldPath = { fieldPath, value, moreFieldsAndValues ->
+ native.update(documentRef.android, fieldPath, value, *moreFieldsAndValues)
+ },
+ ).let { this }
actual fun delete(documentRef: DocumentReference) =
native.delete(documentRef.android).let { this }
diff --git a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeWriteBatchWrapper.kt b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeWriteBatchWrapper.kt
index 9aa34f700..1a3bd69b9 100644
--- a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeWriteBatchWrapper.kt
+++ b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeWriteBatchWrapper.kt
@@ -1,7 +1,6 @@
package dev.gitlive.firebase.firestore.internal
import dev.gitlive.firebase.firestore.DocumentReference
-import dev.gitlive.firebase.firestore.EncodedFieldPath
import dev.gitlive.firebase.firestore.NativeWriteBatch
import dev.gitlive.firebase.firestore.android
import dev.gitlive.firebase.firestore.performUpdate
@@ -25,19 +24,17 @@ internal actual class NativeWriteBatchWrapper internal actual constructor(actual
actual fun updateEncoded(documentRef: DocumentReference, encodedData: EncodedObject) = native.update(documentRef.android, encodedData.android).let { this }
- actual fun updateEncodedFieldsAndValues(
+ actual fun updateEncoded(
documentRef: DocumentReference,
- encodedFieldsAndValues: List>,
- ) = encodedFieldsAndValues.performUpdate { field, value, moreFieldsAndValues ->
- native.update(documentRef.android, field, value, *moreFieldsAndValues)
- }.let { this }
-
- actual fun updateEncodedFieldPathsAndValues(
- documentRef: DocumentReference,
- encodedFieldsAndValues: List>,
- ) = encodedFieldsAndValues.performUpdate { field, value, moreFieldsAndValues ->
- native.update(documentRef.android, field, value, *moreFieldsAndValues)
- }.let { this }
+ encodedFieldsAndValues: List,
+ ) = encodedFieldsAndValues.performUpdate(
+ updateAsField = { field, value, moreFieldsAndValues ->
+ native.update(documentRef.android, field, value, *moreFieldsAndValues)
+ },
+ updateAsFieldPath = { fieldPath, value, moreFieldsAndValues ->
+ native.update(documentRef.android, fieldPath, value, *moreFieldsAndValues)
+ },
+ ).let { this }
actual fun delete(documentRef: DocumentReference) =
native.delete(documentRef.android).let { this }
diff --git a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/FieldValueBuilder.kt b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/FieldValueBuilder.kt
new file mode 100644
index 000000000..53d5a0d13
--- /dev/null
+++ b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/FieldValueBuilder.kt
@@ -0,0 +1,25 @@
+package dev.gitlive.firebase.firestore
+
+import dev.gitlive.firebase.EncodeSettings
+import kotlinx.serialization.SerializationStrategy
+
+public class FieldValueBuilder internal constructor() {
+
+ internal val fieldValues: MutableList = mutableListOf()
+ public var buildSettings: EncodeSettings.Builder.() -> Unit = {
+ encodeDefaults = true
+ }
+
+ public inline fun add(value: T) {
+ addEncoded(encode(value, buildSettings)!!)
+ }
+
+ public fun addWithStrategy(strategy: SerializationStrategy, value: T) {
+ addEncoded(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)!!)
+ }
+
+ @PublishedApi
+ internal fun addEncoded(encodedValue: Any) {
+ fieldValues += encodedValue
+ }
+}
diff --git a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/FieldsAndValuesBuilder.kt b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/FieldsAndValuesBuilder.kt
new file mode 100644
index 000000000..aba64b228
--- /dev/null
+++ b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/FieldsAndValuesBuilder.kt
@@ -0,0 +1,39 @@
+package dev.gitlive.firebase.firestore
+
+import dev.gitlive.firebase.EncodeSettings
+import dev.gitlive.firebase.firestore.internal.FieldAndValue
+import kotlinx.serialization.SerializationStrategy
+
+public class FieldsAndValuesBuilder internal constructor() {
+
+ internal val fieldAndValues: MutableList = mutableListOf()
+ public var buildSettings: EncodeSettings.Builder.() -> Unit = {
+ encodeDefaults = true
+ }
+
+ public inline infix fun String.to(value: T) {
+ toEncoded(encode(value, buildSettings))
+ }
+
+ public inline infix fun FieldPath.to(value: T) {
+ toEncoded(encode(value, buildSettings))
+ }
+
+ public fun String.to(strategy: SerializationStrategy, value: T) {
+ toEncoded(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings))
+ }
+
+ public fun FieldPath.to(strategy: SerializationStrategy, value: T) {
+ toEncoded(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings))
+ }
+
+ @PublishedApi
+ internal fun String.toEncoded(encodedValue: Any?) {
+ fieldAndValues += FieldAndValue.WithStringField(this, encodedValue)
+ }
+
+ @PublishedApi
+ internal fun FieldPath.toEncoded(encodedValue: Any?) {
+ fieldAndValues += FieldAndValue.WithFieldPath(this, encodedValue)
+ }
+}
diff --git a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/Filter.kt b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/Filter.kt
index f9e8558e7..3f5785c9f 100644
--- a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/Filter.kt
+++ b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/Filter.kt
@@ -1,33 +1,31 @@
package dev.gitlive.firebase.firestore
-import dev.gitlive.firebase.firestore.internal.safeValue
+import dev.gitlive.firebase.EncodeSettings
+import kotlinx.serialization.SerializationStrategy
public sealed interface WhereConstraint {
public sealed interface ForNullableObject : WhereConstraint {
public val value: Any?
- public val safeValue: Any? get() = value?.safeValue
}
public sealed interface ForObject : WhereConstraint {
public val value: Any
- public val safeValue: Any get() = value.safeValue
}
public sealed interface ForArray : WhereConstraint {
public val values: List
- public val safeValues: List get() = values.map { it.safeValue }
}
- public data class EqualTo internal constructor(override val value: Any?) : ForNullableObject
- public data class NotEqualTo internal constructor(override val value: Any?) : ForNullableObject
- public data class LessThan internal constructor(override val value: Any) : ForObject
- public data class GreaterThan internal constructor(override val value: Any) : ForObject
- public data class LessThanOrEqualTo internal constructor(override val value: Any) : ForObject
- public data class GreaterThanOrEqualTo internal constructor(override val value: Any) : ForObject
- public data class ArrayContains internal constructor(override val value: Any) : ForObject
- public data class ArrayContainsAny internal constructor(override val values: List) : ForArray
- public data class InArray internal constructor(override val values: List) : ForArray
- public data class NotInArray internal constructor(override val values: List) : ForArray
+ public data class EqualTo @PublishedApi internal constructor(override val value: Any?) : ForNullableObject
+ public data class NotEqualTo @PublishedApi internal constructor(override val value: Any?) : ForNullableObject
+ public data class LessThan @PublishedApi internal constructor(override val value: Any) : ForObject
+ public data class GreaterThan @PublishedApi internal constructor(override val value: Any) : ForObject
+ public data class LessThanOrEqualTo @PublishedApi internal constructor(override val value: Any) : ForObject
+ public data class GreaterThanOrEqualTo @PublishedApi internal constructor(override val value: Any) : ForObject
+ public data class ArrayContains @PublishedApi internal constructor(override val value: Any) : ForObject
+ public data class ArrayContainsAny @PublishedApi internal constructor(override val values: List) : ForArray
+ public data class InArray @PublishedApi internal constructor(override val values: List) : ForArray
+ public data class NotInArray @PublishedApi internal constructor(override val values: List) : ForArray
}
public sealed class Filter {
@@ -37,51 +35,199 @@ public sealed class Filter {
public abstract val constraint: WhereConstraint
}
- public data class Field internal constructor(val field: String, override val constraint: WhereConstraint) : WithConstraint()
- public data class Path internal constructor(val path: FieldPath, override val constraint: WhereConstraint) : WithConstraint()
+ public data class Field @PublishedApi internal constructor(val field: String, override val constraint: WhereConstraint) : WithConstraint()
+ public data class Path @PublishedApi internal constructor(val path: FieldPath, override val constraint: WhereConstraint) : WithConstraint()
}
public class FilterBuilder internal constructor() {
- public infix fun String.equalTo(value: Any?): Filter.WithConstraint = Filter.Field(this, WhereConstraint.EqualTo(value))
-
- public infix fun FieldPath.equalTo(value: Any?): Filter.WithConstraint = Filter.Path(this, WhereConstraint.EqualTo(value))
-
- public infix fun String.notEqualTo(value: Any?): Filter.WithConstraint = Filter.Field(this, WhereConstraint.NotEqualTo(value))
-
- public infix fun FieldPath.notEqualTo(value: Any?): Filter.WithConstraint = Filter.Path(this, WhereConstraint.NotEqualTo(value))
-
- public infix fun String.lessThan(value: Any): Filter.WithConstraint = Filter.Field(this, WhereConstraint.LessThan(value))
-
- public infix fun FieldPath.lessThan(value: Any): Filter.WithConstraint = Filter.Path(this, WhereConstraint.LessThan(value))
-
- public infix fun String.greaterThan(value: Any): Filter.WithConstraint = Filter.Field(this, WhereConstraint.GreaterThan(value))
-
- public infix fun FieldPath.greaterThan(value: Any): Filter.WithConstraint = Filter.Path(this, WhereConstraint.GreaterThan(value))
-
- public infix fun String.lessThanOrEqualTo(value: Any): Filter.WithConstraint = Filter.Field(this, WhereConstraint.LessThanOrEqualTo(value))
-
- public infix fun FieldPath.lessThanOrEqualTo(value: Any): Filter.WithConstraint = Filter.Path(this, WhereConstraint.LessThanOrEqualTo(value))
-
- public infix fun String.greaterThanOrEqualTo(value: Any): Filter.WithConstraint = Filter.Field(this, WhereConstraint.GreaterThanOrEqualTo(value))
-
- public infix fun FieldPath.greaterThanOrEqualTo(value: Any): Filter.WithConstraint = Filter.Path(this, WhereConstraint.GreaterThanOrEqualTo(value))
-
- public infix fun String.contains(value: Any): Filter.WithConstraint = Filter.Field(this, WhereConstraint.ArrayContains(value))
-
- public infix fun FieldPath.contains(value: Any): Filter.WithConstraint = Filter.Path(this, WhereConstraint.ArrayContains(value))
-
- public infix fun String.containsAny(values: List): Filter.WithConstraint = Filter.Field(this, WhereConstraint.ArrayContainsAny(values))
-
- public infix fun FieldPath.containsAny(values: List): Filter.WithConstraint = Filter.Path(this, WhereConstraint.ArrayContainsAny(values))
-
- public infix fun String.inArray(values: List): Filter.WithConstraint = Filter.Field(this, WhereConstraint.InArray(values))
-
- public infix fun FieldPath.inArray(values: List): Filter.WithConstraint = Filter.Path(this, WhereConstraint.InArray(values))
-
- public infix fun String.notInArray(values: List): Filter.WithConstraint = Filter.Field(this, WhereConstraint.NotInArray(values))
+ public var buildSettings: EncodeSettings.Builder.() -> Unit = {
+ encodeDefaults = true
+ }
- public infix fun FieldPath.notInArray(values: List): Filter.WithConstraint = Filter.Path(this, WhereConstraint.NotInArray(values))
+ public val String.isNull: Filter.WithConstraint get() = Filter.Field(this, WhereConstraint.EqualTo(null))
+ public inline infix fun String.equalTo(value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.EqualTo(encode(value, buildSettings)),
+ )
+ public fun String.equalTo(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.EqualTo(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)),
+ )
+
+ public val FieldPath.isNull: Filter.WithConstraint get() = Filter.Path(this, WhereConstraint.EqualTo(null))
+ public inline infix fun FieldPath.equalTo(value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.EqualTo(encode(value, buildSettings)),
+ )
+ public fun FieldPath.equalTo(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.EqualTo(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)),
+ )
+
+ public val String.isNotNull: Filter.WithConstraint get() = Filter.Field(this, WhereConstraint.NotEqualTo(null))
+ public inline infix fun String.notEqualTo(value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.NotEqualTo(encode(value, buildSettings)),
+ )
+ public fun String.notEqualTo(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.NotEqualTo(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)),
+ )
+
+ public val FieldPath.isNotNull: Filter.WithConstraint get() = Filter.Path(this, WhereConstraint.NotEqualTo(null))
+ public inline infix fun FieldPath.notEqualTo(value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.NotEqualTo(encode(value, buildSettings)),
+ )
+ public fun FieldPath.notEqualTo(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.NotEqualTo(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)),
+ )
+
+ public inline infix fun String.lessThan(value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.LessThan(encode(value, buildSettings)!!),
+ )
+ public fun String.lessThan(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.LessThan(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)!!),
+ )
+
+ public inline infix fun FieldPath.lessThan(value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.LessThan(encode(value, buildSettings)!!),
+ )
+ public fun FieldPath.lessThan(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.LessThan(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)!!),
+ )
+
+ public inline infix fun String.greaterThan(value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.GreaterThan(encode(value, buildSettings)!!),
+ )
+ public fun String.greaterThan(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.GreaterThan(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)!!),
+ )
+
+ public inline infix fun FieldPath.greaterThan(value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.GreaterThan(encode(value, buildSettings)!!),
+ )
+ public fun FieldPath.greaterThan(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.GreaterThan(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)!!),
+ )
+
+ public inline infix fun String.lessThanOrEqualTo(value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.LessThanOrEqualTo(encode(value, buildSettings)!!),
+ )
+ public fun String.lessThanOrEqualTo(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.LessThanOrEqualTo(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)!!),
+ )
+
+ public inline infix fun FieldPath.lessThanOrEqualTo(value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.LessThanOrEqualTo(encode(value, buildSettings)!!),
+ )
+ public fun FieldPath.lessThanOrEqualTo(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.LessThanOrEqualTo(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)!!),
+ )
+
+ public inline infix fun String.greaterThanOrEqualTo(value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.GreaterThanOrEqualTo(encode(value, buildSettings)!!),
+ )
+ public fun String.greaterThanOrEqualTo(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.GreaterThanOrEqualTo(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)!!),
+ )
+
+ public inline infix fun FieldPath.greaterThanOrEqualTo(value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.GreaterThanOrEqualTo(encode(value, buildSettings)!!),
+ )
+ public fun FieldPath.greaterThanOrEqualTo(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.GreaterThanOrEqualTo(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)!!),
+ )
+
+ public inline infix fun String.contains(value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.ArrayContains(encode(value, buildSettings)!!),
+ )
+ public fun String.contains(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.ArrayContains(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)!!),
+ )
+
+ public inline infix fun FieldPath.contains(value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.ArrayContains(encode(value, buildSettings)!!),
+ )
+ public fun FieldPath.contains(strategy: SerializationStrategy, value: T): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.ArrayContains(dev.gitlive.firebase.internal.encode(strategy, value, buildSettings)!!),
+ )
+
+ public inline infix fun String.containsAny(values: List): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.ArrayContainsAny(values.map { encode(it, buildSettings)!! }),
+ )
+ public fun String.containsAny(strategy: SerializationStrategy, values: List): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.ArrayContainsAny(values.map { dev.gitlive.firebase.internal.encode(strategy, it, buildSettings)!! }),
+ )
+
+ public inline infix fun FieldPath.containsAny(values: List): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.ArrayContainsAny(values.map { encode(it, buildSettings)!! }),
+ )
+ public fun FieldPath.containsAny(strategy: SerializationStrategy, values: List): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.ArrayContainsAny(values.map { dev.gitlive.firebase.internal.encode(strategy, it, buildSettings)!! }),
+ )
+
+ public inline infix fun String.inArray(values: List): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.InArray(values.map { encode(it, buildSettings)!! }),
+ )
+ public fun String.inArray(strategy: SerializationStrategy, values: List): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.InArray(values.map { dev.gitlive.firebase.internal.encode(strategy, it, buildSettings)!! }),
+ )
+
+ public inline infix fun FieldPath.inArray(values: List): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.InArray(values.map { encode(it, buildSettings)!! }),
+ )
+ public fun FieldPath.inArray(strategy: SerializationStrategy, values: List): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.InArray(values.map { dev.gitlive.firebase.internal.encode(strategy, it, buildSettings)!! }),
+ )
+
+ public inline infix fun String.notInArray(values: List): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.NotInArray(values.map { encode(it, buildSettings)!! }),
+ )
+ public fun String.notInArray(strategy: SerializationStrategy, values: List): Filter.WithConstraint = Filter.Field(
+ this,
+ WhereConstraint.NotInArray(values.map { dev.gitlive.firebase.internal.encode(strategy, it, buildSettings)!! }),
+ )
+
+ public inline infix fun FieldPath.notInArray(values: List): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.NotInArray(values.map { encode(it, buildSettings)!! }),
+ )
+ public fun FieldPath.notInArray(strategy: SerializationStrategy, values: List): Filter.WithConstraint = Filter.Path(
+ this,
+ WhereConstraint.NotInArray(values.map { dev.gitlive.firebase.internal.encode(strategy, it, buildSettings)!! }),
+ )
public infix fun Filter.and(right: Filter): Filter.And {
val leftList = when (this) {
diff --git a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt
index bf4723e49..c87f4194c 100644
--- a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt
+++ b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt
@@ -18,7 +18,6 @@ import dev.gitlive.firebase.firestore.internal.NativeQueryWrapper
import dev.gitlive.firebase.firestore.internal.NativeTransactionWrapper
import dev.gitlive.firebase.firestore.internal.NativeWriteBatchWrapper
import dev.gitlive.firebase.firestore.internal.SetOptions
-import dev.gitlive.firebase.firestore.internal.safeValue
import dev.gitlive.firebase.internal.decode
import dev.gitlive.firebase.internal.encodeAsObject
import kotlinx.coroutines.flow.Flow
@@ -179,31 +178,56 @@ public data class Transaction internal constructor(internal val nativeWrapper: N
internal fun setEncoded(documentRef: DocumentReference, encodedData: EncodedObject, setOptions: SetOptions): Transaction = Transaction(nativeWrapper.setEncoded(documentRef, encodedData, setOptions))
@Deprecated("Deprecated. Use builder instead", replaceWith = ReplaceWith("update(documentRef, data) { this.encodeDefaults = encodeDefaults }"))
- public fun update(documentRef: DocumentReference, data: Any, encodeDefaults: Boolean): Transaction = update(documentRef, data) {
- this.encodeDefaults = encodeDefaults
- }
+ public fun update(documentRef: DocumentReference, data: Any, encodeDefaults: Boolean): Transaction =
+ update(documentRef, data) {
+ this.encodeDefaults = encodeDefaults
+ }
public inline fun update(documentRef: DocumentReference, data: Any, buildSettings: EncodeSettings.Builder.() -> Unit = {}): Transaction = updateEncoded(documentRef, encodeAsObject(data, buildSettings))
@Deprecated("Deprecated. Use builder instead", replaceWith = ReplaceWith("update(documentRef, strategy, data) { this.encodeDefaults = encodeDefaults }"))
- public fun update(documentRef: DocumentReference, strategy: SerializationStrategy, data: T, encodeDefaults: Boolean): Transaction = update(documentRef, strategy, data) {
- this.encodeDefaults = encodeDefaults
- }
+ public fun update(documentRef: DocumentReference, strategy: SerializationStrategy, data: T, encodeDefaults: Boolean): Transaction =
+ update(documentRef, strategy, data) {
+ this.encodeDefaults = encodeDefaults
+ }
public inline fun update(documentRef: DocumentReference, strategy: SerializationStrategy, data: T, buildSettings: EncodeSettings.Builder.() -> Unit = {}): Transaction = updateEncoded(documentRef, encodeAsObject(strategy, data, buildSettings))
@JvmName("updateFields")
- public inline fun update(documentRef: DocumentReference, vararg fieldsAndValues: Pair, buildSettings: EncodeSettings.Builder.() -> Unit = {}): Transaction = updateEncodedFieldsAndValues(documentRef, encodeFieldAndValue(fieldsAndValues, buildSettings).orEmpty())
+ public fun update(documentRef: DocumentReference, vararg fieldsAndValues: Pair): Transaction =
+ update(documentRef, {}, *fieldsAndValues)
+
+ @JvmName("updateFields")
+ public fun update(documentRef: DocumentReference, buildSettings: EncodeSettings.Builder.() -> Unit, vararg fieldsAndValues: Pair): Transaction =
+ update(
+ documentRef,
+ ) {
+ this.buildSettings = buildSettings
+ fieldsAndValues.forEach { (field, value) ->
+ field to value
+ }
+ }
@JvmName("updateFieldPaths")
- public inline fun update(documentRef: DocumentReference, vararg fieldsAndValues: Pair, buildSettings: EncodeSettings.Builder.() -> Unit = {}): Transaction = updateEncodedFieldPathsAndValues(documentRef, encodeFieldAndValue(fieldsAndValues, buildSettings).orEmpty())
+ public fun update(documentRef: DocumentReference, vararg fieldsAndValues: Pair): Transaction =
+ update(documentRef, {}, *fieldsAndValues)
- @PublishedApi
- internal fun updateEncoded(documentRef: DocumentReference, encodedData: EncodedObject): Transaction = Transaction(nativeWrapper.updateEncoded(documentRef, encodedData))
+ @JvmName("updateFieldPaths")
+ public fun update(documentRef: DocumentReference, buildSettings: EncodeSettings.Builder.() -> Unit, vararg fieldsAndValues: Pair): Transaction =
+ update(
+ documentRef,
+ ) {
+ this.buildSettings = buildSettings
+ fieldsAndValues.forEach { (field, value) ->
+ field to value
+ }
+ }
- @PublishedApi
- internal fun updateEncodedFieldsAndValues(documentRef: DocumentReference, encodedFieldsAndValues: List>): Transaction = Transaction(nativeWrapper.updateEncodedFieldsAndValues(documentRef, encodedFieldsAndValues))
+ public fun update(
+ documentRef: DocumentReference,
+ fieldsAndValuesBuilder: FieldsAndValuesBuilder.() -> Unit,
+ ): Transaction = Transaction(nativeWrapper.updateEncoded(documentRef, FieldsAndValuesBuilder().apply(fieldsAndValuesBuilder).fieldAndValues))
@PublishedApi
- internal fun updateEncodedFieldPathsAndValues(documentRef: DocumentReference, encodedFieldsAndValues: List>): Transaction = Transaction(nativeWrapper.updateEncodedFieldPathsAndValues(documentRef, encodedFieldsAndValues))
+ internal fun updateEncoded(documentRef: DocumentReference, encodedData: EncodedObject): Transaction = Transaction(nativeWrapper.updateEncoded(documentRef, encodedData))
public fun delete(documentRef: DocumentReference): Transaction = Transaction(nativeWrapper.delete(documentRef))
public suspend fun get(documentRef: DocumentReference): DocumentSnapshot = DocumentSnapshot(nativeWrapper.get(documentRef))
@@ -230,14 +254,52 @@ public open class Query internal constructor(internal val nativeQuery: NativeQue
public fun orderBy(field: FieldPath, direction: Direction = Direction.ASCENDING): Query = Query(nativeQuery.orderBy(field.encoded, direction))
public fun startAfter(document: DocumentSnapshot): Query = Query(nativeQuery.startAfter(document.native))
- public fun startAfter(vararg fieldValues: Any): Query = Query(nativeQuery.startAfter(*(fieldValues.map { it.safeValue }.toTypedArray())))
+ public fun startAfter(vararg fieldValues: Any?): Query = startAfter({}, *fieldValues)
+ public fun startAfter(buildSettings: EncodeSettings.Builder.() -> Unit, vararg fieldValues: Any?): Query =
+ startAfter {
+ this.buildSettings = buildSettings
+ fieldValues.forEach {
+ add(it)
+ }
+ }
+
+ public fun startAfter(builder: FieldValueBuilder.() -> Unit): Query = Query(nativeQuery.startAfter(*FieldValueBuilder().apply(builder).fieldValues.toTypedArray()))
+
public fun startAt(document: DocumentSnapshot): Query = Query(nativeQuery.startAt(document.native))
- public fun startAt(vararg fieldValues: Any): Query = Query(nativeQuery.startAt(*(fieldValues.map { it.safeValue }.toTypedArray())))
+ public fun startAt(vararg fieldValues: Any?): Query = startAt({}, *fieldValues)
+ public fun startAt(buildSettings: EncodeSettings.Builder.() -> Unit, vararg fieldValues: Any?): Query =
+ startAt {
+ this.buildSettings = buildSettings
+ fieldValues.forEach {
+ add(it)
+ }
+ }
+
+ public fun startAt(builder: FieldValueBuilder.() -> Unit): Query = Query(nativeQuery.startAt(*FieldValueBuilder().apply(builder).fieldValues.toTypedArray()))
public fun endBefore(document: DocumentSnapshot): Query = Query(nativeQuery.endBefore(document.native))
- public fun endBefore(vararg fieldValues: Any): Query = Query(nativeQuery.endBefore(*(fieldValues.map { it.safeValue }.toTypedArray())))
+ public fun endBefore(vararg fieldValues: Any?): Query = endBefore({}, *fieldValues)
+ public fun endBefore(buildSettings: EncodeSettings.Builder.() -> Unit, vararg fieldValues: Any?): Query =
+ endBefore {
+ this.buildSettings = buildSettings
+ fieldValues.forEach {
+ add(it)
+ }
+ }
+
+ public fun endBefore(builder: FieldValueBuilder.() -> Unit): Query = Query(nativeQuery.endBefore(*FieldValueBuilder().apply(builder).fieldValues.toTypedArray()))
+
public fun endAt(document: DocumentSnapshot): Query = Query(nativeQuery.endAt(document.native))
- public fun endAt(vararg fieldValues: Any): Query = Query(nativeQuery.endAt(*(fieldValues.map { it.safeValue }.toTypedArray())))
+ public fun endAt(vararg fieldValues: Any?): Query = endAt({}, *fieldValues)
+ public fun endAt(buildSettings: EncodeSettings.Builder.() -> Unit, vararg fieldValues: Any?): Query =
+ endAt {
+ this.buildSettings = buildSettings
+ fieldValues.forEach {
+ add(it)
+ }
+ }
+
+ public fun endAt(builder: FieldValueBuilder.() -> Unit): Query = Query(nativeQuery.endAt(*FieldValueBuilder().apply(builder).fieldValues.toTypedArray()))
}
@Deprecated("Deprecated in favor of using a [FilterBuilder]", replaceWith = ReplaceWith("where { field equalTo equalTo }", "dev.gitlive.firebase.firestore"))
@@ -348,33 +410,63 @@ public data class WriteBatch internal constructor(internal val nativeWrapper: Na
internal fun setEncoded(documentRef: DocumentReference, encodedData: EncodedObject, setOptions: SetOptions): WriteBatch = WriteBatch(nativeWrapper.setEncoded(documentRef, encodedData, setOptions))
@Deprecated("Deprecated. Use builder instead", replaceWith = ReplaceWith("update(documentRef, data) { this.encodeDefaults = encodeDefaults }"))
- public inline fun update(documentRef: DocumentReference, data: T, encodeDefaults: Boolean): WriteBatch = update(documentRef, data) {
- this.encodeDefaults = encodeDefaults
- }
+ public inline fun update(documentRef: DocumentReference, data: T, encodeDefaults: Boolean): WriteBatch =
+ update(documentRef, data) {
+ this.encodeDefaults = encodeDefaults
+ }
public inline fun update(documentRef: DocumentReference, data: T, buildSettings: EncodeSettings.Builder.() -> Unit = {}): WriteBatch =
updateEncoded(documentRef, encodeAsObject(data, buildSettings))
@Deprecated("Deprecated. Use builder instead", replaceWith = ReplaceWith("update(documentRef, strategy, data) { this.encodeDefaults = encodeDefaults }"))
- public fun update(documentRef: DocumentReference, strategy: SerializationStrategy, data: T, encodeDefaults: Boolean): WriteBatch = update(documentRef, strategy, data) {
- this.encodeDefaults = encodeDefaults
- }
+ public fun update(documentRef: DocumentReference, strategy: SerializationStrategy, data: T, encodeDefaults: Boolean): WriteBatch =
+ update(documentRef, strategy, data) {
+ this.encodeDefaults = encodeDefaults
+ }
public inline fun update(documentRef: DocumentReference, strategy: SerializationStrategy, data: T, buildSettings: EncodeSettings.Builder.() -> Unit = {}): WriteBatch =
updateEncoded(documentRef, encodeAsObject(strategy, data, buildSettings))
@JvmName("updateField")
- public inline fun update(documentRef: DocumentReference, vararg fieldsAndValues: Pair, buildSettings: EncodeSettings.Builder.() -> Unit = {}): WriteBatch = updateEncodedFieldsAndValues(documentRef, encodeFieldAndValue(fieldsAndValues, buildSettings).orEmpty())
+ public fun update(documentRef: DocumentReference, vararg fieldsAndValues: Pair): WriteBatch =
+ update(documentRef, {}, *fieldsAndValues)
+
+ @JvmName("updateField")
+ public fun update(documentRef: DocumentReference, buildSettings: EncodeSettings.Builder.() -> Unit, vararg fieldsAndValues: Pair): WriteBatch =
+ update(
+ documentRef,
+ ) {
+ this.buildSettings = buildSettings
+ fieldsAndValues.forEach { (field, value) ->
+ field to value
+ }
+ }
@JvmName("updateFieldPath")
- public inline fun update(documentRef: DocumentReference, vararg fieldsAndValues: Pair, buildSettings: EncodeSettings.Builder.() -> Unit = {}): WriteBatch = updateEncodedFieldPathsAndValues(documentRef, encodeFieldAndValue(fieldsAndValues, buildSettings).orEmpty())
+ public fun update(documentRef: DocumentReference, vararg fieldsAndValues: Pair): WriteBatch =
+ update(documentRef, {}, *fieldsAndValues)
- @PublishedApi
- internal fun updateEncoded(documentRef: DocumentReference, encodedData: EncodedObject): WriteBatch = WriteBatch(nativeWrapper.updateEncoded(documentRef, encodedData))
+ @JvmName("updateFieldPath")
+ public fun update(documentRef: DocumentReference, buildSettings: EncodeSettings.Builder.() -> Unit, vararg fieldsAndValues: Pair): WriteBatch =
+ update(
+ documentRef,
+ ) {
+ this.buildSettings = buildSettings
+ fieldsAndValues.forEach { (path, value) ->
+ path to value
+ }
+ }
- @PublishedApi
- internal fun updateEncodedFieldsAndValues(documentRef: DocumentReference, encodedFieldsAndValues: List>): WriteBatch = WriteBatch(nativeWrapper.updateEncodedFieldsAndValues(documentRef, encodedFieldsAndValues))
+ public fun update(
+ documentRef: DocumentReference,
+ fieldAndValuesBuilder: FieldsAndValuesBuilder.() -> Unit,
+ ): WriteBatch = WriteBatch(
+ nativeWrapper.updateEncoded(
+ documentRef,
+ FieldsAndValuesBuilder().apply(fieldAndValuesBuilder).fieldAndValues,
+ ),
+ )
@PublishedApi
- internal fun updateEncodedFieldPathsAndValues(documentRef: DocumentReference, encodedFieldsAndValues: List>): WriteBatch = WriteBatch(nativeWrapper.updateEncodedFieldPathsAndValues(documentRef, encodedFieldsAndValues))
+ internal fun updateEncoded(documentRef: DocumentReference, encodedData: EncodedObject): WriteBatch = WriteBatch(nativeWrapper.updateEncoded(documentRef, encodedData))
public fun delete(documentRef: DocumentReference): WriteBatch = WriteBatch(nativeWrapper.delete(documentRef))
public suspend fun commit() {
@@ -513,33 +605,35 @@ public data class DocumentReference internal constructor(internal val native: Na
}
@JvmName("updateFields")
- public suspend inline fun update(vararg fieldsAndValues: Pair, buildSettings: EncodeSettings.Builder.() -> Unit = {}) {
- updateEncodedFieldsAndValues(
- encodeFieldAndValue(
- fieldsAndValues,
- buildSettings,
- ).orEmpty(),
- )
- }
+ public suspend fun update(vararg fieldsAndValues: Pair): Unit =
+ update({}, *fieldsAndValues)
- @PublishedApi
- internal suspend fun updateEncodedFieldsAndValues(encodedFieldsAndValues: List>) {
- native.updateEncodedFieldsAndValues(encodedFieldsAndValues)
- }
+ @JvmName("updateFields")
+ public suspend fun update(buildSettings: EncodeSettings.Builder.() -> Unit, vararg fieldsAndValues: Pair): Unit =
+ update {
+ this.buildSettings = buildSettings
+ fieldsAndValues.forEach { (field, value) ->
+ field to value
+ }
+ }
@JvmName("updateFieldPaths")
- public suspend inline fun update(vararg fieldsAndValues: Pair, buildSettings: EncodeSettings.Builder.() -> Unit = {}) {
- updateEncodedFieldPathsAndValues(
- encodeFieldAndValue(
- fieldsAndValues,
- buildSettings,
- ).orEmpty(),
- )
- }
+ public suspend fun update(vararg fieldsAndValues: Pair): Unit =
+ update({}, *fieldsAndValues)
- @PublishedApi
- internal suspend fun updateEncodedFieldPathsAndValues(encodedFieldsAndValues: List>) {
- native.updateEncodedFieldPathsAndValues(encodedFieldsAndValues)
+ @JvmName("updateFieldPaths")
+ public suspend fun update(buildSettings: EncodeSettings.Builder.() -> Unit, vararg fieldsAndValues: Pair): Unit =
+ update {
+ this.buildSettings = buildSettings
+ fieldsAndValues.forEach { (fieldPath, value) ->
+ fieldPath to value
+ }
+ }
+
+ public suspend fun update(
+ fieldsAndValuesBuilder: FieldsAndValuesBuilder.() -> Unit,
+ ) {
+ native.updateEncoded(FieldsAndValuesBuilder().apply(fieldsAndValuesBuilder).fieldAndValues)
}
public suspend fun delete() {
diff --git a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/helpers.kt b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/helpers.kt
index 766836a76..7247ca002 100644
--- a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/helpers.kt
+++ b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/helpers.kt
@@ -1,38 +1,39 @@
package dev.gitlive.firebase.firestore
-import dev.gitlive.firebase.EncodeSettings
-import kotlin.jvm.JvmName
+import dev.gitlive.firebase.firestore.internal.FieldAndValue
-// ** Helper method to perform an update operation. */
-@JvmName("performUpdateFields")
-@PublishedApi
-internal inline fun encodeFieldAndValue(
- fieldsAndValues: Array>,
- buildSettings: EncodeSettings.Builder.() -> Unit,
-): List>? = encodeFieldAndValue(fieldsAndValues, encodeField = { it }, encodeValue = { encode(it, buildSettings) })
+internal fun List.performUpdate(
+ updateAsField: (String, Any?, Array) -> R,
+ updateAsFieldPath: (EncodedFieldPath, Any?, Array) -> R,
+): R {
+ val first = first()
+ val remaining = drop(1).flatMap { fieldAndValue ->
+ listOf(
+ when (fieldAndValue) {
+ is FieldAndValue.WithFieldPath -> fieldAndValue.path.encoded
+ is FieldAndValue.WithStringField -> fieldAndValue.field
+ },
+ fieldAndValue.value,
+ )
+ }
+ return when (first) {
+ is FieldAndValue.WithFieldPath -> updateAsFieldPath(
+ first.path.encoded,
+ first.value,
+ remaining.toTypedArray(),
+ )
-/** Helper method to perform an update operation. */
-@JvmName("performUpdateFieldPaths")
-@PublishedApi
-internal inline fun encodeFieldAndValue(
- fieldsAndValues: Array>,
- buildSettings: EncodeSettings.Builder.() -> Unit,
-): List>? = encodeFieldAndValue(fieldsAndValues, { it.encoded }, { encode(it, buildSettings) })
+ is FieldAndValue.WithStringField -> updateAsField(
+ first.field,
+ first.value,
+ remaining.toTypedArray(),
+ )
+ }
+}
-/** Helper method to perform an update operation in Android and JS. */
-@PublishedApi
-internal inline fun encodeFieldAndValue(
- fieldsAndValues: Array>,
- encodeField: (T) -> K,
- encodeValue: (Any?) -> Any?,
-): List>? =
- fieldsAndValues.takeUnless { fieldsAndValues.isEmpty() }
- ?.map { (field, value) -> encodeField(field) to value?.let { encodeValue(it) } }
-
-internal fun List>.performUpdate(
- update: (K, Any?, Array) -> R,
-) = update(
- this[0].first,
- this[0].second,
- this.drop(1).flatMap { (field, value) -> listOf(field, value) }.toTypedArray(),
-)
+internal fun List.toEncodedMap(): Map = associate { fieldAndValue ->
+ when (fieldAndValue) {
+ is FieldAndValue.WithStringField -> fieldAndValue.field to fieldAndValue.value
+ is FieldAndValue.WithFieldPath -> fieldAndValue.path.encoded to fieldAndValue.value
+ }
+}
diff --git a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/FieldAndValue.kt b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/FieldAndValue.kt
new file mode 100644
index 000000000..c4d5beeb4
--- /dev/null
+++ b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/FieldAndValue.kt
@@ -0,0 +1,11 @@
+package dev.gitlive.firebase.firestore.internal
+
+import dev.gitlive.firebase.firestore.FieldPath
+
+internal sealed class FieldAndValue {
+
+ abstract val value: Any?
+
+ data class WithStringField(val field: String, override val value: Any?) : FieldAndValue()
+ data class WithFieldPath(val path: FieldPath, override val value: Any?) : FieldAndValue()
+}
diff --git a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt
index baa706419..7cf376cf8 100644
--- a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt
+++ b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt
@@ -1,6 +1,5 @@
package dev.gitlive.firebase.firestore.internal
-import dev.gitlive.firebase.firestore.EncodedFieldPath
import dev.gitlive.firebase.firestore.NativeCollectionReference
import dev.gitlive.firebase.firestore.NativeDocumentReferenceType
import dev.gitlive.firebase.firestore.NativeDocumentSnapshot
@@ -20,7 +19,6 @@ internal expect class NativeDocumentReference(nativeValue: NativeDocumentReferen
suspend fun get(source: Source = Source.DEFAULT): NativeDocumentSnapshot
suspend fun setEncoded(encodedData: EncodedObject, setOptions: SetOptions)
suspend fun updateEncoded(encodedData: EncodedObject)
- suspend fun updateEncodedFieldsAndValues(encodedFieldsAndValues: List>)
- suspend fun updateEncodedFieldPathsAndValues(encodedFieldsAndValues: List>)
+ suspend fun updateEncoded(encodedFieldsAndValues: List)
suspend fun delete()
}
diff --git a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeTransactionWrapper.kt b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeTransactionWrapper.kt
index 6bb72eedf..8a4df4971 100644
--- a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeTransactionWrapper.kt
+++ b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeTransactionWrapper.kt
@@ -1,7 +1,6 @@
package dev.gitlive.firebase.firestore.internal
import dev.gitlive.firebase.firestore.DocumentReference
-import dev.gitlive.firebase.firestore.EncodedFieldPath
import dev.gitlive.firebase.firestore.NativeTransaction
import dev.gitlive.firebase.internal.EncodedObject
@@ -11,8 +10,7 @@ internal expect class NativeTransactionWrapper internal constructor(native: Nati
fun setEncoded(documentRef: DocumentReference, encodedData: EncodedObject, setOptions: SetOptions): NativeTransactionWrapper
fun updateEncoded(documentRef: DocumentReference, encodedData: EncodedObject): NativeTransactionWrapper
- fun updateEncodedFieldsAndValues(documentRef: DocumentReference, encodedFieldsAndValues: List>): NativeTransactionWrapper
- fun updateEncodedFieldPathsAndValues(documentRef: DocumentReference, encodedFieldsAndValues: List>): NativeTransactionWrapper
+ fun updateEncoded(documentRef: DocumentReference, encodedFieldsAndValues: List): NativeTransactionWrapper
fun delete(documentRef: DocumentReference): NativeTransactionWrapper
suspend fun get(documentRef: DocumentReference): NativeDocumentSnapshotWrapper
}
diff --git a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeWriteBatchWrapper.kt b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeWriteBatchWrapper.kt
index bea3d0071..fee11b836 100644
--- a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeWriteBatchWrapper.kt
+++ b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeWriteBatchWrapper.kt
@@ -1,7 +1,6 @@
package dev.gitlive.firebase.firestore.internal
import dev.gitlive.firebase.firestore.DocumentReference
-import dev.gitlive.firebase.firestore.EncodedFieldPath
import dev.gitlive.firebase.firestore.NativeWriteBatch
import dev.gitlive.firebase.internal.EncodedObject
@@ -9,8 +8,7 @@ internal expect class NativeWriteBatchWrapper internal constructor(native: Nativ
val native: NativeWriteBatch
fun setEncoded(documentRef: DocumentReference, encodedData: EncodedObject, setOptions: SetOptions): NativeWriteBatchWrapper
fun updateEncoded(documentRef: DocumentReference, encodedData: EncodedObject): NativeWriteBatchWrapper
- fun updateEncodedFieldsAndValues(documentRef: DocumentReference, encodedFieldsAndValues: List>): NativeWriteBatchWrapper
- fun updateEncodedFieldPathsAndValues(documentRef: DocumentReference, encodedFieldsAndValues: List>): NativeWriteBatchWrapper
+ fun updateEncoded(documentRef: DocumentReference, encodedFieldsAndValues: List): NativeWriteBatchWrapper
fun delete(documentRef: DocumentReference): NativeWriteBatchWrapper
suspend fun commit()
}
diff --git a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/SafeValue.kt b/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/SafeValue.kt
deleted file mode 100644
index afca32060..000000000
--- a/firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/SafeValue.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package dev.gitlive.firebase.firestore.internal
-
-import dev.gitlive.firebase.firestore.DocumentReference
-import dev.gitlive.firebase.firestore.GeoPoint
-import dev.gitlive.firebase.firestore.Timestamp
-
-internal val Any.safeValue: Any get() = when (this) {
- is Timestamp -> nativeValue
- is GeoPoint -> nativeValue
- is DocumentReference -> native.nativeValue
- is Map<*, *> -> this.mapNotNull { (key, value) -> key?.let { it.safeValue to value?.safeValue } }
- is Collection<*> -> this.mapNotNull { it?.safeValue }
- else -> this
-}
diff --git a/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/DocumentReferenceTest.kt b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/DocumentReferenceTest.kt
new file mode 100644
index 000000000..d58024788
--- /dev/null
+++ b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/DocumentReferenceTest.kt
@@ -0,0 +1,430 @@
+package dev.gitlive.firebase.firestore
+
+import dev.gitlive.firebase.internal.decode
+import dev.gitlive.firebase.runTest
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.withContext
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.builtins.ListSerializer
+import kotlinx.serialization.builtins.nullable
+import kotlinx.serialization.builtins.serializer
+import kotlin.random.Random
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+import kotlin.test.assertNotNull
+import kotlin.test.assertNull
+import kotlin.test.assertTrue
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.milliseconds
+
+@IgnoreForAndroidUnitTest
+class DocumentReferenceTest : BaseFirebaseFirestoreTest() {
+
+ @Serializable
+ data class FirestoreTimeTest(
+ val prop1: String,
+ val time: BaseTimestamp?,
+ )
+
+ @Serializable
+ data class TestDataWithDocumentReference(
+ val uid: String,
+ val reference: DocumentReference,
+ val optionalReference: DocumentReference?,
+ )
+
+ @Serializable
+ data class TestDataWithOptionalDocumentReference(
+ val optionalReference: DocumentReference?,
+ )
+
+ @Test
+ fun encodeDocumentReference() = runTest {
+ val doc = firestore.document("a/b")
+ val item = TestDataWithDocumentReference("123", doc, doc)
+ val encoded = encodedAsMap(
+ encode(item) {
+ encodeDefaults = false
+ },
+ )
+ assertEquals("123", encoded["uid"])
+ assertEquals(doc.nativeValue, encoded["reference"])
+ assertEquals(doc.nativeValue, encoded["optionalReference"])
+ }
+
+ @Test
+ fun encodeNullDocumentReference() = runTest {
+ val item = TestDataWithOptionalDocumentReference(null)
+ val encoded = encodedAsMap(
+ encode(item) {
+ encodeDefaults = false
+ },
+ )
+ assertNull(encoded["optionalReference"])
+ }
+
+ @Test
+ fun decodeDocumentReference() = runTest {
+ val doc = firestore.document("a/b")
+ val obj = mapOf(
+ "uid" to "123",
+ "reference" to doc.nativeValue,
+ "optionalReference" to doc.nativeValue,
+ ).asEncoded()
+ val decoded: TestDataWithDocumentReference = decode(obj)
+ assertEquals("123", decoded.uid)
+ assertEquals(doc.path, decoded.reference.path)
+ assertEquals(doc.path, decoded.optionalReference?.path)
+ }
+
+ @Test
+ fun decodeNullDocumentReference() = runTest {
+ val obj = mapOf("optionalReference" to null).asEncoded()
+ val decoded: TestDataWithOptionalDocumentReference = decode(obj)
+ assertNull(decoded.optionalReference?.path)
+ }
+
+ @Test
+ fun testServerTimestampFieldValue() = testDocument(
+ firestore
+ .collection("testServerTimestampFieldValue")
+ .document("test"),
+ ) { doc ->
+ doc.set(
+ FirestoreTimeTest.serializer(),
+ FirestoreTimeTest("ServerTimestamp", Timestamp(123, 0)),
+ )
+ assertEquals(Timestamp(123, 0), doc.get().get("time", TimestampSerializer))
+
+ doc.set(FirestoreTimeTest.serializer(), FirestoreTimeTest("ServerTimestamp", Timestamp.ServerTimestamp))
+
+ assertNotEquals(Timestamp.ServerTimestamp, doc.get().get("time", BaseTimestamp.serializer()))
+ assertNotEquals(Timestamp.ServerTimestamp, doc.get().data(FirestoreTimeTest.serializer()).time)
+ }
+
+ @Test
+ fun testServerTimestampBehaviorNone() = testDocument(
+ firestore
+ .collection("testServerTimestampBehaviorNone")
+ .document("test${Random.nextInt()}"),
+ ) { doc ->
+ val deferredPendingWritesSnapshot = async {
+ doc.snapshots.filter { it.exists }.first()
+ }
+ nonSkippedDelay(100.milliseconds) // makes possible to catch pending writes snapshot
+
+ doc.set(
+ FirestoreTimeTest.serializer(),
+ FirestoreTimeTest("ServerTimestampBehavior", Timestamp.ServerTimestamp),
+ )
+
+ val pendingWritesSnapshot = deferredPendingWritesSnapshot.await()
+ assertTrue(pendingWritesSnapshot.metadata.hasPendingWrites)
+ assertNull(pendingWritesSnapshot.get("time", BaseTimestamp.serializer().nullable, serverTimestampBehavior = ServerTimestampBehavior.NONE))
+ }
+
+ @Test
+ fun testServerTimestampBehaviorEstimate() = testDocument(
+ firestore
+ .collection("testServerTimestampBehaviorEstimate")
+ .document("test${Random.nextInt()}"),
+ ) { doc ->
+ val deferredPendingWritesSnapshot = async {
+ doc.snapshots.filter { it.exists }.first()
+ }
+ nonSkippedDelay(100.milliseconds) // makes possible to catch pending writes snapshot
+
+ doc.set(FirestoreTimeTest.serializer(), FirestoreTimeTest("ServerTimestampBehavior", Timestamp.ServerTimestamp))
+
+ val pendingWritesSnapshot = deferredPendingWritesSnapshot.await()
+ assertTrue(pendingWritesSnapshot.metadata.hasPendingWrites)
+ assertNotNull(pendingWritesSnapshot.get("time", ServerTimestampBehavior.ESTIMATE))
+ assertNotEquals(Timestamp.ServerTimestamp, pendingWritesSnapshot.data(FirestoreTimeTest.serializer(), serverTimestampBehavior = ServerTimestampBehavior.ESTIMATE).time)
+ }
+
+ @Test
+ fun testServerTimestampBehaviorPrevious() = testDocument(
+ firestore
+ .collection("testServerTimestampBehaviorPrevious")
+ .document("test${Random.nextInt()}"),
+ ) { doc ->
+ val deferredPendingWritesSnapshot = async {
+ doc.snapshots.filter { it.exists }.first()
+ }
+ nonSkippedDelay(100.milliseconds) // makes possible to catch pending writes snapshot
+
+ doc.set(FirestoreTimeTest.serializer(), FirestoreTimeTest("ServerTimestampBehavior", Timestamp.ServerTimestamp))
+
+ val pendingWritesSnapshot = deferredPendingWritesSnapshot.await()
+ assertTrue(pendingWritesSnapshot.metadata.hasPendingWrites)
+ assertNull(pendingWritesSnapshot.get("time", BaseTimestamp.serializer().nullable, serverTimestampBehavior = ServerTimestampBehavior.PREVIOUS))
+ }
+
+ @Test
+ fun testDocumentAutoId() = testDocument(
+ firestore
+ .collection("testDocumentAutoId")
+ .document,
+ ) { doc ->
+
+ doc.set(FirestoreTest.serializer(), FirestoreTest("AutoId"))
+
+ val resultDoc = firestore
+ .collection("testDocumentAutoId")
+ .document(doc.id)
+ .get()
+
+ assertEquals(true, resultDoc.exists)
+ assertEquals("AutoId", resultDoc.get("prop1"))
+ }
+
+ @Test
+ fun testUpdateValues() = testDocument(
+ firestore
+ .collection("testFirestoreUpdateMultipleValues")
+ .document("test1"),
+ ) { doc ->
+ doc.set(
+ FirestoreTest.serializer(),
+ FirestoreTest(
+ "property",
+ count = 0,
+ nested = NestedObject("nested"),
+ duration = 600.milliseconds,
+ ),
+ )
+ val dataBefore = doc.get().data(FirestoreTest.serializer())
+ assertEquals(0, dataBefore.count)
+ assertNull(dataBefore.optional)
+ assertEquals(NestedObject("nested"), dataBefore.nested)
+ assertEquals(600.milliseconds, dataBefore.duration)
+
+ doc.update {
+ FirestoreTest::count.name to 5
+ FieldPath(FirestoreTest::optional.name) to "notNull"
+ FirestoreTest::nested.name.to(
+ NestedObject.serializer(),
+ NestedObject("newProperty"),
+ )
+ FieldPath(FirestoreTest::duration.name).to(
+ DurationAsIntSerializer(),
+ 700.milliseconds,
+ )
+ }
+ val dataAfter = doc.get().data(FirestoreTest.serializer())
+ assertEquals(5, dataAfter.count)
+ assertEquals("notNull", dataAfter.optional)
+ assertEquals(NestedObject("newProperty"), dataAfter.nested)
+ assertEquals(700.milliseconds, dataAfter.duration)
+ }
+
+ @Test
+ fun testIncrementFieldValue() = testDocument(
+ firestore
+ .collection("testFirestoreIncrementFieldValue")
+ .document("test1"),
+ ) { doc ->
+ doc.set(FirestoreTest.serializer(), FirestoreTest("increment1", count = 0))
+ val dataBefore = doc.get().data(FirestoreTest.serializer())
+ assertEquals(0, dataBefore.count)
+
+ doc.update("count" to FieldValue.increment(5))
+ val dataAfter = doc.get().data(FirestoreTest.serializer())
+ assertEquals(5, dataAfter.count)
+ }
+
+ @Test
+ fun testArrayUnion() = testDocument(
+ firestore
+ .collection("testFirestoreArrayUnion")
+ .document("test1"),
+ ) { doc ->
+ doc.set(FirestoreTest.serializer(), FirestoreTest("increment1", list = listOf("first")))
+ val dataBefore = doc.get().data(FirestoreTest.serializer())
+ assertEquals(listOf("first"), dataBefore.list)
+
+ doc.update("list" to FieldValue.arrayUnion("second"))
+ val dataAfter = doc.get().data(FirestoreTest.serializer())
+ assertEquals(listOf("first", "second"), dataAfter.list)
+ }
+
+ @Test
+ fun testArrayRemove() = testDocument(
+ firestore
+ .collection("testFirestoreArrayRemove")
+ .document("test1"),
+ ) { doc ->
+ doc.set(FirestoreTest.serializer(), FirestoreTest("increment1", list = listOf("first", "second")))
+ val dataBefore = doc.get().data(FirestoreTest.serializer())
+ assertEquals(listOf("first", "second"), dataBefore.list)
+
+ doc.update("list" to FieldValue.arrayRemove("second"))
+ val dataAfter = doc.get().data(FirestoreTest.serializer())
+ assertEquals(listOf("first"), dataAfter.list)
+ }
+
+ @Test
+ fun testLegacyDoubleTimestamp() = testDocument(
+ firestore
+ .collection("testLegacyDoubleTimestamp")
+ .document("test${Random.nextInt()}"),
+ ) { doc ->
+ @Serializable
+ data class DoubleTimestamp(
+ @Serializable(with = DoubleAsTimestampSerializer::class)
+ val time: Double?,
+ )
+
+ val deferredPendingWritesSnapshot = async {
+ doc.snapshots.filter { it.exists }.first()
+ }
+ nonSkippedDelay(100.milliseconds) // makes possible to catch pending writes snapshot
+
+ doc.set(DoubleTimestamp.serializer(), DoubleTimestamp(DoubleAsTimestampSerializer.SERVER_TIMESTAMP))
+
+ val pendingWritesSnapshot = deferredPendingWritesSnapshot.await()
+ assertTrue(pendingWritesSnapshot.metadata.hasPendingWrites)
+ assertNotNull(pendingWritesSnapshot.get("time", DoubleAsTimestampSerializer, serverTimestampBehavior = ServerTimestampBehavior.ESTIMATE))
+ assertNotEquals(DoubleAsTimestampSerializer.SERVER_TIMESTAMP, pendingWritesSnapshot.data(DoubleTimestamp.serializer(), serverTimestampBehavior = ServerTimestampBehavior.ESTIMATE).time)
+ }
+
+ @Test
+ fun testLegacyDoubleTimestampWriteNewFormatRead() = testDocument(
+ firestore
+ .collection("testLegacyDoubleTimestampEncodeDecode")
+ .document("testLegacy"),
+ ) { doc ->
+ @Serializable
+ data class LegacyDocument(
+ @Serializable(with = DoubleAsTimestampSerializer::class)
+ val time: Double,
+ )
+
+ @Serializable
+ data class NewDocument(
+ val time: Timestamp,
+ )
+
+ val ms = 12345678.0
+
+ doc.set(LegacyDocument.serializer(), LegacyDocument(time = ms))
+
+ val fetched: NewDocument = doc.get().data(NewDocument.serializer())
+ assertEquals(ms, fetched.time.toMilliseconds())
+ }
+
+ @Test
+ fun testGeoPointSerialization() = testDocument(
+ firestore.collection("geoPointSerialization")
+ .document("geoPointSerialization"),
+ ) { doc ->
+ @Serializable
+ data class DataWithGeoPoint(val geoPoint: GeoPoint)
+
+ val data = DataWithGeoPoint(GeoPoint(12.34, 56.78))
+ // store geo point
+ doc.set(DataWithGeoPoint.serializer(), data)
+ // restore data
+ val savedData = doc.get().data(DataWithGeoPoint.serializer())
+ assertEquals(data.geoPoint, savedData.geoPoint)
+
+ // update data
+ val updatedData = DataWithGeoPoint(GeoPoint(87.65, 43.21))
+ doc.update(FieldPath(DataWithGeoPoint::geoPoint.name) to updatedData.geoPoint)
+ // verify update
+ val updatedSavedData = doc.get().data(DataWithGeoPoint.serializer())
+ assertEquals(updatedData.geoPoint, updatedSavedData.geoPoint)
+ }
+
+ @Test
+ fun testDocumentReferenceSerialization() = runTest {
+ @Serializable
+ data class DataWithDocumentReference(
+ val documentReference: DocumentReference,
+ )
+
+ val collection = firestore.collection("documentReferenceSerialization")
+ val document = collection
+ .document("documentReferenceSerialization")
+ val documentRef1 = collection.document("refDoc1")
+ val documentRef2 = collection.document("refDoc2")
+
+ try {
+ documentRef1.set(mapOf("value" to 1))
+ documentRef2.set(mapOf("value" to 2))
+ val data = DataWithDocumentReference(documentRef1)
+ // store reference
+ document.set(DataWithDocumentReference.serializer(), data)
+ // restore data
+ val savedData = document.get().data(DataWithDocumentReference.serializer())
+ assertEquals(data.documentReference.path, savedData.documentReference.path)
+
+ // update data
+ val updatedData = DataWithDocumentReference(documentRef2)
+ document.update {
+ FieldPath(DataWithDocumentReference::documentReference.name).to(
+ DocumentReferenceSerializer,
+ updatedData.documentReference,
+ )
+ }
+ // verify update
+ val updatedSavedData = document.get().data(DataWithDocumentReference.serializer())
+ assertEquals(
+ updatedData.documentReference.path,
+ updatedSavedData.documentReference.path,
+ )
+ } finally {
+ document.delete()
+ documentRef1.delete()
+ documentRef2.delete()
+ }
+ }
+
+ @Test
+ fun testFieldValuesOps() = testDocument(
+ firestore.collection("fieldValuesOps")
+ .document("fieldValuesOps"),
+ ) { doc ->
+ @Serializable
+ data class TestData(val values: List)
+
+ val data = TestData(listOf(1))
+ // store
+ doc.set(TestData.serializer(), data)
+ // append & verify
+ doc.update(FieldPath(TestData::values.name) to FieldValue.arrayUnion(2))
+
+ var savedData = doc.get().data(TestData.serializer())
+ assertEquals(listOf(1, 2), savedData.values)
+
+ // remove & verify
+ doc.update(FieldPath(TestData::values.name) to FieldValue.arrayRemove(1))
+ savedData = doc.get().data(TestData.serializer())
+ assertEquals(listOf(2), savedData.values)
+
+ val list = doc.get().get(TestData::values.name, ListSerializer(Int.serializer()).nullable)
+ assertEquals(listOf(2), list)
+ // delete & verify
+ doc.update(FieldPath(TestData::values.name) to FieldValue.delete)
+ val deletedList = doc.get().get(TestData::values.name, ListSerializer(Int.serializer()).nullable)
+ assertNull(deletedList)
+ }
+
+ private suspend fun nonSkippedDelay(timeout: Duration) = withContext(Dispatchers.Default) {
+ delay(timeout)
+ }
+
+ private fun testDocument(document: DocumentReference, block: suspend CoroutineScope.(DocumentReference) -> Unit) = runTest {
+ try {
+ block(document)
+ } finally {
+ document.delete()
+ }
+ }
+}
diff --git a/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/FirestoreSourceTest.kt b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/FirestoreSourceTest.kt
index 2a5d74d90..f87664321 100644
--- a/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/FirestoreSourceTest.kt
+++ b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/FirestoreSourceTest.kt
@@ -12,7 +12,7 @@ class FirestoreSourceTest {
lateinit var firestore: FirebaseFirestore
companion object {
- val testDoc = FirebaseFirestoreTest.FirestoreTest(
+ val testDoc = BaseFirebaseFirestoreTest.FirestoreTest(
"aaa",
0.0,
1,
@@ -21,10 +21,6 @@ class FirestoreSourceTest {
)
}
- private suspend fun setDoc() {
- firestore.collection("testFirestoreQuerying").document("one").set(testDoc)
- }
-
private fun initializeFirebase(persistenceEnabled: Boolean = false) {
val app = Firebase.apps(context).firstOrNull() ?: Firebase.initialize(
context,
@@ -58,67 +54,75 @@ class FirestoreSourceTest {
}
@Test
- fun testGetFromServer_withPersistence() = runTest {
- initializeFirebase(persistenceEnabled = true)
- setDoc()
- val doc = firestore.collection("testFirestoreQuerying").document("one").get(Source.SERVER)
+ fun testGetFromServer_withPersistence() = testFirebaseDoc(true) {
+ val doc = get(Source.SERVER)
assertTrue(doc.exists)
assertFalse(doc.metadata.isFromCache)
}
@Test
- fun testGetFromServer_withoutPersistence() = runTest {
- initializeFirebase(persistenceEnabled = false)
- setDoc()
- val doc = firestore.collection("testFirestoreQuerying").document("one").get(Source.SERVER)
+ fun testGetFromServer_withoutPersistence() = testFirebaseDoc(false) {
+ val doc = get(Source.SERVER)
assertTrue(doc.exists)
assertFalse(doc.metadata.isFromCache)
}
@Test
- fun testGetFromCache() = runTest {
- initializeFirebase(persistenceEnabled = true)
-
+ fun testGetFromCache() = testFirebaseDoc(true) {
// Warm up cache by setting a document
- setDoc()
+ set(testDoc)
- val cachedDoc = firestore.collection("testFirestoreQuerying").document("one").get(Source.CACHE)
+ val cachedDoc = get(Source.CACHE)
assertTrue(cachedDoc.exists)
assertTrue(cachedDoc.metadata.isFromCache)
}
@Test
- fun testGetFromCache_withoutPersistence() = runTest {
- initializeFirebase(persistenceEnabled = false)
- setDoc()
+ fun testGetFromCache_withoutPersistence() = testFirebaseDoc(false) {
assertFailsWith(FirebaseFirestoreException::class) {
- firestore.collection("testFirestoreQuerying").document("one").get(Source.CACHE)
+ get(Source.CACHE)
}
}
@Test
- fun testGetDefault_withPersistence() = runTest {
- initializeFirebase(persistenceEnabled = false)
- val doc = firestore.collection("testFirestoreQuerying").document("one").get(Source.DEFAULT)
+ fun testGetDefault_withPersistence() = testFirebaseDoc(false) {
+ val doc = get(Source.DEFAULT)
assertTrue(doc.exists)
assertFalse(doc.metadata.isFromCache)
}
@Test
- fun testGet() = runTest {
- initializeFirebase(persistenceEnabled = false)
- val doc = firestore.collection("testFirestoreQuerying").document("one").get()
+ fun testGet() = testFirebaseDoc(false) {
+ val doc = get()
assertTrue(doc.exists)
assertFalse(doc.metadata.isFromCache)
}
@Test
- fun testGetDefault_withoutPersistence() = runTest {
- initializeFirebase(persistenceEnabled = true)
- setDoc()
- val doc = firestore.collection("testFirestoreQuerying").document("one").get(Source.DEFAULT)
+ fun testGetDefault_withoutPersistence() = testFirebaseDoc(true) {
+ val doc = get(Source.DEFAULT)
assertTrue(doc.exists)
// Firebase defaults to first fetching from server
assertFalse(doc.metadata.isFromCache)
}
+
+ private fun testFirebaseDoc(
+ persistenceEnabled: Boolean,
+ block: suspend DocumentReference.() -> Unit,
+ ) = runTest {
+ initializeFirebase()
+ val doc = firestore.collection("testFirestoreQuerying").document("one")
+ doc.set(testDoc)
+
+ Firebase.apps(context).forEach { it.delete() }
+
+ initializeFirebase(persistenceEnabled = persistenceEnabled)
+
+ val newDoc = firestore.collection("testFirestoreQuerying").document("one")
+ try {
+ newDoc.block()
+ } finally {
+ newDoc.delete()
+ }
+ }
}
diff --git a/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/QueryTest.kt b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/QueryTest.kt
new file mode 100644
index 000000000..665044bda
--- /dev/null
+++ b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/QueryTest.kt
@@ -0,0 +1,662 @@
+package dev.gitlive.firebase.firestore
+
+import dev.gitlive.firebase.runTest
+import kotlinx.serialization.KSerializer
+import kotlinx.serialization.Serializable
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertNotNull
+import kotlin.time.Duration.Companion.milliseconds
+
+open class QueryTest : BaseFirebaseFirestoreTest() {
+
+ companion object {
+ const val COLLECTION = "testFirestoreQuerying"
+ val testOne = FirestoreTest(
+ "aaa",
+ 0.0,
+ 1,
+ listOf("a", "aa", "aaa"),
+ "notNull",
+ NestedObject("ddd"),
+ listOf(NestedObject("l1"), NestedObject("l2"), NestedObject("l3")),
+ 100.milliseconds,
+ )
+ val testTwo = FirestoreTest(
+ "bbb",
+ 0.0,
+ 2,
+ listOf("b", "bb", "ccc"),
+ null,
+ NestedObject("eee"),
+ listOf(NestedObject("l2"), NestedObject("l4"), NestedObject("l5")),
+ 200.milliseconds,
+ )
+ val testThree = FirestoreTest(
+ "ccc",
+ 1.0,
+ 3,
+ listOf("c", "cc", "ccc"),
+ "notNull",
+ NestedObject("fff"),
+ listOf(NestedObject("l3"), NestedObject("l6"), NestedObject("l7")),
+ 300.milliseconds,
+ )
+ }
+
+ private val collection get() = firestore.collection(COLLECTION)
+
+ @Test
+ fun testStringOrderBy() = runTestWithFirestoreData {
+ val resultDocs = collection
+ .orderBy(FirestoreTest::prop1.name)
+ .get()
+ .documents
+ assertEquals(3, resultDocs.size)
+ assertEquals("aaa", resultDocs[0].get(FirestoreTest::prop1.name))
+ assertEquals("bbb", resultDocs[1].get(FirestoreTest::prop1.name))
+ assertEquals("ccc", resultDocs[2].get(FirestoreTest::prop1.name))
+ }
+
+ @Test
+ fun testFieldOrderBy() = runTestWithFirestoreData {
+ val resultDocs = firestore.collection(COLLECTION)
+ .orderBy(FieldPath(FirestoreTest::prop1.name)).get().documents
+ assertEquals(3, resultDocs.size)
+ assertEquals("aaa", resultDocs[0].get(FirestoreTest::prop1.name))
+ assertEquals("bbb", resultDocs[1].get(FirestoreTest::prop1.name))
+ assertEquals("ccc", resultDocs[2].get(FirestoreTest::prop1.name))
+ }
+
+ @Test
+ fun testStringOrderByAscending() = runTestWithFirestoreData {
+ val resultDocs = firestore.collection(COLLECTION)
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING).get().documents
+ assertEquals(3, resultDocs.size)
+ assertEquals("aaa", resultDocs[0].get(FirestoreTest::prop1.name))
+ assertEquals("bbb", resultDocs[1].get(FirestoreTest::prop1.name))
+ assertEquals("ccc", resultDocs[2].get(FirestoreTest::prop1.name))
+ }
+
+ @Test
+ fun testFieldOrderByAscending() = runTestWithFirestoreData {
+ val resultDocs = firestore.collection(COLLECTION)
+ .orderBy(FieldPath(FirestoreTest::prop1.name), Direction.ASCENDING).get().documents
+ assertEquals(3, resultDocs.size)
+ assertEquals("aaa", resultDocs[0].get(FirestoreTest::prop1.name))
+ assertEquals("bbb", resultDocs[1].get(FirestoreTest::prop1.name))
+ assertEquals("ccc", resultDocs[2].get(FirestoreTest::prop1.name))
+ }
+
+ @Test
+ fun testStringOrderByDescending() = runTestWithFirestoreData {
+ val resultDocs = firestore.collection(COLLECTION)
+ .orderBy(FirestoreTest::prop1.name, Direction.DESCENDING).get().documents
+ assertEquals(3, resultDocs.size)
+ assertEquals("ccc", resultDocs[0].get(FirestoreTest::prop1.name))
+ assertEquals("bbb", resultDocs[1].get(FirestoreTest::prop1.name))
+ assertEquals("aaa", resultDocs[2].get(FirestoreTest::prop1.name))
+ }
+
+ @Test
+ fun testFieldOrderByDescending() = runTestWithFirestoreData {
+ val resultDocs = firestore.collection(COLLECTION)
+ .orderBy(FieldPath(FirestoreTest::prop1.name), Direction.DESCENDING).get().documents
+ assertEquals(3, resultDocs.size)
+ assertEquals("ccc", resultDocs[0].get(FirestoreTest::prop1.name))
+ assertEquals("bbb", resultDocs[1].get(FirestoreTest::prop1.name))
+ assertEquals("aaa", resultDocs[2].get(FirestoreTest::prop1.name))
+ }
+
+ @Test
+ fun testQueryEqualTo() = runTestWithFirestoreData {
+ val fieldQuery = collection
+ .where { FirestoreTest::prop1.name equalTo testOne.prop1 }
+
+ fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
+
+ val pathQuery = collection
+ .where { FieldPath(FirestoreTest::prop1.name) equalTo testTwo.prop1 }
+
+ pathQuery.assertDocuments(FirestoreTest.serializer(), testTwo)
+
+ val nullableQuery = collection
+ .where { FieldPath(FirestoreTest::optional.name).isNull }
+
+ nullableQuery.assertDocuments(FirestoreTest.serializer(), testTwo)
+
+ val serializeFieldQuery = collection.where {
+ FirestoreTest::nested.name.equalTo(NestedObject.serializer(), testOne.nested!!)
+ }
+ serializeFieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
+
+ val serializePathQuery = collection.where {
+ FieldPath(FirestoreTest::nested.name).equalTo(NestedObject.serializer(), testTwo.nested!!)
+ }
+ serializePathQuery.assertDocuments(FirestoreTest.serializer(), testTwo)
+ }
+
+ @Test
+ fun testQueryNotEqualTo() = runTestWithFirestoreData {
+ val fieldQuery = collection
+ .where { FirestoreTest::prop1.name notEqualTo testOne.prop1 }
+
+ fieldQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+
+ val pathQuery = collection
+ .where { FieldPath(FirestoreTest::prop1.name) notEqualTo testTwo.prop1 }
+
+ pathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testThree)
+
+ val nullableQuery = collection
+ .where { FieldPath(FirestoreTest::optional.name).isNotNull }
+
+ nullableQuery.assertDocuments(FirestoreTest.serializer(), testOne, testThree)
+
+ val serializeFieldQuery = collection.where {
+ FirestoreTest::nested.name.notEqualTo(NestedObject.serializer(), testOne.nested!!)
+ }
+ serializeFieldQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+
+ val serializePathQuery = collection.where {
+ FieldPath(FirestoreTest::nested.name).notEqualTo(NestedObject.serializer(), testTwo.nested!!)
+ }
+ serializePathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testThree)
+ }
+
+ @Test
+ fun testQueryLessThan() = runTestWithFirestoreData {
+ val fieldQuery = collection
+ .where { "count" lessThan testThree.count }
+
+ fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val pathQuery = collection
+ .where { FieldPath(FirestoreTest::count.name) lessThan testTwo.count }
+
+ pathQuery.assertDocuments(FirestoreTest.serializer(), testOne)
+
+ val serializeFieldQuery = collection.where {
+ "duration".lessThan(DurationAsIntSerializer(), testThree.duration)
+ }
+ serializeFieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val serializePathQuery = collection.where {
+ FieldPath(FirestoreTest::duration.name).lessThan(DurationAsIntSerializer(), testTwo.duration)
+ }
+ serializePathQuery.assertDocuments(FirestoreTest.serializer(), testOne)
+ }
+
+ @Test
+ fun testQueryGreaterThan() = runTestWithFirestoreData {
+ val fieldQuery = collection
+ .where { "count" greaterThan testOne.count }
+
+ fieldQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+
+ val pathQuery = collection
+ .where { FieldPath(FirestoreTest::count.name) greaterThan testTwo.count }
+
+ pathQuery.assertDocuments(FirestoreTest.serializer(), testThree)
+
+ val serializeFieldQuery = collection.where {
+ "duration".greaterThan(DurationAsIntSerializer(), testOne.duration)
+ }
+ serializeFieldQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+
+ val serializePathQuery = collection.where {
+ FieldPath(FirestoreTest::duration.name).greaterThan(DurationAsIntSerializer(), testTwo.duration)
+ }
+ serializePathQuery.assertDocuments(FirestoreTest.serializer(), testThree)
+ }
+
+ @Test
+ fun testQueryLessThanOrEqualTo() = runTestWithFirestoreData {
+ val fieldQuery = collection
+ .where { "count" lessThanOrEqualTo testOne.count }
+
+ fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
+
+ val pathQuery = collection
+ .where { FieldPath(FirestoreTest::count.name) lessThanOrEqualTo testTwo.count }
+
+ pathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val serializeFieldQuery = collection.where {
+ "duration".lessThanOrEqualTo(DurationAsIntSerializer(), testOne.duration)
+ }
+ serializeFieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
+
+ val serializePathQuery = collection.where {
+ FieldPath(FirestoreTest::duration.name).lessThanOrEqualTo(DurationAsIntSerializer(), testTwo.duration)
+ }
+ serializePathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+ }
+
+ @Test
+ fun testQueryGreaterThanOrEqualTo() = runTestWithFirestoreData {
+ val fieldQuery = collection
+ .where { "count" greaterThanOrEqualTo testThree.count }
+
+ fieldQuery.assertDocuments(FirestoreTest.serializer(), testThree)
+
+ val pathQuery = collection
+ .where { FieldPath(FirestoreTest::count.name) greaterThanOrEqualTo testTwo.count }
+
+ pathQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+
+ val serializeFieldQuery = collection.where {
+ "duration".greaterThanOrEqualTo(DurationAsIntSerializer(), testTwo.duration)
+ }
+ serializeFieldQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+
+ val serializePathQuery = collection.where {
+ FieldPath(FirestoreTest::duration.name).greaterThanOrEqualTo(DurationAsIntSerializer(), testThree.duration)
+ }
+ serializePathQuery.assertDocuments(FirestoreTest.serializer(), testThree)
+ }
+
+ @Test
+ fun testQueryArrayContains() = runTestWithFirestoreData {
+ val fieldQuery = collection
+ .where { "list" contains "a" }
+
+ fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
+
+ val pathQuery = collection
+ .where { FieldPath(FirestoreTest::list.name) contains "ccc" }
+
+ pathQuery.assertDocuments(FirestoreTest.serializer(), testThree, testTwo)
+
+ val serializeFieldQuery = collection.where {
+ "nestedList".contains(NestedObject.serializer(), NestedObject("l2"))
+ }
+ serializeFieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val serializePathQuery = collection.where {
+ FieldPath(FirestoreTest::nestedList.name).contains(NestedObject.serializer(), NestedObject("l3"))
+ }
+ serializePathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testThree)
+ }
+
+ @Test
+ fun testQueryArrayContainsAny() = runTestWithFirestoreData {
+ val fieldQuery = collection
+ .where { "list" containsAny listOf("a", "b") }
+
+ fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val pathQuery = collection
+ .where { FieldPath(FirestoreTest::list.name) containsAny listOf("c", "d") }
+
+ pathQuery.assertDocuments(FirestoreTest.serializer(), testThree)
+
+ val serializeFieldQuery = collection.where {
+ "nestedList".containsAny(NestedObject.serializer(), listOf(NestedObject("l1"), NestedObject("l4")))
+ }
+ serializeFieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val serializePathQuery = collection.where {
+ FieldPath(FirestoreTest::nestedList.name).containsAny(NestedObject.serializer(), listOf(NestedObject("l5"), NestedObject("l7")))
+ }
+ serializePathQuery.assertDocuments(FirestoreTest.serializer(), testThree, testTwo)
+ }
+
+ @Test
+ fun testQueryInArray() = runTestWithFirestoreData {
+ val fieldQuery = collection
+ .where { FirestoreTest::prop1.name inArray listOf("aaa", "bbb") }
+
+ fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val pathQuery = collection
+ .where { FieldPath(FirestoreTest::prop1.name) inArray listOf("ccc", "ddd") }
+
+ pathQuery.assertDocuments(FirestoreTest.serializer(), testThree)
+
+ val serializeFieldQuery = collection.where {
+ FirestoreTest::nested.name.inArray(NestedObject.serializer(), listOf(NestedObject("ddd"), NestedObject("eee")))
+ }
+ serializeFieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val serializePathQuery = collection.where {
+ FieldPath(FirestoreTest::nested.name).inArray(NestedObject.serializer(), listOf(NestedObject("eee"), NestedObject("fff")))
+ }
+ serializePathQuery.assertDocuments(FirestoreTest.serializer(), testThree, testTwo)
+ }
+
+ @Test
+ fun testQueryNotInArray() = runTestWithFirestoreData {
+ val fieldQuery = collection
+ .where { FirestoreTest::prop1.name notInArray listOf("aaa", "bbb") }
+
+ fieldQuery.assertDocuments(FirestoreTest.serializer(), testThree)
+
+ val pathQuery = collection
+ .where { FieldPath(FirestoreTest::prop1.name) notInArray listOf("ccc", "ddd") }
+
+ pathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val serializeFieldQuery = collection.where {
+ FirestoreTest::nested.name.notInArray(NestedObject.serializer(), listOf(NestedObject("ddd"), NestedObject("eee")))
+ }
+ serializeFieldQuery.assertDocuments(FirestoreTest.serializer(), testThree)
+
+ val serializePathQuery = collection.where {
+ FieldPath(FirestoreTest::nested.name).notInArray(NestedObject.serializer(), listOf(NestedObject("eee"), NestedObject("fff")))
+ }
+ serializePathQuery.assertDocuments(FirestoreTest.serializer(), testOne)
+ }
+
+ @Test
+ fun testCompoundQuery() = runTestWithFirestoreData {
+ val andQuery = collection
+ .where {
+ FieldPath(FirestoreTest::prop1.name) inArray listOf("aaa", "bbb") and (FieldPath(FirestoreTest::count.name) equalTo 1)
+ }
+ andQuery.assertDocuments(FirestoreTest.serializer(), testOne)
+
+ val orQuery = collection
+ .where {
+ FieldPath(FirestoreTest::prop1.name) equalTo "aaa" or (FieldPath(FirestoreTest::count.name) equalTo 2)
+ }
+ orQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val andOrQuery = collection
+ .where {
+ all(
+ any(
+ FieldPath(FirestoreTest::prop1.name) equalTo "aaa",
+ FieldPath(FirestoreTest::count.name) equalTo 2,
+ )!!,
+ FieldPath(FirestoreTest::list.name) contains "a",
+ )
+ }
+ andOrQuery.assertDocuments(FirestoreTest.serializer(), testOne)
+ }
+
+ @Test
+ fun testQueryByDocumentId() = runTestWithFirestoreData {
+ val fieldQuery = collection
+ .where { FieldPath.documentId equalTo "one" }
+ fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
+ }
+
+ @Test
+ fun testQueryByTimestamp() = runTest {
+ @Serializable
+ data class DocumentWithTimestamp(
+ val time: Timestamp,
+ )
+
+ val collection = firestore
+ .collection("testQueryByTimestamp")
+
+ val timestamp = Timestamp.fromMilliseconds(1693262549000.0)
+
+ val pastTimestamp = Timestamp(timestamp.seconds - 60, 12345000) // note: iOS truncates 3 last digits of nanoseconds due to internal conversions
+ val futureTimestamp = Timestamp(timestamp.seconds + 60, 78910000)
+
+ val doc1 = collection.add(DocumentWithTimestamp.serializer(), DocumentWithTimestamp(pastTimestamp))
+ val doc2 = collection.add(DocumentWithTimestamp.serializer(), DocumentWithTimestamp(futureTimestamp))
+
+ try {
+ val equalityQueryResult = collection.where {
+ FieldPath(DocumentWithTimestamp::time.name) equalTo pastTimestamp
+ }.get().documents.map { it.data(DocumentWithTimestamp.serializer()) }.toSet()
+
+ assertEquals(setOf(DocumentWithTimestamp(pastTimestamp)), equalityQueryResult)
+
+ val gtQueryResult = collection.where {
+ FieldPath(DocumentWithTimestamp::time.name) greaterThan timestamp
+ }.get().documents.map { it.data(DocumentWithTimestamp.serializer()) }.toSet()
+
+ assertEquals(setOf(DocumentWithTimestamp(futureTimestamp)), gtQueryResult)
+ } finally {
+ doc1.delete()
+ doc2.delete()
+ }
+ }
+
+ @Test
+ fun testStartAfterDocumentSnapshot() = runTestWithFirestoreData {
+ val query = collection
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ val firstPage = query.limit(2)
+
+ firstPage.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+ val lastDocumentSnapshot = firstPage.get().documents.lastOrNull()
+ assertNotNull(lastDocumentSnapshot)
+
+ val secondPage = query.startAfter(lastDocumentSnapshot)
+ secondPage.assertDocuments(FirestoreTest.serializer(), testThree)
+ }
+
+ @Test
+ fun testStartAfterFieldValues() = runTestWithFirestoreData {
+ val query = collection
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ query.assertDocuments(FirestoreTest.serializer(), testOne, testTwo, testThree)
+
+ val secondPage = query.startAfter("bbb")
+ secondPage.assertDocuments(FirestoreTest.serializer(), testThree)
+
+ val encodedQuery = collection
+ .orderBy(FirestoreTest::nested.name, Direction.ASCENDING)
+
+ val encodedSecondPage = encodedQuery.startAfter {
+ addWithStrategy(NestedObject.serializer(), NestedObject("eee"))
+ }
+ encodedSecondPage.assertDocuments(FirestoreTest.serializer(), testThree)
+
+ val multipleQuery = collection
+ .orderBy(FieldPath(FirestoreTest::time.name), Direction.ASCENDING)
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ val multipleSecondPage = multipleQuery.startAfter(0.0, "aaa")
+ multipleSecondPage.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+
+ val encodedMultipleQuery = collection
+ .orderBy(FieldPath(FirestoreTest::time.name), Direction.ASCENDING)
+ .orderBy(FirestoreTest::nested.name, Direction.ASCENDING)
+
+ val encodedMultipleSecondPage = encodedMultipleQuery.startAfter {
+ add(0.0)
+ addWithStrategy(NestedObject.serializer(), NestedObject("ddd"))
+ }
+ encodedMultipleSecondPage.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+ }
+
+ @Test
+ fun testStartAtDocumentSnapshot() = runTestWithFirestoreData {
+ val query = collection
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ val firstPage = query.limit(2)
+ firstPage.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val lastDocumentSnapshot = firstPage.get().documents.lastOrNull()
+ assertNotNull(lastDocumentSnapshot)
+
+ val secondPage = query.startAt(lastDocumentSnapshot)
+ secondPage.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+ }
+
+ @Test
+ fun testStartAtFieldValues() = runTestWithFirestoreData {
+ val query = collection
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ val secondPage = query.startAt("bbb")
+ secondPage.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+
+ val encodedQuery = collection
+ .orderBy(FirestoreTest::nested.name, Direction.ASCENDING)
+
+ val encodedSecondPage = encodedQuery.startAt {
+ addWithStrategy(NestedObject.serializer(), NestedObject("eee"))
+ }
+ encodedSecondPage.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+
+ val multipleQuery = collection
+ .orderBy(FieldPath(FirestoreTest::time.name), Direction.ASCENDING)
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ val multipleSecondPage = multipleQuery.startAt(0.0, "bbb")
+ multipleSecondPage.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+
+ val encodedMultipleQuery = collection
+ .orderBy(FieldPath(FirestoreTest::time.name), Direction.ASCENDING)
+ .orderBy(FirestoreTest::nested.name, Direction.ASCENDING)
+
+ val encodedMultipleSecondPage = encodedMultipleQuery.startAt {
+ add(0.0)
+ addWithStrategy(NestedObject.serializer(), NestedObject("eee"))
+ }
+ encodedMultipleSecondPage.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
+ }
+
+ @Test
+ fun testEndBeforeDocumentSnapshot() = runTestWithFirestoreData {
+ val query = collection
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ val firstPage = query.limit(2)
+ firstPage.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val lastDocumentSnapshot = firstPage.get().documents.lastOrNull()
+ assertNotNull(lastDocumentSnapshot)
+
+ val secondPage = query.endBefore(lastDocumentSnapshot)
+ secondPage.assertDocuments(FirestoreTest.serializer(), testOne)
+ }
+
+ @Test
+ fun testEndBeforeFieldValues() = runTestWithFirestoreData {
+ val query = collection
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ val secondPage = query.endBefore("bbb")
+ secondPage.assertDocuments(FirestoreTest.serializer(), testOne)
+
+ val encodedQuery = collection
+ .orderBy(FirestoreTest::nested.name, Direction.ASCENDING)
+
+ val encodedSecondPage = encodedQuery.endBefore {
+ addWithStrategy(NestedObject.serializer(), NestedObject("eee"))
+ }
+ encodedSecondPage.assertDocuments(FirestoreTest.serializer(), testOne)
+
+ val multipleQuery = collection
+ .orderBy(FieldPath(FirestoreTest::time.name), Direction.ASCENDING)
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ val multipleSecondPage = multipleQuery.endBefore(0.0, "bbb")
+ multipleSecondPage.assertDocuments(FirestoreTest.serializer(), testOne)
+
+ val encodedMultipleQuery = collection
+ .orderBy(FieldPath(FirestoreTest::time.name), Direction.ASCENDING)
+ .orderBy(FirestoreTest::nested.name, Direction.ASCENDING)
+
+ val encodedMultipleSecondPage = encodedMultipleQuery.endBefore {
+ add(0.0)
+ addWithStrategy(NestedObject.serializer(), NestedObject("eee"))
+ }
+ encodedMultipleSecondPage.assertDocuments(FirestoreTest.serializer(), testOne)
+ }
+
+ @Test
+ fun testEndAtDocumentSnapshot() = runTestWithFirestoreData {
+ val query = collection
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ val firstPage = query.limit(2) // First 2 results
+ firstPage.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val lastDocumentSnapshot = firstPage.get().documents.lastOrNull()
+ assertNotNull(lastDocumentSnapshot)
+
+ val secondPage = query.endAt(lastDocumentSnapshot)
+ secondPage.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+ }
+
+ @Test
+ fun testEndAtFieldValues() = runTestWithFirestoreData {
+ val query = collection
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ val secondPage = query.endAt("bbb")
+ secondPage.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val encodedQuery = collection
+ .orderBy(FirestoreTest::nested.name, Direction.ASCENDING)
+
+ val encodedSecondPage = encodedQuery.endAt {
+ addWithStrategy(NestedObject.serializer(), NestedObject("eee"))
+ }
+ encodedSecondPage.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
+
+ val multipleQuery = collection
+ .orderBy(FieldPath(FirestoreTest::time.name), Direction.ASCENDING)
+ .orderBy(FirestoreTest::prop1.name, Direction.ASCENDING)
+
+ val multipleSecondPage = multipleQuery.endAt(0.0, "aaa")
+ multipleSecondPage.assertDocuments(FirestoreTest.serializer(), testOne)
+
+ val encodedMultipleQuery = collection
+ .orderBy(FieldPath(FirestoreTest::time.name), Direction.ASCENDING)
+ .orderBy(FirestoreTest::nested.name, Direction.ASCENDING)
+
+ val encodedMultipleSecondPage = encodedMultipleQuery.endAt {
+ add(0.0)
+ addWithStrategy(NestedObject.serializer(), NestedObject("ddd"))
+ }
+ encodedMultipleSecondPage.assertDocuments(FirestoreTest.serializer(), testOne)
+ }
+
+ private fun runTestWithFirestoreData(
+ documentOne: FirestoreTest = testOne,
+ documentTwo: FirestoreTest = testTwo,
+ documentThree: FirestoreTest = testThree,
+ block: suspend () -> Unit,
+ ) = runTest {
+ try {
+ setupFirestoreData(documentOne, documentTwo, documentThree)
+ block()
+ } finally {
+ cleanFirestoreData()
+ }
+ }
+
+ private suspend fun setupFirestoreData(
+ documentOne: FirestoreTest = testOne,
+ documentTwo: FirestoreTest = testTwo,
+ documentThree: FirestoreTest = testThree,
+ ) {
+ firestore.collection(COLLECTION)
+ .document("one")
+ .set(FirestoreTest.serializer(), documentOne)
+ firestore.collection(COLLECTION)
+ .document("two")
+ .set(FirestoreTest.serializer(), documentTwo)
+ firestore.collection(COLLECTION)
+ .document("three")
+ .set(FirestoreTest.serializer(), documentThree)
+ }
+
+ private suspend fun cleanFirestoreData() {
+ firestore.collection(COLLECTION).document("one").delete()
+ firestore.collection(COLLECTION).document("two").delete()
+ firestore.collection(COLLECTION).document("three").delete()
+ }
+
+ private suspend fun Query.assertDocuments(serializer: KSerializer, vararg expected: T) {
+ val documents = get().documents
+ assertEquals(expected.size, documents.size)
+ documents.forEachIndexed { index, documentSnapshot ->
+ assertEquals(expected[index], documentSnapshot.data(serializer))
+ }
+ }
+}
diff --git a/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/TransactionTest.kt b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/TransactionTest.kt
new file mode 100644
index 000000000..5a68d53a8
--- /dev/null
+++ b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/TransactionTest.kt
@@ -0,0 +1,53 @@
+package dev.gitlive.firebase.firestore
+
+import dev.gitlive.firebase.runTest
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+import kotlin.time.Duration.Companion.milliseconds
+
+@IgnoreForAndroidUnitTest
+class TransactionTest : BaseFirebaseFirestoreTest() {
+
+ @Test
+ fun runTransaction() = runTest {
+ val collection = firestore.collection("testServerTestTransaction")
+ val document = collection.document("doc1")
+ try {
+ document.set(
+ strategy = FirestoreTest.serializer(),
+ data = FirestoreTest(
+ prop1 = "prop1",
+ count = 0,
+ ),
+ )
+ val result = firestore.runTransaction {
+ val count = get(document).data(FirestoreTest.serializer()).count
+
+ if (count < 1) {
+ update(document) {
+ FirestoreTest::prop1.name to "newProperty"
+ FieldPath(FirestoreTest::count.name) to 5
+ FirestoreTest::duration.name.to(DurationAsIntSerializer(), 100.milliseconds)
+ FieldPath(FirestoreTest::nested.name).to(
+ NestedObject.serializer(),
+ NestedObject("nested"),
+ )
+ }
+ true
+ } else {
+ throw IllegalStateException("Invalid count")
+ }
+ }
+ assertTrue(result)
+
+ val updated = document.get().data(FirestoreTest.serializer())
+ assertEquals("newProperty", updated.prop1)
+ assertEquals(5, updated.count)
+ assertEquals(100.milliseconds, updated.duration)
+ assertEquals(NestedObject("nested"), updated.nested)
+ } finally {
+ document.delete()
+ }
+ }
+}
diff --git a/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/WriteBatchTest.kt b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/WriteBatchTest.kt
new file mode 100644
index 000000000..f5e8ece3f
--- /dev/null
+++ b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/WriteBatchTest.kt
@@ -0,0 +1,210 @@
+package dev.gitlive.firebase.firestore
+
+import dev.gitlive.firebase.runTest
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.time.Duration.Companion.milliseconds
+
+@IgnoreForAndroidUnitTest
+class WriteBatchTest : BaseFirebaseFirestoreTest() {
+
+ private val collection get() = firestore
+ .collection("testServerTestSetBatch")
+
+ @Test
+ fun testSetBatch() = testBatch { doc1, doc2 ->
+ val batch = firestore.batch()
+ batch.set(
+ documentRef = doc1,
+ strategy = FirestoreTest.serializer(),
+ data = FirestoreTest(
+ prop1 = "prop1",
+ time = 123.0,
+ ),
+ )
+ batch.set(
+ documentRef = doc2,
+ strategy = FirestoreTest.serializer(),
+ data = FirestoreTest(
+ prop1 = "prop2",
+ time = 456.0,
+ ),
+ )
+ batch.commit()
+
+ assertEquals("prop1", doc1.get().data(FirestoreTest.serializer()).prop1)
+ assertEquals("prop2", doc2.get().data(FirestoreTest.serializer()).prop1)
+ }
+
+ @Test
+ fun testSetBatchDoesNotEncodeEmptyValues() = testBatch { doc1, doc2 ->
+ val batch = firestore.batch()
+ batch.set(
+ documentRef = doc1,
+ strategy = FirestoreTest.serializer(),
+ data = FirestoreTest(
+ prop1 = "prop1-set",
+ time = 125.0,
+ ),
+ )
+ batch.set(
+ documentRef = doc2,
+ strategy = FirestoreTest.serializer(),
+ data = FirestoreTest(
+ prop1 = "prop2-set",
+ time = 250.0,
+ ),
+ )
+ batch.commit()
+
+ assertEquals(125.0, doc1.get().get("time") as Double?)
+ assertEquals("prop1-set", doc1.get().data(FirestoreTest.serializer()).prop1)
+ assertEquals(250.0, doc2.get().get("time") as Double?)
+ assertEquals("prop2-set", doc2.get().data(FirestoreTest.serializer()).prop1)
+ }
+
+ @Test
+ fun testUpdateBatch() = testBatch { doc1, doc2 ->
+ doc1.set(
+ FirestoreTest(
+ prop1 = "prop1",
+ time = 123.0,
+ ),
+ )
+ doc2.set(
+ FirestoreTest(
+ prop1 = "prop2",
+ time = 456.0,
+ ),
+ )
+
+ val batch = firestore.batch()
+ batch.update(
+ documentRef = doc1,
+ strategy = FirestoreTest.serializer(),
+ data = FirestoreTest(
+ prop1 = "prop1-updated",
+ time = 345.0,
+ ),
+ ) {
+ encodeDefaults = false
+ }
+ batch.update(
+ documentRef = doc2,
+ strategy = FirestoreTest.serializer(),
+ data = FirestoreTest(
+ prop1 = "prop2-updated",
+ time = 567.0,
+ ),
+ ) {
+ encodeDefaults = false
+ }
+ batch.commit()
+
+ assertEquals("prop1-updated", doc1.get().data(FirestoreTest.serializer()).prop1)
+ assertEquals("prop2-updated", doc2.get().data(FirestoreTest.serializer()).prop1)
+ }
+
+ @Test
+ fun testUpdateBatchDoesNotEncodeEmptyValues() = testBatch { doc1, doc2 ->
+ doc1.set(
+ FirestoreTest(
+ prop1 = "prop1",
+ time = 123.0,
+ ),
+ )
+ doc2.set(
+ FirestoreTest(
+ prop1 = "prop2",
+ time = 456.0,
+ ),
+ )
+ val batch = firestore.batch()
+ batch.update(
+ documentRef = doc1,
+ strategy = FirestoreTest.serializer(),
+ data = FirestoreTest(
+ prop1 = "prop1-set",
+ time = 126.0,
+ ),
+ ) {
+ encodeDefaults = false
+ }
+ batch.update(
+ documentRef = doc2,
+ strategy = FirestoreTest.serializer(),
+ data = FirestoreTest(
+ prop1 = "prop2-set",
+ time = 457.0,
+ ),
+ ) {
+ encodeDefaults = false
+ }
+ batch.commit()
+
+ assertEquals(126.0, doc1.get().get("time") as Double?)
+ assertEquals("prop1-set", doc1.get().data(FirestoreTest.serializer()).prop1)
+ assertEquals(457.0, doc2.get().get("time") as Double?)
+ assertEquals("prop2-set", doc2.get().data(FirestoreTest.serializer()).prop1)
+ }
+
+ @Test
+ fun testUpdateFieldValuesBatch() = testBatch { doc1, doc2 ->
+ doc1.set(
+ FirestoreTest(
+ prop1 = "prop1",
+ time = 123.0,
+ duration = 800.milliseconds,
+ ),
+ )
+
+ doc2.set(
+ FirestoreTest(
+ prop1 = "prop2",
+ time = 456.0,
+ duration = 700.milliseconds,
+ ),
+ )
+
+ val batch = firestore.batch()
+ batch.update(doc1) {
+ FirestoreTest::prop1.name to "prop1-updated"
+ FieldPath(FirestoreTest::optional.name) to "notNull"
+ FirestoreTest::duration.name.to(DurationAsIntSerializer(), 300.milliseconds)
+ FieldPath(FirestoreTest::nested.name).to(NestedObject.serializer(), NestedObject("nested"))
+ }
+ batch.update(doc2) {
+ FirestoreTest::prop1.name to "prop2-updated"
+ FieldPath(FirestoreTest::optional.name) to "alsoNotNull"
+ FirestoreTest::duration.name.to(DurationAsIntSerializer(), 200.milliseconds)
+ FieldPath(FirestoreTest::nested.name).to(NestedObject.serializer(), NestedObject("alsoNested"))
+ }
+ batch.commit()
+
+ val updatedDoc1 = doc1.get().data(FirestoreTest.serializer())
+ assertEquals("prop1-updated", updatedDoc1.prop1)
+ assertEquals("notNull", updatedDoc1.optional)
+ assertEquals(300.milliseconds, updatedDoc1.duration)
+ assertEquals(NestedObject("nested"), updatedDoc1.nested)
+
+ val updatedDoc2 = doc2.get().data(FirestoreTest.serializer())
+ assertEquals("prop2-updated", updatedDoc2.prop1)
+ assertEquals("alsoNotNull", updatedDoc2.optional)
+ assertEquals(200.milliseconds, updatedDoc2.duration)
+ assertEquals(NestedObject("alsoNested"), updatedDoc2.nested)
+ }
+
+ private fun testBatch(block: suspend (DocumentReference, DocumentReference) -> Unit) = runTest {
+ val doc1 = collection
+ .document("test1")
+ val doc2 = collection
+ .document("test2")
+
+ try {
+ block(doc1, doc2)
+ } finally {
+ doc1.delete()
+ doc2.delete()
+ }
+ }
+}
diff --git a/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt
index 50b90c44c..7f79a7ebc 100644
--- a/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt
+++ b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt
@@ -8,31 +8,19 @@ import dev.gitlive.firebase.Firebase
import dev.gitlive.firebase.FirebaseApp
import dev.gitlive.firebase.FirebaseOptions
import dev.gitlive.firebase.apps
-import dev.gitlive.firebase.internal.decode
import dev.gitlive.firebase.initialize
import dev.gitlive.firebase.runBlockingTest
import dev.gitlive.firebase.runTest
-import dev.gitlive.firebase.withSerializer
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.async
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.filter
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.withContext
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
-import kotlinx.serialization.builtins.ListSerializer
-import kotlinx.serialization.builtins.nullable
-import kotlinx.serialization.builtins.serializer
-import kotlin.random.Random
+import kotlinx.serialization.descriptors.PrimitiveKind
+import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
+import kotlinx.serialization.descriptors.SerialDescriptor
+import kotlinx.serialization.encoding.Decoder
+import kotlinx.serialization.encoding.Encoder
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.test.assertNotEquals
-import kotlin.test.assertNotNull
-import kotlin.test.assertNull
-import kotlin.test.assertTrue
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
@@ -46,7 +34,7 @@ expect fun encodedAsMap(encoded: Any?): Map
expect fun Map.asEncoded(): Any
@IgnoreForAndroidUnitTest
-class FirebaseFirestoreTest {
+abstract class BaseFirebaseFirestoreTest {
@Serializable
data class FirestoreTest(
@@ -55,35 +43,27 @@ class FirebaseFirestoreTest {
val count: Int = 0,
val list: List = emptyList(),
val optional: String? = null,
+ val nested: NestedObject? = null,
+ val nestedList: List = emptyList(),
+ @Serializable(with = DurationAsIntSerializer::class)
+ val duration: Duration = Duration.ZERO,
)
@Serializable
- data class FirestoreTimeTest(
- val prop1: String,
- val time: BaseTimestamp?,
+ data class NestedObject(
+ val prop2: String,
)
- companion object {
- val testOne = FirestoreTest(
- "aaa",
- 0.0,
- 1,
- listOf("a", "aa", "aaa"),
- "notNull",
- )
- val testTwo = FirestoreTest(
- "bbb",
- 0.0,
- 2,
- listOf("b", "bb", "ccc"),
- )
- val testThree = FirestoreTest(
- "ccc",
- 1.0,
- 3,
- listOf("c", "cc", "ccc"),
- "notNull",
- )
+ // Long would be better but JS does not seem to support it on the Firebase level https://stackoverflow.com/questions/31930406/storing-long-type-in-firebase
+ class DurationAsIntSerializer : KSerializer {
+
+ override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("millisecondsSinceEpoch", PrimitiveKind.INT)
+
+ override fun serialize(encoder: Encoder, value: Duration) {
+ encoder.encodeInt(value.inWholeMilliseconds.toInt())
+ }
+
+ override fun deserialize(decoder: Decoder): Duration = decoder.decodeInt().milliseconds
}
lateinit var firebaseApp: FirebaseApp
@@ -120,951 +100,14 @@ class FirebaseFirestoreTest {
it.delete()
}
}
+}
- @Test
- fun testStringOrderBy() = runTest {
- setupFirestoreData()
- val resultDocs = firestore
- .collection("testFirestoreQuerying")
- .orderBy("prop1")
- .get()
- .documents
- assertEquals(3, resultDocs.size)
- assertEquals("aaa", resultDocs[0].get("prop1"))
- assertEquals("bbb", resultDocs[1].get("prop1"))
- assertEquals("ccc", resultDocs[2].get("prop1"))
- }
-
- @Test
- fun testFieldOrderBy() = runTest {
- setupFirestoreData()
-
- val resultDocs = firestore.collection("testFirestoreQuerying")
- .orderBy(FieldPath("prop1")).get().documents
- assertEquals(3, resultDocs.size)
- assertEquals("aaa", resultDocs[0].get("prop1"))
- assertEquals("bbb", resultDocs[1].get("prop1"))
- assertEquals("ccc", resultDocs[2].get("prop1"))
- }
-
- @Test
- fun testStringOrderByAscending() = runTest {
- setupFirestoreData()
-
- val resultDocs = firestore.collection("testFirestoreQuerying")
- .orderBy("prop1", Direction.ASCENDING).get().documents
- assertEquals(3, resultDocs.size)
- assertEquals("aaa", resultDocs[0].get("prop1"))
- assertEquals("bbb", resultDocs[1].get("prop1"))
- assertEquals("ccc", resultDocs[2].get("prop1"))
- }
-
- @Test
- fun testFieldOrderByAscending() = runTest {
- setupFirestoreData()
-
- val resultDocs = firestore.collection("testFirestoreQuerying")
- .orderBy(FieldPath("prop1"), Direction.ASCENDING).get().documents
- assertEquals(3, resultDocs.size)
- assertEquals("aaa", resultDocs[0].get("prop1"))
- assertEquals("bbb", resultDocs[1].get("prop1"))
- assertEquals("ccc", resultDocs[2].get("prop1"))
- }
-
- @Test
- fun testStringOrderByDescending() = runTest {
- setupFirestoreData()
-
- val resultDocs = firestore.collection("testFirestoreQuerying")
- .orderBy("prop1", Direction.DESCENDING).get().documents
- assertEquals(3, resultDocs.size)
- assertEquals("ccc", resultDocs[0].get("prop1"))
- assertEquals("bbb", resultDocs[1].get("prop1"))
- assertEquals("aaa", resultDocs[2].get("prop1"))
- }
-
- @Test
- fun testFieldOrderByDescending() = runTest {
- setupFirestoreData()
-
- val resultDocs = firestore.collection("testFirestoreQuerying")
- .orderBy(FieldPath("prop1"), Direction.DESCENDING).get().documents
- assertEquals(3, resultDocs.size)
- assertEquals("ccc", resultDocs[0].get("prop1"))
- assertEquals("bbb", resultDocs[1].get("prop1"))
- assertEquals("aaa", resultDocs[2].get("prop1"))
- }
-
- @Test
- fun testServerTimestampFieldValue() = runTest {
- val doc = firestore
- .collection("testServerTimestampFieldValue")
- .document("test")
- doc.set(
- FirestoreTimeTest.serializer(),
- FirestoreTimeTest("ServerTimestamp", Timestamp(123, 0)),
- )
- assertEquals(Timestamp(123, 0), doc.get().get("time", TimestampSerializer))
-
- doc.set(FirestoreTimeTest.serializer(), FirestoreTimeTest("ServerTimestamp", Timestamp.ServerTimestamp))
-
- assertNotEquals(Timestamp.ServerTimestamp, doc.get().get("time", BaseTimestamp.serializer()))
- assertNotEquals(Timestamp.ServerTimestamp, doc.get().data(FirestoreTimeTest.serializer()).time)
- }
-
- @Test
- fun testServerTimestampBehaviorNone() = runTest {
- val doc = firestore
- .collection("testServerTimestampBehaviorNone")
- .document("test${Random.nextInt()}")
-
- val deferredPendingWritesSnapshot = async {
- doc.snapshots.filter { it.exists }.first()
- }
- nonSkippedDelay(100.milliseconds) // makes possible to catch pending writes snapshot
-
- doc.set(
- FirestoreTimeTest.serializer(),
- FirestoreTimeTest("ServerTimestampBehavior", Timestamp.ServerTimestamp),
- )
-
- val pendingWritesSnapshot = deferredPendingWritesSnapshot.await()
- assertTrue(pendingWritesSnapshot.metadata.hasPendingWrites)
- assertNull(pendingWritesSnapshot.get("time", BaseTimestamp.serializer().nullable, serverTimestampBehavior = ServerTimestampBehavior.NONE))
- }
-
- @Test
- fun testSetBatch() = runTest {
- val doc = firestore
- .collection("testServerTestSetBatch")
- .document("test")
- val batch = firestore.batch()
- batch.set(
- documentRef = doc,
- strategy = FirestoreTest.serializer(),
- data = FirestoreTest(
- prop1 = "prop1",
- time = 123.0,
- ),
- )
- batch.commit()
-
- assertEquals("prop1", doc.get().data(FirestoreTest.serializer()).prop1)
- }
-
- @Test
- fun testServerTimestampBehaviorEstimate() = runTest {
- val doc = firestore
- .collection("testServerTimestampBehaviorEstimate")
- .document("test${Random.nextInt()}")
-
- val deferredPendingWritesSnapshot = async {
- doc.snapshots.filter { it.exists }.first()
- }
- nonSkippedDelay(100.milliseconds) // makes possible to catch pending writes snapshot
-
- doc.set(FirestoreTimeTest.serializer(), FirestoreTimeTest("ServerTimestampBehavior", Timestamp.ServerTimestamp))
-
- val pendingWritesSnapshot = deferredPendingWritesSnapshot.await()
- assertTrue(pendingWritesSnapshot.metadata.hasPendingWrites)
- assertNotNull(pendingWritesSnapshot.get("time", ServerTimestampBehavior.ESTIMATE))
- assertNotEquals(Timestamp.ServerTimestamp, pendingWritesSnapshot.data(FirestoreTimeTest.serializer(), serverTimestampBehavior = ServerTimestampBehavior.ESTIMATE).time)
- }
-
- @Test
- fun testServerTimestampBehaviorPrevious() = runTest {
- val doc = firestore
- .collection("testServerTimestampBehaviorPrevious")
- .document("test${Random.nextInt()}")
-
- val deferredPendingWritesSnapshot = async {
- doc.snapshots.filter { it.exists }.first()
- }
- nonSkippedDelay(100.milliseconds) // makes possible to catch pending writes snapshot
-
- doc.set(FirestoreTimeTest.serializer(), FirestoreTimeTest("ServerTimestampBehavior", Timestamp.ServerTimestamp))
-
- val pendingWritesSnapshot = deferredPendingWritesSnapshot.await()
- assertTrue(pendingWritesSnapshot.metadata.hasPendingWrites)
- assertNull(pendingWritesSnapshot.get("time", BaseTimestamp.serializer().nullable, serverTimestampBehavior = ServerTimestampBehavior.PREVIOUS))
- }
-
- @Test
- fun testDocumentAutoId() = runTest {
- val doc = firestore
- .collection("testDocumentAutoId")
- .document
-
- doc.set(FirestoreTest.serializer(), FirestoreTest("AutoId"))
-
- val resultDoc = firestore
- .collection("testDocumentAutoId")
- .document(doc.id)
- .get()
-
- assertEquals(true, resultDoc.exists)
- assertEquals("AutoId", resultDoc.get("prop1"))
- }
-
- @Test
- fun testStartAfterDocumentSnapshot() = runTest {
- setupFirestoreData()
- val query = firestore
- .collection("testFirestoreQuerying")
- .orderBy("prop1", Direction.ASCENDING)
-
- val firstPage = query.limit(2).get().documents // First 2 results
- assertEquals(2, firstPage.size)
- assertEquals("aaa", firstPage[0].get("prop1"))
- assertEquals("bbb", firstPage[1].get("prop1"))
-
- val lastDocumentSnapshot = firstPage.lastOrNull()
- assertNotNull(lastDocumentSnapshot)
-
- val secondPage = query.startAfter(lastDocumentSnapshot).get().documents
- assertEquals(1, secondPage.size)
- assertEquals("ccc", secondPage[0].get("prop1"))
- }
-
- @Test
- fun testStartAfterFieldValues() = runTest {
- setupFirestoreData()
- val query = firestore
- .collection("testFirestoreQuerying")
- .orderBy("prop1", Direction.ASCENDING)
-
- val firstPage = query.get().documents
- assertEquals(3, firstPage.size)
- assertEquals("aaa", firstPage[0].get("prop1"))
- assertEquals("bbb", firstPage[1].get("prop1"))
- assertEquals("ccc", firstPage[2].get("prop1"))
-
- val secondPage = query.startAfter("bbb").get().documents
- assertEquals(1, secondPage.size)
- assertEquals("ccc", secondPage[0].get("prop1"))
- }
-
- @Test
- fun testStartAtDocumentSnapshot() = runTest {
- setupFirestoreData()
- val query = firestore
- .collection("testFirestoreQuerying")
- .orderBy("prop1", Direction.ASCENDING)
-
- val firstPage = query.limit(2).get().documents // First 2 results
- assertEquals(2, firstPage.size)
- assertEquals("aaa", firstPage[0].get("prop1"))
- assertEquals("bbb", firstPage[1].get("prop1"))
-
- val lastDocumentSnapshot = firstPage.lastOrNull()
- assertNotNull(lastDocumentSnapshot)
-
- val secondPage = query.startAt(lastDocumentSnapshot).get().documents
- assertEquals(2, secondPage.size)
- assertEquals("bbb", secondPage[0].get("prop1"))
- assertEquals("ccc", secondPage[1].get("prop1"))
- }
-
- @Test
- fun testStartAtFieldValues() = runTest {
- setupFirestoreData()
- val query = firestore
- .collection("testFirestoreQuerying")
- .orderBy("prop1", Direction.ASCENDING)
-
- val firstPage = query.get().documents // First 2 results
- assertEquals(3, firstPage.size)
- assertEquals("aaa", firstPage[0].get("prop1"))
- assertEquals("bbb", firstPage[1].get("prop1"))
- assertEquals("ccc", firstPage[2].get("prop1"))
-
- val secondPage = query.startAt("bbb").get().documents
- assertEquals(2, secondPage.size)
- assertEquals("bbb", secondPage[0].get("prop1"))
- assertEquals("ccc", secondPage[1].get("prop1"))
- }
-
- @Test
- fun testEndBeforeDocumentSnapshot() = runTest {
- setupFirestoreData()
- val query = firestore
- .collection("testFirestoreQuerying")
- .orderBy("prop1", Direction.ASCENDING)
-
- val firstPage = query.limit(2).get().documents // First 2 results
- assertEquals(2, firstPage.size)
- assertEquals("aaa", firstPage[0].get("prop1"))
- assertEquals("bbb", firstPage[1].get("prop1"))
-
- val lastDocumentSnapshot = firstPage.lastOrNull()
- assertNotNull(lastDocumentSnapshot)
-
- val secondPage = query.endBefore(lastDocumentSnapshot).get().documents
- assertEquals(1, secondPage.size)
- assertEquals("aaa", secondPage[0].get("prop1"))
- }
-
- @Test
- fun testEndBeforeFieldValues() = runTest {
- setupFirestoreData()
- val query = firestore
- .collection("testFirestoreQuerying")
- .orderBy("prop1", Direction.ASCENDING)
-
- val firstPage = query.get().documents
- assertEquals(3, firstPage.size)
- assertEquals("aaa", firstPage[0].get("prop1"))
- assertEquals("bbb", firstPage[1].get("prop1"))
- assertEquals("ccc", firstPage[2].get("prop1"))
-
- val secondPage = query.endBefore("bbb").get().documents
- assertEquals(1, secondPage.size)
- assertEquals("aaa", secondPage[0].get("prop1"))
- }
-
- @Test
- fun testEndAtDocumentSnapshot() = runTest {
- setupFirestoreData()
- val query = firestore
- .collection("testFirestoreQuerying")
- .orderBy("prop1", Direction.ASCENDING)
-
- val firstPage = query.limit(2).get().documents // First 2 results
- assertEquals(2, firstPage.size)
- assertEquals("aaa", firstPage[0].get("prop1"))
- assertEquals("bbb", firstPage[1].get("prop1"))
-
- val lastDocumentSnapshot = firstPage.lastOrNull()
- assertNotNull(lastDocumentSnapshot)
-
- val secondPage = query.endAt(lastDocumentSnapshot).get().documents
- assertEquals(2, secondPage.size)
- assertEquals("aaa", secondPage[0].get("prop1"))
- assertEquals("bbb", secondPage[1].get("prop1"))
- }
-
- @Test
- fun testEndAtFieldValues() = runTest {
- setupFirestoreData()
- val query = firestore
- .collection("testFirestoreQuerying")
- .orderBy("prop1", Direction.ASCENDING)
-
- val firstPage = query.get().documents // First 2 results
- assertEquals(3, firstPage.size)
- assertEquals("aaa", firstPage[0].get("prop1"))
- assertEquals("bbb", firstPage[1].get("prop1"))
- assertEquals("ccc", firstPage[2].get("prop1"))
-
- val secondPage = query.endAt("bbb").get().documents
- assertEquals(2, secondPage.size)
- assertEquals("aaa", secondPage[0].get("prop1"))
- assertEquals("bbb", secondPage[1].get("prop1"))
- }
-
- @Test
- fun testIncrementFieldValue() = runTest {
- val doc = firestore
- .collection("testFirestoreIncrementFieldValue")
- .document("test1")
-
- doc.set(FirestoreTest.serializer(), FirestoreTest("increment1", count = 0))
- val dataBefore = doc.get().data(FirestoreTest.serializer())
- assertEquals(0, dataBefore.count)
-
- doc.update("count" to FieldValue.increment(5))
- val dataAfter = doc.get().data(FirestoreTest.serializer())
- assertEquals(5, dataAfter.count)
- }
-
- @Test
- fun testArrayUnion() = runTest {
- val doc = firestore
- .collection("testFirestoreArrayUnion")
- .document("test1")
-
- doc.set(FirestoreTest.serializer(), FirestoreTest("increment1", list = listOf("first")))
- val dataBefore = doc.get().data(FirestoreTest.serializer())
- assertEquals(listOf("first"), dataBefore.list)
-
- doc.update("list" to FieldValue.arrayUnion("second"))
- val dataAfter = doc.get().data(FirestoreTest.serializer())
- assertEquals(listOf("first", "second"), dataAfter.list)
- }
-
- @Test
- fun testArrayRemove() = runTest {
- val doc = firestore
- .collection("testFirestoreArrayRemove")
- .document("test1")
-
- doc.set(FirestoreTest.serializer(), FirestoreTest("increment1", list = listOf("first", "second")))
- val dataBefore = doc.get().data(FirestoreTest.serializer())
- assertEquals(listOf("first", "second"), dataBefore.list)
-
- doc.update("list" to FieldValue.arrayRemove("second"))
- val dataAfter = doc.get().data(FirestoreTest.serializer())
- assertEquals(listOf("first"), dataAfter.list)
- }
-
- @Test
- fun testSetBatchDoesNotEncodeEmptyValues() = runTest {
- val doc = firestore
- .collection("testServerTestSetBatch")
- .document("test")
- val batch = firestore.batch()
- batch.set(
- documentRef = doc,
- strategy = FirestoreTest.serializer(),
- data = FirestoreTest(
- prop1 = "prop1-set",
- time = 125.0,
- ),
- )
- batch.commit()
-
- assertEquals(125.0, doc.get().get("time") as Double?)
- assertEquals("prop1-set", doc.get().data(FirestoreTest.serializer()).prop1)
- }
-
- @Test
- fun testUpdateBatch() = runTest {
- val doc = firestore
- .collection("testServerTestSetBatch")
- .document("test").apply {
- set(
- FirestoreTest(
- prop1 = "prop1",
- time = 123.0,
- ),
- )
- }
-
- val batch = firestore.batch()
- batch.update(
- documentRef = doc,
- strategy = FirestoreTest.serializer(),
- data = FirestoreTest(
- prop1 = "prop1-updated",
- time = 123.0,
- ),
- ) {
- encodeDefaults = false
- }
- batch.commit()
-
- assertEquals("prop1-updated", doc.get().data(FirestoreTest.serializer()).prop1)
- }
-
- @Test
- fun testUpdateBatchDoesNotEncodeEmptyValues() = runTest {
- val doc = firestore
- .collection("testServerTestSetBatch")
- .document("test").apply {
- set(
- FirestoreTest(
- prop1 = "prop1",
- time = 123.0,
- ),
- )
- }
- val batch = firestore.batch()
- batch.update(
- documentRef = doc,
- strategy = FirestoreTest.serializer(),
- data = FirestoreTest(
- prop1 = "prop1-set",
- time = 126.0,
- ),
- ) {
- encodeDefaults = false
- }
- batch.commit()
-
- assertEquals(126.0, doc.get().get("time") as Double?)
- assertEquals("prop1-set", doc.get().data(FirestoreTest.serializer()).prop1)
- }
-
- @Test
- fun testLegacyDoubleTimestamp() = runTest {
- @Serializable
- data class DoubleTimestamp(
- @Serializable(with = DoubleAsTimestampSerializer::class)
- val time: Double?,
- )
-
- val doc = firestore
- .collection("testLegacyDoubleTimestamp")
- .document("test${Random.nextInt()}")
-
- val deferredPendingWritesSnapshot = async {
- doc.snapshots.filter { it.exists }.first()
- }
- nonSkippedDelay(100.milliseconds) // makes possible to catch pending writes snapshot
-
- doc.set(DoubleTimestamp.serializer(), DoubleTimestamp(DoubleAsTimestampSerializer.SERVER_TIMESTAMP))
-
- val pendingWritesSnapshot = deferredPendingWritesSnapshot.await()
- assertTrue(pendingWritesSnapshot.metadata.hasPendingWrites)
- assertNotNull(pendingWritesSnapshot.get("time", DoubleAsTimestampSerializer, serverTimestampBehavior = ServerTimestampBehavior.ESTIMATE))
- assertNotEquals(DoubleAsTimestampSerializer.SERVER_TIMESTAMP, pendingWritesSnapshot.data(DoubleTimestamp.serializer(), serverTimestampBehavior = ServerTimestampBehavior.ESTIMATE).time)
- }
-
- @Test
- fun testLegacyDoubleTimestampWriteNewFormatRead() = runTest {
- @Serializable
- data class LegacyDocument(
- @Serializable(with = DoubleAsTimestampSerializer::class)
- val time: Double,
- )
-
- @Serializable
- data class NewDocument(
- val time: Timestamp,
- )
-
- val doc = firestore
- .collection("testLegacyDoubleTimestampEncodeDecode")
- .document("testLegacy")
-
- val ms = 12345678.0
-
- doc.set(LegacyDocument.serializer(), LegacyDocument(time = ms))
-
- val fetched: NewDocument = doc.get().data(NewDocument.serializer())
- assertEquals(ms, fetched.time.toMilliseconds())
- }
-
- @Test
- fun testQueryByTimestamp() = runTest {
- @Serializable
- data class DocumentWithTimestamp(
- val time: Timestamp,
- )
-
- val collection = firestore
- .collection("testQueryByTimestamp")
-
- val timestamp = Timestamp.fromMilliseconds(1693262549000.0)
-
- val pastTimestamp = Timestamp(timestamp.seconds - 60, 12345000) // note: iOS truncates 3 last digits of nanoseconds due to internal conversions
- val futureTimestamp = Timestamp(timestamp.seconds + 60, 78910000)
-
- collection.add(DocumentWithTimestamp.serializer(), DocumentWithTimestamp(pastTimestamp))
- collection.add(DocumentWithTimestamp.serializer(), DocumentWithTimestamp(futureTimestamp))
-
- val equalityQueryResult = collection.where {
- FieldPath(DocumentWithTimestamp::time.name) equalTo pastTimestamp
- }.get().documents.map { it.data(DocumentWithTimestamp.serializer()) }.toSet()
-
- assertEquals(setOf(DocumentWithTimestamp(pastTimestamp)), equalityQueryResult)
-
- val gtQueryResult = collection.where {
- FieldPath(DocumentWithTimestamp::time.name) greaterThan timestamp
- }.get().documents.map { it.data(DocumentWithTimestamp.serializer()) }.toSet()
-
- assertEquals(setOf(DocumentWithTimestamp(futureTimestamp)), gtQueryResult)
- }
-
- @Test
- fun testGeoPointSerialization() = runTest {
- @Serializable
- data class DataWithGeoPoint(val geoPoint: GeoPoint)
-
- fun getDocument() = firestore.collection("geoPointSerialization")
- .document("geoPointSerialization")
-
- val data = DataWithGeoPoint(GeoPoint(12.34, 56.78))
- // store geo point
- getDocument().set(DataWithGeoPoint.serializer(), data)
- // restore data
- val savedData = getDocument().get().data(DataWithGeoPoint.serializer())
- assertEquals(data.geoPoint, savedData.geoPoint)
-
- // update data
- val updatedData = DataWithGeoPoint(GeoPoint(87.65, 43.21))
- getDocument().update(FieldPath(DataWithGeoPoint::geoPoint.name) to updatedData.geoPoint)
- // verify update
- val updatedSavedData = getDocument().get().data(DataWithGeoPoint.serializer())
- assertEquals(updatedData.geoPoint, updatedSavedData.geoPoint)
- }
-
- @Test
- fun testDocumentReferenceSerialization() = runTest {
- @Serializable
- data class DataWithDocumentReference(
- val documentReference: DocumentReference,
- )
-
- fun getCollection() = firestore.collection("documentReferenceSerialization")
- fun getDocument() = getCollection()
- .document("documentReferenceSerialization")
- val documentRef1 = getCollection().document("refDoc1").apply {
- set(mapOf("value" to 1))
- }
- val documentRef2 = getCollection().document("refDoc2").apply {
- set(mapOf("value" to 2))
- }
-
- val data = DataWithDocumentReference(documentRef1)
- // store reference
- getDocument().set(DataWithDocumentReference.serializer(), data)
- // restore data
- val savedData = getDocument().get().data(DataWithDocumentReference.serializer())
- assertEquals(data.documentReference.path, savedData.documentReference.path)
-
- // update data
- val updatedData = DataWithDocumentReference(documentRef2)
- getDocument().update(
- FieldPath(DataWithDocumentReference::documentReference.name) to updatedData.documentReference.withSerializer(DocumentReferenceSerializer),
- )
- // verify update
- val updatedSavedData = getDocument().get().data(DataWithDocumentReference.serializer())
- assertEquals(updatedData.documentReference.path, updatedSavedData.documentReference.path)
- }
-
- @Serializable
- data class TestDataWithDocumentReference(
- val uid: String,
- val reference: DocumentReference,
- val optionalReference: DocumentReference?,
- )
-
- @Serializable
- data class TestDataWithOptionalDocumentReference(
- val optionalReference: DocumentReference?,
- )
-
- @Test
- fun encodeDocumentReference() = runTest {
- val doc = firestore.document("a/b")
- val item = TestDataWithDocumentReference("123", doc, doc)
- val encoded = encodedAsMap(
- encode(item) {
- encodeDefaults = false
- },
- )
- assertEquals("123", encoded["uid"])
- assertEquals(doc.nativeValue, encoded["reference"])
- assertEquals(doc.nativeValue, encoded["optionalReference"])
- }
-
- @Test
- fun encodeNullDocumentReference() = runTest {
- val item = TestDataWithOptionalDocumentReference(null)
- val encoded = encodedAsMap(
- encode(item) {
- encodeDefaults = false
- },
- )
- assertNull(encoded["optionalReference"])
- }
-
- @Test
- fun decodeDocumentReference() = runTest {
- val doc = firestore.document("a/b")
- val obj = mapOf(
- "uid" to "123",
- "reference" to doc.nativeValue,
- "optionalReference" to doc.nativeValue,
- ).asEncoded()
- val decoded: TestDataWithDocumentReference = decode(obj)
- assertEquals("123", decoded.uid)
- assertEquals(doc.path, decoded.reference.path)
- assertEquals(doc.path, decoded.optionalReference?.path)
- }
-
- @Test
- fun decodeNullDocumentReference() = runTest {
- val obj = mapOf("optionalReference" to null).asEncoded()
- val decoded: TestDataWithOptionalDocumentReference = decode(obj)
- assertNull(decoded.optionalReference?.path)
- }
-
- @Test
- fun testFieldValuesOps() = runTest {
- @Serializable
- data class TestData(val values: List)
- fun getDocument() = firestore.collection("fieldValuesOps")
- .document("fieldValuesOps")
-
- val data = TestData(listOf(1))
- // store
- getDocument().set(TestData.serializer(), data)
- // append & verify
- getDocument().update(FieldPath(TestData::values.name) to FieldValue.arrayUnion(2))
-
- var savedData = getDocument().get().data(TestData.serializer())
- assertEquals(listOf(1, 2), savedData.values)
-
- // remove & verify
- getDocument().update(FieldPath(TestData::values.name) to FieldValue.arrayRemove(1))
- savedData = getDocument().get().data(TestData.serializer())
- assertEquals(listOf(2), savedData.values)
-
- val list = getDocument().get().get(TestData::values.name, ListSerializer(Int.serializer()).nullable)
- assertEquals(listOf(2), list)
- // delete & verify
- getDocument().update(FieldPath(TestData::values.name) to FieldValue.delete)
- val deletedList = getDocument().get().get(TestData::values.name, ListSerializer(Int.serializer()).nullable)
- assertNull(deletedList)
- }
-
- @Test
- fun testQueryEqualTo() = runTest {
- setupFirestoreData()
-
- val fieldQuery = firestore
- .collection("testFirestoreQuerying")
- .where { "prop1" equalTo testOne.prop1 }
-
- fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
-
- val pathQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::prop1.name) equalTo testTwo.prop1 }
-
- pathQuery.assertDocuments(FirestoreTest.serializer(), testTwo)
-
- val nullableQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::optional.name) equalTo null }
-
- nullableQuery.assertDocuments(FirestoreTest.serializer(), testTwo)
- }
-
- @Test
- fun testQueryNotEqualTo() = runTest {
- setupFirestoreData()
-
- val fieldQuery = firestore
- .collection("testFirestoreQuerying")
- .where { "prop1" notEqualTo testOne.prop1 }
-
- fieldQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
-
- val pathQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::prop1.name) notEqualTo testTwo.prop1 }
-
- pathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testThree)
-
- val nullableQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::optional.name) notEqualTo null }
-
- nullableQuery.assertDocuments(FirestoreTest.serializer(), testOne, testThree)
- }
-
- @Test
- fun testQueryLessThan() = runTest {
- setupFirestoreData()
-
- val fieldQuery = firestore
- .collection("testFirestoreQuerying")
- .where { "count" lessThan testThree.count }
-
- fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
-
- val pathQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::count.name) lessThan testTwo.count }
-
- pathQuery.assertDocuments(FirestoreTest.serializer(), testOne)
- }
-
- @Test
- fun testQueryGreaterThan() = runTest {
- setupFirestoreData()
-
- val fieldQuery = firestore
- .collection("testFirestoreQuerying")
- .where { "count" greaterThan testOne.count }
-
- fieldQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
-
- val pathQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::count.name) greaterThan testTwo.count }
-
- pathQuery.assertDocuments(FirestoreTest.serializer(), testThree)
- }
-
- @Test
- fun testQueryLessThanOrEqualTo() = runTest {
- setupFirestoreData()
-
- val fieldQuery = firestore
- .collection("testFirestoreQuerying")
- .where { "count" lessThanOrEqualTo testOne.count }
-
- fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
-
- val pathQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::count.name) lessThanOrEqualTo testTwo.count }
-
- pathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
- }
-
- @Test
- fun testQueryGreaterThanOrEqualTo() = runTest {
- setupFirestoreData()
-
- val fieldQuery = firestore
- .collection("testFirestoreQuerying")
- .where { "count" greaterThanOrEqualTo testThree.count }
-
- fieldQuery.assertDocuments(FirestoreTest.serializer(), testThree)
-
- val pathQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::count.name) greaterThanOrEqualTo testTwo.count }
-
- pathQuery.assertDocuments(FirestoreTest.serializer(), testTwo, testThree)
- }
-
- @Test
- fun testQueryArrayContains() = runTest {
- setupFirestoreData()
-
- val fieldQuery = firestore
- .collection("testFirestoreQuerying")
- .where { "list" contains "a" }
-
- fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
-
- val pathQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::list.name) contains "ccc" }
-
- pathQuery.assertDocuments(FirestoreTest.serializer(), testThree, testTwo)
- }
-
- @Test
- fun testQueryArrayContainsAny() = runTest {
- setupFirestoreData()
-
- val fieldQuery = firestore
- .collection("testFirestoreQuerying")
- .where { "list" containsAny listOf("a", "b") }
-
- fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
-
- val pathQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::list.name) containsAny listOf("c", "d") }
-
- pathQuery.assertDocuments(FirestoreTest.serializer(), testThree)
- }
-
- @Test
- fun testQueryInArray() = runTest {
- setupFirestoreData()
-
- val fieldQuery = firestore
- .collection("testFirestoreQuerying")
- .where { "prop1" inArray listOf("aaa", "bbb") }
-
- fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
-
- val pathQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::prop1.name) inArray listOf("ccc", "ddd") }
-
- pathQuery.assertDocuments(FirestoreTest.serializer(), testThree)
- }
-
- @Test
- fun testQueryNotInArray() = runTest {
- setupFirestoreData()
-
- val fieldQuery = firestore
- .collection("testFirestoreQuerying")
- .where { "prop1" notInArray listOf("aaa", "bbb") }
-
- fieldQuery.assertDocuments(FirestoreTest.serializer(), testThree)
-
- val pathQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath(FirestoreTest::prop1.name) notInArray listOf("ccc", "ddd") }
-
- pathQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
- }
-
- @Test
- fun testCompoundQuery() = runTest {
- setupFirestoreData()
-
- val andQuery = firestore
- .collection("testFirestoreQuerying")
- .where {
- FieldPath(FirestoreTest::prop1.name) inArray listOf("aaa", "bbb") and (FieldPath(FirestoreTest::count.name) equalTo 1)
- }
- andQuery.assertDocuments(FirestoreTest.serializer(), testOne)
-
- val orQuery = firestore
- .collection("testFirestoreQuerying")
- .where {
- FieldPath(FirestoreTest::prop1.name) equalTo "aaa" or (FieldPath(FirestoreTest::count.name) equalTo 2)
- }
- orQuery.assertDocuments(FirestoreTest.serializer(), testOne, testTwo)
-
- val andOrQuery = firestore
- .collection("testFirestoreQuerying")
- .where {
- all(
- any(
- FieldPath(FirestoreTest::prop1.name) equalTo "aaa",
- FieldPath(FirestoreTest::count.name) equalTo 2,
- )!!,
- FieldPath(FirestoreTest::list.name) contains "a",
- )
- }
- andOrQuery.assertDocuments(FirestoreTest.serializer(), testOne)
- }
-
- @Test
- fun testQueryByDocumentId() = runTest {
- setupFirestoreData()
-
- val fieldQuery = firestore
- .collection("testFirestoreQuerying")
- .where { FieldPath.documentId equalTo "one" }
- fieldQuery.assertDocuments(FirestoreTest.serializer(), testOne)
- }
+@IgnoreForAndroidUnitTest
+class FirebaseFirestoreTest : BaseFirebaseFirestoreTest() {
@Test
fun testMultiple() = runTest {
Firebase.firestore(firebaseApp).disableNetwork()
Firebase.firestore(firebaseApp).enableNetwork()
}
-
- private suspend fun setupFirestoreData(
- documentOne: FirestoreTest = testOne,
- documentTwo: FirestoreTest = testTwo,
- documentThree: FirestoreTest = testThree,
- ) {
- firestore.collection("testFirestoreQuerying")
- .document("one")
- .set(FirestoreTest.serializer(), documentOne)
- firestore.collection("testFirestoreQuerying")
- .document("two")
- .set(FirestoreTest.serializer(), documentTwo)
- firestore.collection("testFirestoreQuerying")
- .document("three")
- .set(FirestoreTest.serializer(), documentThree)
- }
-
- private suspend fun Query.assertDocuments(serializer: KSerializer, vararg expected: T) {
- val documents = get().documents
- assertEquals(expected.size, documents.size)
- documents.forEachIndexed { index, documentSnapshot ->
- assertEquals(expected[index], documentSnapshot.data(serializer))
- }
- }
-
- private suspend fun nonSkippedDelay(timeout: Duration) = withContext(Dispatchers.Default) {
- delay(timeout)
- }
}
diff --git a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt
index d0eb95602..8497833e8 100644
--- a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt
+++ b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt
@@ -1,6 +1,6 @@
package dev.gitlive.firebase.firestore
-import cocoapods.FirebaseFirestoreInternal.FIRTimestamp
+import cocoapods.FirebaseCore.FIRTimestamp
import kotlinx.serialization.Serializable
/** A class representing a platform specific Firebase Timestamp. */
diff --git a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt
index 98856556b..4f2c72d14 100644
--- a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt
+++ b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeDocumentReference.kt
@@ -1,10 +1,10 @@
package dev.gitlive.firebase.firestore.internal
-import dev.gitlive.firebase.firestore.EncodedFieldPath
import dev.gitlive.firebase.firestore.NativeDocumentReferenceType
import dev.gitlive.firebase.firestore.Source
import dev.gitlive.firebase.firestore.await
import dev.gitlive.firebase.firestore.awaitResult
+import dev.gitlive.firebase.firestore.toEncodedMap
import dev.gitlive.firebase.firestore.toException
import dev.gitlive.firebase.internal.EncodedObject
import dev.gitlive.firebase.internal.ios
@@ -55,14 +55,9 @@ internal actual class NativeDocumentReference actual constructor(actual val nati
ios.updateData(encodedData.ios, it)
}
- actual suspend fun updateEncodedFieldsAndValues(encodedFieldsAndValues: List>) =
+ actual suspend fun updateEncoded(encodedFieldsAndValues: List) =
await {
- ios.updateData(encodedFieldsAndValues.toMap(), it)
- }
-
- actual suspend fun updateEncodedFieldPathsAndValues(encodedFieldsAndValues: List