From 21d22641b5e504b1c4a1aed4a20589a7b08072e5 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Fri, 10 Jun 2022 18:20:51 +0300 Subject: [PATCH 01/28] Refactor app and database modules --- .../kotlin/dev/gitlive/firebase/firebase.kt | 29 ++- .../kotlin/dev/gitlive/firebase/externals.kt | 73 ------- .../dev/gitlive/firebase/externals/app.kt | 28 +++ .../gitlive/firebase/externals/database.kt | 129 ++++++++++++ .../kotlin/dev/gitlive/firebase/externals2.kt | 7 +- .../dev/gitlive/firebase/database/database.kt | 191 +++++++++++------- 6 files changed, 302 insertions(+), 155 deletions(-) create mode 100644 firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app.kt create mode 100644 firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database.kt diff --git a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt index 16214a1c4..946943042 100644 --- a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt +++ b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt @@ -4,33 +4,44 @@ package dev.gitlive.firebase +import dev.gitlive.firebase.externals.getApp +import dev.gitlive.firebase.externals.getApps +import dev.gitlive.firebase.externals.initializeApp import kotlin.js.json +import dev.gitlive.firebase.externals.FirebaseApp as JsFirebaseApp -actual val Firebase.app: FirebaseApp - get() = FirebaseApp(firebase.app()) +actual val Firebase.app: FirebaseApp get() = FirebaseApp(getApp()) -actual fun Firebase.app(name: String): FirebaseApp = - FirebaseApp(firebase.app(name)) +actual fun Firebase.app(name: String): FirebaseApp = FirebaseApp(getApp(name)) actual fun Firebase.initialize(context: Any?): FirebaseApp? = throw UnsupportedOperationException("Cannot initialize firebase without options in JS") actual fun Firebase.initialize(context: Any?, options: FirebaseOptions, name: String): FirebaseApp = - FirebaseApp(firebase.initializeApp(options.toJson(), name)) + FirebaseApp(initializeApp(options.toJson(), name)) actual fun Firebase.initialize(context: Any?, options: FirebaseOptions) = - FirebaseApp(firebase.initializeApp(options.toJson())) + FirebaseApp(initializeApp(options.toJson())) -actual class FirebaseApp internal constructor(val js: firebase.App) { +actual class FirebaseApp internal constructor(val js: JsFirebaseApp) { actual val name: String get() = js.name actual val options: FirebaseOptions get() = js.options.run { - FirebaseOptions(applicationId, apiKey, databaseUrl, gaTrackingId, storageBucket, projectId, messagingSenderId, authDomain) + FirebaseOptions( + js.options.appId, + js.options.apiKey, + js.options.databaseURL, + js.options.gaTrackingId, + js.options.storageBucket, + js.options.projectId, + js.options.messagingSenderId, + js.options.authDomain + ) } } -actual fun Firebase.apps(context: Any?) = firebase.apps.map { FirebaseApp(it) } +actual fun Firebase.apps(context: Any?) = getApps().map { FirebaseApp(it) } private fun FirebaseOptions.toJson() = json( "apiKey" to apiKey, diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt index 670ddeab4..03b6a0459 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt @@ -13,27 +13,11 @@ import kotlin.js.Promise external object firebase { open class App { - val name: String - val options: Options fun functions(region: String? = definedExternally): functions.Functions - fun database(url: String? = definedExternally): database.Database fun firestore(): firestore.Firestore } - interface Options { - val applicationId: String - val apiKey: String - val databaseUrl: String? - val gaTrackingId: String? - val storageBucket: String? - val projectId: String? - val messagingSenderId: String? - val authDomain: String? - } - - val apps : Array fun app(name: String? = definedExternally): App - fun initializeApp(options: Any, name: String? = definedExternally) : App interface FirebaseError { var code: String @@ -286,63 +270,6 @@ external object firebase { } - fun database(app: App? = definedExternally): database.Database - - object database { - fun enableLogging(logger: Boolean?, persistent: Boolean? = definedExternally) - - open class Database { - fun ref(path: String? = definedExternally): Reference - fun useEmulator(host: String, port: Int) - } - open class ThenableReference : Reference - - - open class Query { - fun on(eventType: String?, callback: SnapshotCallback, cancelCallbackOrContext: (error: Error) -> Unit? = definedExternally, context: Any? = definedExternally): SnapshotCallback - fun off(eventType: String?, callback: SnapshotCallback?, context: Any? = definedExternally) - fun once(eventType: String, callback: SnapshotCallback, failureCallbackOrContext: (error: Error) -> Unit? = definedExternally, context: Any? = definedExternally): SnapshotCallback - fun orderByChild(path: String): Query - fun orderByKey(): Query - fun orderByValue(): Query - fun startAt(value: Any, key: String? = definedExternally): Query - fun endAt(value: Any, key: String? = definedExternally): Query - fun equalTo(value: Any, key: String? = definedExternally): Query - fun limitToFirst(limit: Int): Query - fun limitToLast (limit: Int): Query - } - - open class Reference: Query { - val key: String? - fun child(path: String): Reference - fun remove(): Promise - fun onDisconnect(): OnDisconnect - fun update(value: Any?): Promise - fun set(value: Any?): Promise - fun push(): ThenableReference - } - - open class DataSnapshot { - val key: String? - fun `val`(): Any - fun exists(): Boolean - fun forEach(action: (a: DataSnapshot) -> Boolean): Boolean - fun numChildren(): Int - fun child(path: String): DataSnapshot - } - - open class OnDisconnect { - fun update(value: Any?): Promise - fun remove(): Promise - fun cancel(): Promise - fun set(value: Any?): Promise - } - - object ServerValue { - val TIMESTAMP: Any - } - } - fun firestore(): firestore.Firestore object firestore { diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app.kt new file mode 100644 index 000000000..dd23959bb --- /dev/null +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app.kt @@ -0,0 +1,28 @@ +@file:JsModule("firebase/app") +@file:JsNonModule + +package dev.gitlive.firebase.externals + +external fun initializeApp(options: Any, name: String = definedExternally): FirebaseApp + +external fun getApp(name: String = definedExternally): FirebaseApp + +external fun getApps(): List + +external interface FirebaseApp { + val automaticDataCollectionEnabled: Boolean + val name: String + val options: FirebaseOptions +} + +external interface FirebaseOptions { + val apiKey: String + val appId : String + val authDomain: String? + val databaseURL: String? + val measurementId: String? + val messagingSenderId: String? + val gaTrackingId: String? + val projectId: String? + val storageBucket: String? +} diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database.kt new file mode 100644 index 000000000..71999426e --- /dev/null +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database.kt @@ -0,0 +1,129 @@ +@file:JsModule("firebase/database") +@file:JsNonModule + +package dev.gitlive.firebase.externals + +import dev.gitlive.firebase.* +import kotlin.js.Promise + +external fun child(parent: DatabaseReference, path: String): DatabaseReference + +external fun connectDatabaseEmulator( + db: Database, + host: String, + port: Int, + options: Any? = definedExternally +) + +external fun enableLogging(enabled: Boolean?, persistent: Boolean? = definedExternally) + +external fun endAt(value: Any?, key: String? = definedExternally): QueryConstraint + +external fun endBefore(value: Any?, key: String? = definedExternally): QueryConstraint + +external fun equalTo(value: Any?, key: String? = definedExternally): QueryConstraint + +external fun get(query: Query): Promise + +external fun getDatabase( + app: FirebaseApp? = definedExternally, + url: String? = definedExternally +): Database + +external fun increment(delta: Long): Any + +external fun limitToFirst(limit: Int): QueryConstraint + +external fun limitToLast(limit: Int): QueryConstraint + +external fun off(query: Query, eventType: String?, callback: Any?) + +external fun onChildAdded( + query: Query, + callback: ChangeSnapshotCallback, + cancelCallback: CancelCallback? = definedExternally, +): Unsubscribe + +external fun onChildChanged( + query: Query, + callback: ChangeSnapshotCallback, + cancelCallback: CancelCallback? = definedExternally, +): Unsubscribe + +external fun onChildMoved( + query: Query, + callback: ChangeSnapshotCallback, + cancelCallback: CancelCallback? = definedExternally, +): Unsubscribe + +external fun onChildRemoved( + query: Query, + callback: ChangeSnapshotCallback, + cancelCallback: CancelCallback? = definedExternally, +): Unsubscribe + +external fun onValue( + query: Query, + callback: ValueSnapshotCallback, + cancelCallback: CancelCallback? = definedExternally, +): Unsubscribe + +external fun onDisconnect(ref: DatabaseReference): OnDisconnect + +external fun orderByChild(path: String): QueryConstraint + +external fun orderByKey(): QueryConstraint + +external fun orderByValue(): QueryConstraint + +external fun push(parent: DatabaseReference, value: Any? = definedExternally): ThenableReference + +external fun query(query: Query, vararg queryConstraints: QueryConstraint): Query + +external fun ref(db: Database, path: String? = definedExternally): DatabaseReference + +external fun remove(ref: DatabaseReference): Promise + +external fun serverTimestamp(): Any + +external fun set(ref: DatabaseReference, value: Any?): Promise + +external fun startAfter(value: Any?, key: String? = definedExternally): QueryConstraint + +external fun startAt(value: Any?, key: String? = definedExternally): QueryConstraint + +external fun update(ref: DatabaseReference, values: Any): Promise + +external interface Database { + val app: FirebaseApp +} + +external interface Query { + val ref: DatabaseReference +} + +external interface QueryConstraint + +external interface DatabaseReference : Query { + val key: String? + val parent: DatabaseReference? + val root: DatabaseReference +} + +external interface ThenableReference : DatabaseReference + +external interface DataSnapshot { + val key: String? + fun `val`(): Any + fun exists(): Boolean + fun forEach(action: (a: DataSnapshot) -> Boolean): Boolean + fun numChildren(): Int + fun child(path: String): DataSnapshot +} + +external interface OnDisconnect { + fun cancel(): Promise + fun remove(): Promise + fun set(value: Any?): Promise + fun update(value: Any): Promise +} diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt index ece0901c3..75d5e6443 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt @@ -4,6 +4,7 @@ package dev.gitlive.firebase +import dev.gitlive.firebase.externals.DataSnapshot import kotlin.js.Promise @JsModule("firebase/compat/auth") @@ -28,8 +29,10 @@ external object installations @JsName("default") external object remoteConfig -typealias SnapshotCallback = (data: firebase.database.DataSnapshot, b: String?) -> Unit +typealias ChangeSnapshotCallback = (data: DataSnapshot, previousChildName: String?) -> Unit +typealias ValueSnapshotCallback = (data: DataSnapshot) -> Unit +typealias CancelCallback = (error: Throwable) -> Unit +typealias Unsubscribe = () -> Unit operator fun firebase.functions.HttpsCallable.invoke() = asDynamic()() as Promise operator fun firebase.functions.HttpsCallable.invoke(data: Any?) = asDynamic()(data) as Promise - diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt index 9a595e051..467f5f423 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -5,6 +5,8 @@ package dev.gitlive.firebase.database import dev.gitlive.firebase.* +import dev.gitlive.firebase.FirebaseApp +import dev.gitlive.firebase.externals.* import kotlinx.coroutines.* import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow @@ -14,123 +16,161 @@ import kotlinx.coroutines.selects.select import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationStrategy import kotlin.js.Promise +import dev.gitlive.firebase.externals.DataSnapshot as JsDataSnapshot +import dev.gitlive.firebase.externals.DatabaseReference as JsDatabaseReference +import dev.gitlive.firebase.externals.OnDisconnect as JsOnDisconnect +import dev.gitlive.firebase.externals.Query as JsQuery +import dev.gitlive.firebase.externals.endAt as jsEndAt +import dev.gitlive.firebase.externals.equalTo as jsEqualTo +import dev.gitlive.firebase.externals.limitToFirst as jsLimitToFirst +import dev.gitlive.firebase.externals.limitToLast as jsLimitToLast +import dev.gitlive.firebase.externals.orderByChild as jsOrderByChild +import dev.gitlive.firebase.externals.orderByKey as jsOrderByKey +import dev.gitlive.firebase.externals.orderByValue as jsOrderByValue +import dev.gitlive.firebase.externals.startAt as jsStartAt @PublishedApi internal inline fun encode(value: T, shouldEncodeElementDefault: Boolean) = - encode(value, shouldEncodeElementDefault, firebase.database.ServerValue.TIMESTAMP) + encode(value, shouldEncodeElementDefault, serverTimestamp()) -internal fun encode(strategy: SerializationStrategy, value: T, shouldEncodeElementDefault: Boolean): Any? = - encode(strategy, value, shouldEncodeElementDefault, firebase.database.ServerValue.TIMESTAMP) +internal fun encode( + strategy: SerializationStrategy, + value: T, + shouldEncodeElementDefault: Boolean +): Any? = encode(strategy, value, shouldEncodeElementDefault, serverTimestamp()) -actual val Firebase.database - get() = rethrow { dev.gitlive.firebase.database; FirebaseDatabase(firebase.database()) } +actual val Firebase.database get() = rethrow { FirebaseDatabase(getDatabase()) } actual fun Firebase.database(app: FirebaseApp) = - rethrow { dev.gitlive.firebase.database; FirebaseDatabase(firebase.database(app.js)) } + rethrow { FirebaseDatabase(getDatabase(app = app.js)) } -actual fun Firebase.database(url: String) = - rethrow { dev.gitlive.firebase.database; FirebaseDatabase(firebase.app().database(url)) } +actual fun Firebase.database(url: String) = rethrow { FirebaseDatabase(getDatabase(url = url)) } actual fun Firebase.database(app: FirebaseApp, url: String) = - rethrow { dev.gitlive.firebase.database; FirebaseDatabase(app.js.database(url)) } + rethrow { FirebaseDatabase(getDatabase(app = app.js, url = url)) } -actual class FirebaseDatabase internal constructor(val js: firebase.database.Database) { - actual fun reference(path: String) = rethrow { DatabaseReference(js.ref(path)) } - actual fun reference() = rethrow { DatabaseReference(js.ref()) } +actual class FirebaseDatabase internal constructor(val js: Database) { + actual fun reference(path: String) = rethrow { DatabaseReference(ref(js, path)) } + actual fun reference() = rethrow { DatabaseReference(ref(js)) } actual fun setPersistenceEnabled(enabled: Boolean) {} - actual fun setLoggingEnabled(enabled: Boolean) = rethrow { firebase.database.enableLogging(enabled) } - actual fun useEmulator(host: String, port: Int) = rethrow { js.useEmulator(host, port) } + actual fun setLoggingEnabled(enabled: Boolean) = rethrow { enableLogging(enabled) } + + actual fun useEmulator(host: String, port: Int) = + rethrow { connectDatabaseEmulator(js, host, port) } } -actual open class Query internal constructor(open val js: firebase.database.Query) { +actual open class Query internal constructor(open val js: JsQuery) { - actual fun orderByKey() = Query(js.orderByKey()) - actual fun orderByValue() = Query(js.orderByValue()) - actual fun orderByChild(path: String) = Query(js.orderByChild(path)) + actual fun orderByKey() = Query(query(js, jsOrderByKey())) + actual fun orderByValue() = Query(query(js, jsOrderByValue())) + actual fun orderByChild(path: String) = Query(query(js, jsOrderByChild(path))) - actual val valueEvents get() = callbackFlow { - val listener = rethrow { - js.on( - "value", - { it, _ -> trySend(DataSnapshot(it)) }, - { close(DatabaseException(it)).run { Unit } } - ) + actual val valueEvents + get() = callbackFlow { + val unsubscribe = rethrow { + onValue( + query = js, + callback = { trySend(DataSnapshot(it)) }, + cancelCallback = { close(DatabaseException(it)).run { } } + ) + } + awaitClose { rethrow { unsubscribe() } } } - awaitClose { rethrow { js.off("value", listener) } } - } actual fun childEvents(vararg types: ChildEvent.Type) = callbackFlow { - val listeners = rethrow { + + val unsubscribes = rethrow { types.map { type -> - "child_${type.name.lowercase()}".let { eventType -> - eventType to js.on( - eventType, - { snapshot, previousChildName -> - trySend( - ChildEvent( - DataSnapshot(snapshot), - type, - previousChildName - ) - ) - }, - { close(DatabaseException(it)).run { Unit } } + val callback: ChangeSnapshotCallback = { snapshot, previousChildName -> + trySend( + ChildEvent( + DataSnapshot(snapshot), + type, + previousChildName + ) ) } + + val cancelCallback: CancelCallback = { + close(DatabaseException(it)).run { } + } + + when (type) { + ChildEvent.Type.ADDED -> onChildAdded(js, callback, cancelCallback) + ChildEvent.Type.CHANGED -> onChildChanged(js, callback, cancelCallback) + ChildEvent.Type.MOVED -> onChildMoved(js, callback, cancelCallback) + ChildEvent.Type.REMOVED -> onChildRemoved(js, callback, cancelCallback) + } + } } - awaitClose { rethrow { listeners.forEach { (eventType, listener) -> js.off(eventType, listener) } } } + + awaitClose { rethrow { unsubscribes.forEach { it.invoke() } } } } - actual fun startAt(value: String, key: String?) = Query(js.startAt(value, key ?: undefined)) + actual fun startAt(value: String, key: String?) = + Query(query(js, jsStartAt(value, key ?: undefined))) - actual fun startAt(value: Double, key: String?) = Query(js.startAt(value, key ?: undefined)) + actual fun startAt(value: Double, key: String?) = + Query(query(js, jsStartAt(value, key ?: undefined))) - actual fun startAt(value: Boolean, key: String?) = Query(js.startAt(value, key ?: undefined)) + actual fun startAt(value: Boolean, key: String?) = + Query(query(js, jsStartAt(value, key ?: undefined))) - actual fun endAt(value: String, key: String?) = Query(js.endAt(value, key ?: undefined)) + actual fun endAt(value: String, key: String?) = + Query(query(js, jsEndAt(value, key ?: undefined))) - actual fun endAt(value: Double, key: String?) = Query(js.endAt(value, key ?: undefined)) + actual fun endAt(value: Double, key: String?) = + Query(query(js, jsEndAt(value, key ?: undefined))) - actual fun endAt(value: Boolean, key: String?) = Query(js.endAt(value, key ?: undefined)) + actual fun endAt(value: Boolean, key: String?) = + Query(query(js, jsEndAt(value, key ?: undefined))) - actual fun limitToFirst(limit: Int) = Query(js.limitToFirst(limit)) + actual fun limitToFirst(limit: Int) = Query(query(js, jsLimitToFirst(limit))) - actual fun limitToLast(limit: Int) = Query(js.limitToLast(limit)) + actual fun limitToLast(limit: Int) = Query(query(js, jsLimitToLast(limit))) - actual fun equalTo(value: String, key: String?) = Query(js.equalTo(value, key ?: undefined)) + actual fun equalTo(value: String, key: String?) = + Query(query(js, jsEqualTo(value, key ?: undefined))) - actual fun equalTo(value: Double, key: String?) = Query(js.equalTo(value, key ?: undefined)) + actual fun equalTo(value: Double, key: String?) = + Query(query(js, jsEqualTo(value, key ?: undefined))) - actual fun equalTo(value: Boolean, key: String?) = Query(js.equalTo(value, key ?: undefined)) + actual fun equalTo(value: Boolean, key: String?) = + Query(query(js, jsEqualTo(value, key ?: undefined))) override fun toString() = js.toString() } -actual class DatabaseReference internal constructor(override val js: firebase.database.Reference): Query(js) { +actual class DatabaseReference internal constructor( + override val js: JsDatabaseReference +) : Query(js) { actual val key get() = rethrow { js.key } - actual fun push() = rethrow { DatabaseReference(js.push()) } - actual fun child(path: String) = rethrow { DatabaseReference(js.child(path)) } + actual fun push() = rethrow { DatabaseReference(push(js)) } + actual fun child(path: String) = rethrow { DatabaseReference(child(js, path)) } - actual fun onDisconnect() = rethrow { OnDisconnect(js.onDisconnect()) } + actual fun onDisconnect() = rethrow { OnDisconnect(onDisconnect(js)) } actual suspend fun updateChildren(update: Map, encodeDefaults: Boolean) = - rethrow { js.update(encode(update, encodeDefaults)).awaitWhileOnline() } + rethrow { update(js, encode(update, encodeDefaults)!!).awaitWhileOnline() } - actual suspend fun removeValue() = rethrow { js.remove().awaitWhileOnline() } + actual suspend fun removeValue() = rethrow { remove(js).awaitWhileOnline() } actual suspend inline fun setValue(value: T?, encodeDefaults: Boolean) = rethrow { - js.set(encode(value, encodeDefaults)).awaitWhileOnline() + set(js, encode(value, encodeDefaults)).awaitWhileOnline() } - actual suspend fun setValue(strategy: SerializationStrategy, value: T, encodeDefaults: Boolean) = - rethrow { js.set(encode(strategy, value, encodeDefaults)).awaitWhileOnline() } + actual suspend fun setValue( + strategy: SerializationStrategy, + value: T, + encodeDefaults: Boolean + ) = rethrow { set(js, encode(strategy, value, encodeDefaults)).awaitWhileOnline() } } -actual class DataSnapshot internal constructor(val js: firebase.database.DataSnapshot) { +actual class DataSnapshot internal constructor(val js: JsDataSnapshot) { actual inline fun value() = rethrow { decode(value = js.`val`()) } @@ -150,33 +190,42 @@ actual class DataSnapshot internal constructor(val js: firebase.database.DataSna } -actual class OnDisconnect internal constructor(val js: firebase.database.OnDisconnect) { +actual class OnDisconnect internal constructor(val js: JsOnDisconnect) { actual suspend fun removeValue() = rethrow { js.remove().awaitWhileOnline() } - actual suspend fun cancel() = rethrow { js.cancel().awaitWhileOnline() } + actual suspend fun cancel() = rethrow { js.cancel().awaitWhileOnline() } actual suspend fun updateChildren(update: Map, encodeDefaults: Boolean) = - rethrow { js.update(encode(update, encodeDefaults)).awaitWhileOnline() } + rethrow { js.update(encode(update, encodeDefaults)!!).awaitWhileOnline() } actual suspend inline fun setValue(value: T, encodeDefaults: Boolean) = rethrow { js.set(encode(value, encodeDefaults)).awaitWhileOnline() } - actual suspend fun setValue(strategy: SerializationStrategy, value: T, encodeDefaults: Boolean) = + actual suspend fun setValue( + strategy: SerializationStrategy, + value: T, + encodeDefaults: Boolean + ) = rethrow { js.set(encode(strategy, value, encodeDefaults)).awaitWhileOnline() } } -actual class DatabaseException actual constructor(message: String?, cause: Throwable?) : RuntimeException(message, cause) { - constructor(error: dynamic) : this("${error.code ?: "UNKNOWN"}: ${error.message}", error.unsafeCast()) +actual class DatabaseException actual constructor(message: String?, cause: Throwable?) : + RuntimeException(message, cause) { + constructor(error: dynamic) : this( + "${error.code ?: "UNKNOWN"}: ${error.message}", + error.unsafeCast() + ) } -inline fun T.rethrow(function: T.() -> R): R = dev.gitlive.firebase.database.rethrow { function() } +inline fun T.rethrow(function: T.() -> R): R = + dev.gitlive.firebase.database.rethrow { function() } inline fun rethrow(function: () -> R): R { try { return function() } catch (e: Exception) { throw e - } catch(e: dynamic) { + } catch (e: dynamic) { throw DatabaseException(e) } } From ea7fa10810234444e00e964a6748ede00a348005 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Sat, 11 Jun 2022 20:28:21 +0300 Subject: [PATCH 02/28] Refactor auth --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 53 ++-- .../dev/gitlive/firebase/auth/credentials.kt | 62 +++-- .../dev/gitlive/firebase/auth/multifactor.kt | 26 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 63 +++-- .../kotlin/dev/gitlive/firebase/externals.kt | 229 --------------- .../dev/gitlive/firebase/externals/auth.kt | 260 ++++++++++++++++++ 6 files changed, 395 insertions(+), 298 deletions(-) create mode 100644 firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth.kt 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 ea117682a..3c12b4db2 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 @@ -5,18 +5,21 @@ package dev.gitlive.firebase.auth import dev.gitlive.firebase.* +import dev.gitlive.firebase.FirebaseApp +import dev.gitlive.firebase.externals.* import kotlinx.coroutines.await import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow import kotlin.js.json +import dev.gitlive.firebase.externals.AuthResult as JsAuthResult actual val Firebase.auth - get() = rethrow { dev.gitlive.firebase.auth; FirebaseAuth(firebase.auth()) } + get() = rethrow { FirebaseAuth(getAuth()) } actual fun Firebase.auth(app: FirebaseApp) = - rethrow { dev.gitlive.firebase.auth; FirebaseAuth(firebase.auth(app.js)) } + rethrow { FirebaseAuth(getAuth(app.js)) } -actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) { +actual class FirebaseAuth internal constructor(val js: Auth) { actual val currentUser: FirebaseUser? get() = rethrow { js.currentUser?.let { FirebaseUser(it) } } @@ -39,47 +42,51 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) { get() = js.languageCode ?: "" set(value) { js.languageCode = value } - actual suspend fun applyActionCode(code: String) = rethrow { js.applyActionCode(code).await() } - actual suspend fun confirmPasswordReset(code: String, newPassword: String) = rethrow { js.confirmPasswordReset(code, newPassword).await() } + actual suspend fun applyActionCode(code: String) = rethrow { applyActionCode(js, code).await() } + actual suspend fun confirmPasswordReset(code: String, newPassword: String) = rethrow { + confirmPasswordReset(js, code, newPassword).await() + } actual suspend fun createUserWithEmailAndPassword(email: String, password: String) = - rethrow { AuthResult(js.createUserWithEmailAndPassword(email, password).await()) } + rethrow { AuthResult(createUserWithEmailAndPassword(js, email, password).await()) } - actual suspend fun fetchSignInMethodsForEmail(email: String): List = rethrow { js.fetchSignInMethodsForEmail(email).await().asList() } + actual suspend fun fetchSignInMethodsForEmail(email: String): List = rethrow { + fetchSignInMethodsForEmail(js, email).await().asList() + } actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) = - rethrow { js.sendPasswordResetEmail(email, actionCodeSettings?.toJson()).await() } + rethrow { sendPasswordResetEmail(js, email, actionCodeSettings?.toJson()).await() } actual suspend fun sendSignInLinkToEmail(email: String, actionCodeSettings: ActionCodeSettings) = - rethrow { js.sendSignInLinkToEmail(email, actionCodeSettings.toJson()).await() } + rethrow { sendSignInLinkToEmail(js, email, actionCodeSettings.toJson()).await() } - actual fun isSignInWithEmailLink(link: String) = rethrow { js.isSignInWithEmailLink(link) } + actual fun isSignInWithEmailLink(link: String) = rethrow { isSignInWithEmailLink(js, link) } actual suspend fun signInWithEmailAndPassword(email: String, password: String) = - rethrow { AuthResult(js.signInWithEmailAndPassword(email, password).await()) } + rethrow { AuthResult(signInWithEmailAndPassword(js, email, password).await()) } actual suspend fun signInWithCustomToken(token: String) = - rethrow { AuthResult(js.signInWithCustomToken(token).await()) } + rethrow { AuthResult(signInWithCustomToken(js, token).await()) } actual suspend fun signInAnonymously() = - rethrow { AuthResult(js.signInAnonymously().await()) } + rethrow { AuthResult(signInAnonymously(js).await()) } actual suspend fun signInWithCredential(authCredential: AuthCredential) = - rethrow { AuthResult(js.signInWithCredential(authCredential.js).await()) } + rethrow { AuthResult(signInWithCredential(js, authCredential.js).await()) } actual suspend fun signInWithEmailLink(email: String, link: String) = - rethrow { AuthResult(js.signInWithEmailLink(email, link).await()) } + rethrow { AuthResult(signInWithEmailLink(js, email, link).await()) } - actual suspend fun signOut() = rethrow { js.signOut().await() } + actual suspend fun signOut() = rethrow { signOut(js).await() } actual suspend fun updateCurrentUser(user: FirebaseUser) = - rethrow { js.updateCurrentUser(user.js).await() } + rethrow { updateCurrentUser(js, user.js).await() } actual suspend fun verifyPasswordResetCode(code: String): String = - rethrow { js.verifyPasswordResetCode(code).await() } + rethrow { verifyPasswordResetCode(js, code).await() } actual suspend fun checkActionCode(code: String): T = rethrow { - val result = js.checkActionCode(code).await() + val result = checkActionCode(js, code).await() @Suppress("UNCHECKED_CAST") return when(result.operation) { "EMAIL_SIGNIN" -> ActionCodeResult.SignInWithEmailLink @@ -98,15 +105,17 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) { } as T } - actual fun useEmulator(host: String, port: Int) = rethrow { js.useEmulator("http://$host:$port") } + actual fun useEmulator(host: String, port: Int) = rethrow { + connectAuthEmulator(js, "http://$host:$port") + } } -actual class AuthResult internal constructor(val js: firebase.auth.AuthResult) { +actual class AuthResult internal constructor(val js: JsAuthResult) { actual val user: FirebaseUser? get() = rethrow { js.user?.let { FirebaseUser(it) } } } -actual class AuthTokenResult(val js: firebase.auth.IdTokenResult) { +actual class AuthTokenResult(val js: IdTokenResult) { // actual val authTimestamp: Long // get() = js.authTime actual val claims: Map diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 13db5dc70..2a784710b 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -1,36 +1,43 @@ package dev.gitlive.firebase.auth -import dev.gitlive.firebase.firebase +import dev.gitlive.firebase.externals.* +import dev.gitlive.firebase.externals.EmailAuthProvider +import dev.gitlive.firebase.externals.FacebookAuthProvider +import dev.gitlive.firebase.externals.GithubAuthProvider +import dev.gitlive.firebase.externals.GoogleAuthProvider +import dev.gitlive.firebase.externals.PhoneAuthProvider +import dev.gitlive.firebase.externals.TwitterAuthProvider import kotlinx.coroutines.await -import kotlin.js.Json import kotlin.js.json +import dev.gitlive.firebase.externals.AuthCredential as JsAuthCredential +import dev.gitlive.firebase.externals.OAuthProvider as JsOAuthProvider -actual open class AuthCredential(val js: firebase.auth.AuthCredential) { +actual open class AuthCredential(val js: JsAuthCredential) { actual val providerId: String get() = js.providerId } -actual class PhoneAuthCredential(js: firebase.auth.AuthCredential) : AuthCredential(js) -actual class OAuthCredential(js: firebase.auth.AuthCredential) : AuthCredential(js) +actual class PhoneAuthCredential(js: JsAuthCredential) : AuthCredential(js) +actual class OAuthCredential(js: JsAuthCredential) : AuthCredential(js) actual object EmailAuthProvider { actual fun credential(email: String, password: String): AuthCredential = - AuthCredential(firebase.auth.EmailAuthProvider.credential(email, password)) + AuthCredential(EmailAuthProvider.credential(email, password)) actual fun credentialWithLink( email: String, emailLink: String - ): AuthCredential = AuthCredential(firebase.auth.EmailAuthProvider.credentialWithLink(email, emailLink)) + ): AuthCredential = AuthCredential(EmailAuthProvider.credentialWithLink(email, emailLink)) } actual object FacebookAuthProvider { actual fun credential(accessToken: String): AuthCredential = - AuthCredential(firebase.auth.FacebookAuthProvider.credential(accessToken)) + AuthCredential(FacebookAuthProvider.credential(accessToken)) } actual object GithubAuthProvider { actual fun credential(token: String): AuthCredential = - AuthCredential(firebase.auth.GithubAuthProvider.credential(token)) + AuthCredential(GithubAuthProvider.credential(token)) } actual object GoogleAuthProvider { @@ -38,26 +45,32 @@ actual object GoogleAuthProvider { require(idToken != null || accessToken != null) { "Both parameters are optional but at least one must be present." } - return AuthCredential(firebase.auth.GoogleAuthProvider.credential(idToken, accessToken)) + return AuthCredential(GoogleAuthProvider.credential(idToken, accessToken)) } } -actual class OAuthProvider(val js: firebase.auth.OAuthProvider) { +actual class OAuthProvider(val js: JsOAuthProvider) { actual constructor( provider: String, scopes: List, customParameters: Map, auth: FirebaseAuth - ) : this(firebase.auth.OAuthProvider(provider)) { + ) : this(JsOAuthProvider(provider)) { rethrow { scopes.forEach { js.addScope(it) } js.setCustomParameters(customParameters) } } + actual companion object { - actual fun credential(providerId: String, accessToken: String?, idToken: String?, rawNonce: String?): OAuthCredential = rethrow { - firebase.auth.OAuthProvider(providerId) + actual fun credential( + providerId: String, + accessToken: String?, + idToken: String?, + rawNonce: String? + ): OAuthCredential = rethrow { + JsOAuthProvider(providerId) .credential( json( "accessToken" to (accessToken ?: undefined), @@ -71,23 +84,30 @@ actual class OAuthProvider(val js: firebase.auth.OAuthProvider) { } } -actual class PhoneAuthProvider(val js: firebase.auth.PhoneAuthProvider) { +actual class PhoneAuthProvider(val js: PhoneAuthProvider) { + + actual constructor(auth: FirebaseAuth) : this(PhoneAuthProvider(auth.js)) - actual constructor(auth: FirebaseAuth) : this(firebase.auth.PhoneAuthProvider(auth.js)) + actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = + PhoneAuthCredential(PhoneAuthProvider.credential(verificationId, smsCode)) - actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(firebase.auth.PhoneAuthProvider.credential(verificationId, smsCode)) - actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential = rethrow { - val verificationId = js.verifyPhoneNumber(phoneNumber, verificationProvider.verifier).await() + actual suspend fun verifyPhoneNumber( + phoneNumber: String, + verificationProvider: PhoneVerificationProvider + ): AuthCredential = rethrow { + val verificationId = + js.verifyPhoneNumber(phoneNumber, verificationProvider.verifier).await() val verificationCode = verificationProvider.getVerificationCode(verificationId) credential(verificationId, verificationCode) } } actual interface PhoneVerificationProvider { - val verifier: firebase.auth.ApplicationVerifier + val verifier: ApplicationVerifier suspend fun getVerificationCode(verificationId: String): String } actual object TwitterAuthProvider { - actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(firebase.auth.TwitterAuthProvider.credential(token, secret)) + actual fun credential(token: String, secret: String): AuthCredential = + AuthCredential(TwitterAuthProvider.credential(token, secret)) } diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index 41cd7edbf..de227388a 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -1,23 +1,31 @@ package dev.gitlive.firebase.auth -import dev.gitlive.firebase.firebase +import dev.gitlive.firebase.externals.MultiFactorUser import kotlinx.coroutines.await import kotlin.js.Date +import dev.gitlive.firebase.externals.MultiFactorAssertion as JsMultiFactorAssertion +import dev.gitlive.firebase.externals.MultiFactorInfo as JsMultiFactorInfo +import dev.gitlive.firebase.externals.MultiFactorResolver as JsMultiFactorResolver +import dev.gitlive.firebase.externals.MultiFactorSession as JsMultiFactorSession -actual class MultiFactor(val js: firebase.multifactor.MultiFactorUser) { +actual class MultiFactor(val js: MultiFactorUser) { actual val enrolledFactors: List get() = rethrow { js.enrolledFactors.map { MultiFactorInfo(it) } } + actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) = rethrow { js.enroll(multiFactorAssertion.js, displayName).await() } + actual suspend fun getSession(): MultiFactorSession = rethrow { MultiFactorSession(js.getSession().await()) } + actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo) = rethrow { js.unenroll(multiFactorInfo.js).await() } + actual suspend fun unenroll(factorUid: String) = rethrow { js.unenroll(factorUid).await() } } -actual class MultiFactorInfo(val js: firebase.multifactor.MultiFactorInfo) { +actual class MultiFactorInfo(val js: JsMultiFactorInfo) { actual val displayName: String? get() = rethrow { js.displayName } actual val enrollmentTime: Double @@ -28,17 +36,19 @@ actual class MultiFactorInfo(val js: firebase.multifactor.MultiFactorInfo) { get() = rethrow { js.uid } } -actual class MultiFactorAssertion(val js: firebase.multifactor.MultiFactorAssertion) { +actual class MultiFactorAssertion(val js: JsMultiFactorAssertion) { actual val factorId: String get() = rethrow { js.factorId } } -actual class MultiFactorSession(val js: firebase.multifactor.MultiFactorSession) +actual class MultiFactorSession(val js: JsMultiFactorSession) -actual class MultiFactorResolver(val js: firebase.multifactor.MultifactorResolver) { +actual class MultiFactorResolver(val js: JsMultiFactorResolver) { actual val auth: FirebaseAuth = rethrow { FirebaseAuth(js.auth) } actual val hints: List = rethrow { js.hints.map { MultiFactorInfo(it) } } actual val session: MultiFactorSession = rethrow { MultiFactorSession(js.session) } - actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = rethrow { AuthResult(js.resolveSignIn(assertion.js).await()) } -} \ No newline at end of file + actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = rethrow { + AuthResult(js.resolveSignIn(assertion.js).await()) + } +} diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt index ab6cb796e..2a4730e36 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -1,10 +1,19 @@ package dev.gitlive.firebase.auth -import dev.gitlive.firebase.firebase +import dev.gitlive.firebase.externals.* import kotlinx.coroutines.await import kotlin.js.Date +import dev.gitlive.firebase.externals.UserInfo as JsUserInfo +import dev.gitlive.firebase.externals.getIdTokenResult +import dev.gitlive.firebase.externals.linkWithCredential +import dev.gitlive.firebase.externals.sendEmailVerification +import dev.gitlive.firebase.externals.unlink +import dev.gitlive.firebase.externals.updateEmail +import dev.gitlive.firebase.externals.updatePassword +import dev.gitlive.firebase.externals.updatePhoneNumber +import dev.gitlive.firebase.externals.updateProfile -actual class FirebaseUser internal constructor(val js: firebase.user.User) { +actual class FirebaseUser internal constructor(val js: User) { actual val uid: String get() = rethrow { js.uid } actual val displayName: String? @@ -22,38 +31,56 @@ actual class FirebaseUser internal constructor(val js: firebase.user.User) { actual val metaData: UserMetaData? get() = rethrow { UserMetaData(js.metadata) } actual val multiFactor: MultiFactor - get() = rethrow { MultiFactor(js.multiFactor) } + get() = rethrow { MultiFactor(multiFactor(js)) } actual val providerData: List get() = rethrow { js.providerData.map { UserInfo(it) } } actual val providerId: String get() = rethrow { js.providerId } actual suspend fun delete() = rethrow { js.delete().await() } actual suspend fun reload() = rethrow { js.reload().await() } - actual suspend fun getIdToken(forceRefresh: Boolean): String? = rethrow { js.getIdToken(forceRefresh).await() } - actual suspend fun getIdTokenResult(forceRefresh: Boolean): AuthTokenResult = rethrow { AuthTokenResult(js.getIdTokenResult(forceRefresh).await()) } - actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = rethrow { AuthResult(js.linkWithCredential(credential.js).await()) } + actual suspend fun getIdToken(forceRefresh: Boolean): String? = rethrow { + js.getIdToken(forceRefresh).await() + } + actual suspend fun getIdTokenResult(forceRefresh: Boolean): AuthTokenResult = rethrow { + AuthTokenResult(getIdTokenResult(js, forceRefresh).await()) + } + actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = rethrow { + AuthResult( linkWithCredential(js, credential.js).await()) + } actual suspend fun reauthenticate(credential: AuthCredential) = rethrow { - js.reauthenticateWithCredential(credential.js).await() + reauthenticateWithCredential(js, credential.js).await() Unit } - actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = rethrow { AuthResult(js.reauthenticateWithCredential(credential.js).await()) } + actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = + rethrow { AuthResult(reauthenticateWithCredential(js, credential.js).await()) } - actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = rethrow { js.sendEmailVerification(actionCodeSettings?.toJson()).await() } - actual suspend fun unlink(provider: String): FirebaseUser? = rethrow { FirebaseUser(js.unlink(provider).await()) } - actual suspend fun updateEmail(email: String) = rethrow { js.updateEmail(email).await() } - actual suspend fun updatePassword(password: String) = rethrow { js.updatePassword(password).await() } - actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = rethrow { js.updatePhoneNumber(credential.js).await() } + actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = rethrow { + sendEmailVerification(js, actionCodeSettings?.toJson()).await() + } + actual suspend fun unlink(provider: String): FirebaseUser? = rethrow { + FirebaseUser(unlink(js, provider).await()) + } + actual suspend fun updateEmail(email: String) = rethrow { updateEmail(js, email).await() } + actual suspend fun updatePassword(password: String) = rethrow { + updatePassword(js, password).await() + } + actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = rethrow { + updatePhoneNumber(js, credential.js).await() + } actual suspend fun updateProfile(displayName: String?, photoUrl: String?) = rethrow { - val request = object : firebase.user.ProfileUpdateRequest { + val request = object : ProfileUpdateRequest { override val displayName: String? = displayName override val photoURL: String? = photoUrl } - js.updateProfile(request).await() + updateProfile(js, request).await() } - actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = rethrow { js.verifyBeforeUpdateEmail(newEmail, actionCodeSettings?.toJson()).await() } + actual suspend fun verifyBeforeUpdateEmail( + newEmail: String, + actionCodeSettings: ActionCodeSettings? + ) = rethrow { verifyBeforeUpdateEmail(js, newEmail, actionCodeSettings?.toJson()).await() } } -actual class UserInfo(val js: firebase.user.UserInfo) { +actual class UserInfo(val js: JsUserInfo) { actual val displayName: String? get() = rethrow { js.displayName } actual val email: String? @@ -68,7 +95,7 @@ actual class UserInfo(val js: firebase.user.UserInfo) { get() = rethrow { js.uid } } -actual class UserMetaData(val js: firebase.user.UserMetadata) { +actual class UserMetaData(val js: UserMetadata) { actual val creationTime: Double? get() = rethrow {js.creationTime?.let { (Date(it).getTime() / 1000.0) } } actual val lastSignInTime: Double? diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt index 03b6a0459..0926a0eba 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt @@ -25,235 +25,6 @@ external object firebase { var name: String } - fun auth(app: App? = definedExternally): auth.Auth - - object auth { - open class Auth { - val currentUser: user.User? - var languageCode: String? - - fun useEmulator(url: String) - fun applyActionCode(code: String): Promise - fun checkActionCode(code: String): Promise - fun confirmPasswordReset(code: String, newPassword: String): Promise - fun createUserWithEmailAndPassword(email: String, password: String): Promise - fun fetchSignInMethodsForEmail(email: String): Promise> - fun sendPasswordResetEmail(email: String, actionCodeSettings: Any?): Promise - fun sendSignInLinkToEmail(email: String, actionCodeSettings: Any?): Promise - fun isSignInWithEmailLink(link: String): Boolean - fun signInWithEmailAndPassword(email: String, password: String): Promise - fun signInWithCustomToken(token: String): Promise - fun signInAnonymously(): Promise - fun signInWithCredential(authCredential: AuthCredential): Promise - fun signInWithPopup(provider: AuthProvider): Promise - fun signInWithRedirect(provider: AuthProvider): Promise - fun signInWithEmailLink(email: String, link: String): Promise - fun getRedirectResult(): Promise - fun signOut(): Promise - fun updateCurrentUser(user: user.User?): Promise - fun verifyPasswordResetCode(code: String): Promise - - fun onAuthStateChanged(nextOrObserver: (user.User?) -> Unit): () -> Unit - fun onIdTokenChanged(nextOrObserver: (user.User?) -> Unit): () -> Unit - } - - abstract class IdTokenResult { - val authTime: String - val claims: Json - val expirationTime: String - val issuedAtTime: String - val signInProvider: String? - val signInSecondFactor: String? - val token: String - } - - abstract class AuthResult { - val credential: AuthCredential? - val operationType: String? - val user: user.User? - } - - abstract class AuthCredential { - val providerId: String - val signInMethod: String - } - - abstract class ActionCodeInfo { - val operation: String - val data: ActionCodeData - } - - abstract class ActionCodeData { - val email: String? - val multiFactorInfo: multifactor.MultiFactorInfo? - val previousEmail: String? - } - - interface ActionCodeSettings { - val android: AndroidActionCodeSettings? - val dynamicLinkDomain: String? - val handleCodeInApp: Boolean? - val iOS: iOSActionCodeSettings? - val url: String - } - - interface AndroidActionCodeSettings { - val installApp: Boolean? - val minimumVersion: String? - val packageName: String - } - - interface iOSActionCodeSettings { - val bundleId: String? - } - - interface AuthProvider - - class EmailAuthProvider : AuthProvider { - companion object { - fun credential(email : String, password : String): AuthCredential - fun credentialWithLink(email: String, emailLink: String): AuthCredential - } - } - - class FacebookAuthProvider : AuthProvider { - companion object { - fun credential(token: String): AuthCredential - } - } - - class GithubAuthProvider : AuthProvider { - companion object { - fun credential(token: String): AuthCredential - } - } - - class GoogleAuthProvider : AuthProvider{ - companion object { - fun credential(idToken: String?, accessToken: String?): AuthCredential - } - } - - open class OAuthProvider(providerId: String) : AuthProvider { - val providerId: String - fun credential(optionsOrIdToken: Any?, accessToken: String?): AuthCredential - - fun addScope(scope: String) - fun setCustomParameters(customOAuthParameters: Map) - } - - interface OAuthCredentialOptions { - val accessToken: String? - val idToken: String? - val rawNonce: String? - } - - class PhoneAuthProvider(auth: Auth?) : AuthProvider { - companion object { - fun credential(verificationId: String, verificationCode: String): AuthCredential - } - fun verifyPhoneNumber(phoneInfoOptions: String, applicationVerifier: ApplicationVerifier): Promise - } - - abstract class ApplicationVerifier { - val type: String - fun verify(): Promise - } - - class TwitterAuthProvider : AuthProvider { - companion object { - fun credential (token: String, secret: String): AuthCredential - } - } - } - - fun User(a: Any,b: Any,c: Any): user.User - - object user { - abstract class User { - val uid: String - val displayName: String? - val email: String? - val emailVerified: Boolean - val metadata: UserMetadata - val multiFactor: multifactor.MultiFactorUser - val phoneNumber: String? - val photoURL: String? - val providerData: Array - val providerId: String - val refreshToken: String - val tenantId: String? - val isAnonymous: Boolean - - fun delete(): Promise - fun getIdToken(forceRefresh: Boolean?): Promise - fun getIdTokenResult(forceRefresh: Boolean?): Promise - fun linkWithCredential(credential: auth.AuthCredential): Promise - fun reauthenticateWithCredential(credential: auth.AuthCredential): Promise - fun reload(): Promise - fun sendEmailVerification(actionCodeSettings: Any?): Promise - fun unlink(providerId: String): Promise - fun updateEmail(newEmail: String): Promise - fun updatePassword(newPassword: String): Promise - fun updatePhoneNumber(phoneCredential: auth.AuthCredential): Promise - fun updateProfile(profile: ProfileUpdateRequest): Promise - fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: Any?): Promise - } - - abstract class UserMetadata { - val creationTime: String? - val lastSignInTime: String? - } - - abstract class UserInfo { - val displayName: String? - val email: String? - val phoneNumber: String? - val photoURL: String? - val providerId: String - val uid: String - } - - interface ProfileUpdateRequest { - val displayName: String? - val photoURL: String? - } - - } - - object multifactor { - abstract class MultiFactorUser { - val enrolledFactors: Array - - fun enroll(assertion: MultiFactorAssertion, displayName: String?): Promise - fun getSession(): Promise - fun unenroll(option: MultiFactorInfo): Promise - fun unenroll(option: String): Promise - } - - abstract class MultiFactorInfo { - val displayName: String? - val enrollmentTime: String - val factorId: String - val uid: String - } - - abstract class MultiFactorAssertion { - val factorId: String - } - - interface MultiFactorSession - - abstract class MultifactorResolver { - - val auth: auth.Auth - val hints: Array - val session: MultiFactorSession - - fun resolveSignIn(assertion: MultiFactorAssertion): Promise - } - } - fun functions(app: App? = definedExternally): functions.Functions object functions { diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth.kt new file mode 100644 index 000000000..cf0bf31e3 --- /dev/null +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth.kt @@ -0,0 +1,260 @@ +@file:JsModule("firebase/auth") +@file:JsNonModule + +package dev.gitlive.firebase.externals + +import dev.gitlive.firebase.Unsubscribe +import kotlin.js.Json +import kotlin.js.Promise + +external fun applyActionCode(auth: Auth, code: String): Promise + +external fun checkActionCode(auth: Auth, code: String): Promise + +external fun confirmPasswordReset(auth: Auth, code: String, newPassword: String): Promise + +external fun connectAuthEmulator(auth: Auth, url: String, options: Any? = definedExternally) + +external fun createUserWithEmailAndPassword( + auth: Auth, + email: String, + password: String +): Promise + +external fun deleteUser(user: User): Promise + +external fun fetchSignInMethodsForEmail(auth: Auth, email: String): Promise> + +external fun getAuth(app: FirebaseApp? = definedExternally): Auth + +external fun getIdToken(user: User, forceRefresh: Boolean?): Promise + +external fun getIdTokenResult(user: User, forceRefresh: Boolean?): Promise + +external fun isSignInWithEmailLink(auth: Auth, link: String): Boolean + +external fun linkWithCredential(user: User, credential: AuthCredential): Promise + +external fun multiFactor(user: User): MultiFactorUser + +external fun onAuthStateChanged(auth: Auth, nextOrObserver: (User?) -> Unit): Unsubscribe + +external fun onIdTokenChanged(auth: Auth, nextOrObserver: (User?) -> Unit): Unsubscribe + +external fun sendEmailVerification(user: User, actionCodeSettings: Any?): Promise + +external fun reauthenticateWithCredential( + user: User, + credential: AuthCredential +): Promise + +external fun reload(user: User): Promise + +external fun sendPasswordResetEmail( + auth: Auth, + email: String, + actionCodeSettings: Any? +): Promise + +external fun sendSignInLinkToEmail( + auth: Auth, + email: String, + actionCodeSettings: Any? +): Promise + +external fun signInAnonymously(auth: Auth): Promise + +external fun signInWithCredential(auth: Auth, authCredential: AuthCredential): Promise + +external fun signInWithCustomToken(auth: Auth, token: String): Promise + +external fun signInWithEmailAndPassword( + auth: Auth, + email: String, + password: String +): Promise + +external fun signInWithEmailLink(auth: Auth, email: String, link: String): Promise + +external fun signOut(auth: Auth): Promise + +external fun unlink(user: User, providerId: String): Promise + +external fun updateCurrentUser(auth: Auth, user: User?): Promise + +external fun updateEmail(user: User, newEmail: String): Promise + +external fun updatePassword(user: User, newPassword: String): Promise + +external fun updatePhoneNumber(user: User, phoneCredential: AuthCredential): Promise + +external fun updateProfile(user: User, profile: ProfileUpdateRequest): Promise + +external fun verifyBeforeUpdateEmail( + user: User, + newEmail: String, + actionCodeSettings: Any? +): Promise + +external fun verifyPasswordResetCode(auth: Auth, code: String): Promise + +external interface Auth { + val currentUser: User? + var languageCode: String? + + fun onAuthStateChanged(nextOrObserver: (User?) -> Unit): Unsubscribe + fun onIdTokenChanged(nextOrObserver: (User?) -> Unit): Unsubscribe + fun signOut(): Promise + fun updateCurrentUser(user: User?): Promise +} + +external interface UserInfo { + val displayName: String? + val email: String? + val phoneNumber: String? + val photoURL: String? + val providerId: String + val uid: String +} + +external interface User : UserInfo { + val emailVerified: Boolean + val isAnonymous: Boolean + val metadata: UserMetadata + val providerData: Array + val refreshToken: String + val tenantId: String? + + fun delete(): Promise + fun getIdToken(forceRefresh: Boolean?): Promise + fun getIdTokenResult(forceRefresh: Boolean?): Promise + fun reload(): Promise +} + +external interface UserMetadata { + val creationTime: String? + val lastSignInTime: String? +} + +external interface IdTokenResult { + val authTime: String + val claims: Json + val expirationTime: String + val issuedAtTime: String + val signInProvider: String? + val signInSecondFactor: String? + val token: String +} + +external interface ActionCodeInfo { + val operation: String + val data: ActionCodeData +} + +external interface ActionCodeData { + val email: String? + val multiFactorInfo: MultiFactorInfo? + val previousEmail: String? +} + +external interface AuthResult { + val credential: AuthCredential? + val operationType: String? + val user: User? +} + +external interface AuthCredential { + val providerId: String + val signInMethod: String +} + +external interface ProfileUpdateRequest { + val displayName: String? + val photoURL: String? +} + +external interface MultiFactorUser { + val enrolledFactors: Array + + fun enroll(assertion: MultiFactorAssertion, displayName: String?): Promise + fun getSession(): Promise + fun unenroll(option: MultiFactorInfo): Promise + fun unenroll(option: String): Promise +} + +external interface MultiFactorInfo { + val displayName: String? + val enrollmentTime: String + val factorId: String + val uid: String +} + +external interface MultiFactorAssertion { + val factorId: String +} + +external interface MultiFactorSession + +external interface MultiFactorResolver { + val auth: Auth + val hints: Array + val session: MultiFactorSession + + fun resolveSignIn(assertion: MultiFactorAssertion): Promise +} + +external interface AuthProvider + +external object EmailAuthProvider : AuthProvider { + fun credential(email: String, password: String): AuthCredential + fun credentialWithLink(email: String, emailLink: String): AuthCredential +} + +external object FacebookAuthProvider : AuthProvider { + fun credential(token: String): AuthCredential +} + +external object GithubAuthProvider : AuthProvider { + fun credential(token: String): AuthCredential +} + +external object GoogleAuthProvider : AuthProvider { + fun credential(idToken: String?, accessToken: String?): AuthCredential +} + +external class OAuthProvider(providerId: String) : AuthProvider { + val providerId: String + fun credential(optionsOrIdToken: Any?, accessToken: String?): AuthCredential + + fun addScope(scope: String) + fun setCustomParameters(customOAuthParameters: Map) +} + +external interface OAuthCredentialOptions { + val accessToken: String? + val idToken: String? + val rawNonce: String? +} + +external class PhoneAuthProvider(auth: Auth?) : AuthProvider { + companion object { + fun credential( + verificationId: String, + verificationCode: String + ): AuthCredential + } + + fun verifyPhoneNumber( + phoneInfoOptions: String, + applicationVerifier: ApplicationVerifier + ): Promise +} + +external interface ApplicationVerifier { + val type: String + fun verify(): Promise +} + +external object TwitterAuthProvider : AuthProvider { + fun credential(token: String, secret: String): AuthCredential +} From 3846b15565fc7e32b2f15c4473b5b4624020429f Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Sun, 12 Jun 2022 19:12:46 +0300 Subject: [PATCH 03/28] Refactor firestore --- .../kotlin/dev/gitlive/firebase/firebase.kt | 8 +- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 4 +- .../dev/gitlive/firebase/auth/credentials.kt | 18 +- .../dev/gitlive/firebase/auth/multifactor.kt | 10 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 12 +- .../kotlin/dev/gitlive/firebase/externals.kt | 135 ---------- .../firebase/externals/{ => app}/app.kt | 2 +- .../firebase/externals/{ => auth}/auth.kt | 3 +- .../externals/{ => database}/database.kt | 3 +- .../firebase/externals/firestore/firestore.kt | 255 ++++++++++++++++++ .../kotlin/dev/gitlive/firebase/externals2.kt | 14 +- .../dev/gitlive/firebase/database/database.kt | 26 +- .../gitlive/firebase/firestore/firestore.kt | 2 +- .../gitlive/firebase/firestore/firestore.kt | 2 +- .../gitlive/firebase/firestore/firestore.kt | 2 +- .../gitlive/firebase/firestore/firestore.kt | 206 ++++++++------ 16 files changed, 417 insertions(+), 285 deletions(-) rename firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/{ => app}/app.kt (94%) rename firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/{ => auth}/auth.kt (98%) rename firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/{ => database}/database.kt (97%) create mode 100644 firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore/firestore.kt diff --git a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt index 946943042..4e40e52fd 100644 --- a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt +++ b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt @@ -4,11 +4,11 @@ package dev.gitlive.firebase -import dev.gitlive.firebase.externals.getApp -import dev.gitlive.firebase.externals.getApps -import dev.gitlive.firebase.externals.initializeApp +import dev.gitlive.firebase.externals.app.getApp +import dev.gitlive.firebase.externals.app.getApps +import dev.gitlive.firebase.externals.app.initializeApp import kotlin.js.json -import dev.gitlive.firebase.externals.FirebaseApp as JsFirebaseApp +import dev.gitlive.firebase.externals.app.FirebaseApp as JsFirebaseApp actual val Firebase.app: FirebaseApp get() = FirebaseApp(getApp()) 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 3c12b4db2..95cd6de18 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 @@ -6,12 +6,12 @@ package dev.gitlive.firebase.auth import dev.gitlive.firebase.* import dev.gitlive.firebase.FirebaseApp -import dev.gitlive.firebase.externals.* +import dev.gitlive.firebase.externals.auth.* import kotlinx.coroutines.await import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow import kotlin.js.json -import dev.gitlive.firebase.externals.AuthResult as JsAuthResult +import dev.gitlive.firebase.externals.auth.AuthResult as JsAuthResult actual val Firebase.auth get() = rethrow { FirebaseAuth(getAuth()) } diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 2a784710b..9b719a716 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -1,16 +1,16 @@ package dev.gitlive.firebase.auth -import dev.gitlive.firebase.externals.* -import dev.gitlive.firebase.externals.EmailAuthProvider -import dev.gitlive.firebase.externals.FacebookAuthProvider -import dev.gitlive.firebase.externals.GithubAuthProvider -import dev.gitlive.firebase.externals.GoogleAuthProvider -import dev.gitlive.firebase.externals.PhoneAuthProvider -import dev.gitlive.firebase.externals.TwitterAuthProvider +import dev.gitlive.firebase.externals.auth.* +import dev.gitlive.firebase.externals.auth.EmailAuthProvider +import dev.gitlive.firebase.externals.auth.FacebookAuthProvider +import dev.gitlive.firebase.externals.auth.GithubAuthProvider +import dev.gitlive.firebase.externals.auth.GoogleAuthProvider +import dev.gitlive.firebase.externals.auth.PhoneAuthProvider +import dev.gitlive.firebase.externals.auth.TwitterAuthProvider import kotlinx.coroutines.await import kotlin.js.json -import dev.gitlive.firebase.externals.AuthCredential as JsAuthCredential -import dev.gitlive.firebase.externals.OAuthProvider as JsOAuthProvider +import dev.gitlive.firebase.externals.auth.AuthCredential as JsAuthCredential +import dev.gitlive.firebase.externals.auth.OAuthProvider as JsOAuthProvider actual open class AuthCredential(val js: JsAuthCredential) { actual val providerId: String diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index de227388a..45b1291d5 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -1,12 +1,12 @@ package dev.gitlive.firebase.auth -import dev.gitlive.firebase.externals.MultiFactorUser +import dev.gitlive.firebase.externals.auth.MultiFactorUser import kotlinx.coroutines.await import kotlin.js.Date -import dev.gitlive.firebase.externals.MultiFactorAssertion as JsMultiFactorAssertion -import dev.gitlive.firebase.externals.MultiFactorInfo as JsMultiFactorInfo -import dev.gitlive.firebase.externals.MultiFactorResolver as JsMultiFactorResolver -import dev.gitlive.firebase.externals.MultiFactorSession as JsMultiFactorSession +import dev.gitlive.firebase.externals.auth.MultiFactorAssertion as JsMultiFactorAssertion +import dev.gitlive.firebase.externals.auth.MultiFactorInfo as JsMultiFactorInfo +import dev.gitlive.firebase.externals.auth.MultiFactorResolver as JsMultiFactorResolver +import dev.gitlive.firebase.externals.auth.MultiFactorSession as JsMultiFactorSession actual class MultiFactor(val js: MultiFactorUser) { actual val enrolledFactors: List diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt index 2a4730e36..38bf58322 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -1,17 +1,9 @@ package dev.gitlive.firebase.auth -import dev.gitlive.firebase.externals.* +import dev.gitlive.firebase.externals.auth.* import kotlinx.coroutines.await import kotlin.js.Date -import dev.gitlive.firebase.externals.UserInfo as JsUserInfo -import dev.gitlive.firebase.externals.getIdTokenResult -import dev.gitlive.firebase.externals.linkWithCredential -import dev.gitlive.firebase.externals.sendEmailVerification -import dev.gitlive.firebase.externals.unlink -import dev.gitlive.firebase.externals.updateEmail -import dev.gitlive.firebase.externals.updatePassword -import dev.gitlive.firebase.externals.updatePhoneNumber -import dev.gitlive.firebase.externals.updateProfile +import dev.gitlive.firebase.externals.auth.UserInfo as JsUserInfo actual class FirebaseUser internal constructor(val js: User) { actual val uid: String diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt index 0926a0eba..f5f519517 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt @@ -14,7 +14,6 @@ external object firebase { open class App { fun functions(region: String? = definedExternally): functions.Functions - fun firestore(): firestore.Firestore } fun app(name: String? = definedExternally): App @@ -41,140 +40,6 @@ external object firebase { } - fun firestore(): firestore.Firestore - - object firestore { - fun setLogLevel(level: String) - - open class PersistenceSettings { - var experimentalTabSynchronization: Boolean - } - - open class Firestore { - fun runTransaction(func: (transaction: Transaction) -> Promise): Promise - fun batch(): WriteBatch - fun collection(collectionPath: String): CollectionReference - fun collectionGroup(collectionId: String): Query - fun doc(documentPath: String): DocumentReference - fun settings(settings: Json) - fun enablePersistence(): Promise - fun clearPersistence(): Promise - fun useEmulator(host: String, port: Int) - fun disableNetwork(): Promise - fun enableNetwork(): Promise - } - - open class Timestamp { - val seconds: Double - val nanoseconds: Double - fun toMillis(): Double - } - - open class Query { - fun get(options: Any? = definedExternally): Promise - fun where(field: String, opStr: String, value: Any?): Query - fun where(field: FieldPath, opStr: String, value: Any?): Query - fun onSnapshot(next: (snapshot: QuerySnapshot) -> Unit, error: (error: Error) -> Unit): () -> Unit - fun onSnapshot(options: Json, next: (snapshot: QuerySnapshot) -> Unit, error: (error: Error) -> Unit): () -> Unit - fun limit(limit: Double): Query - fun orderBy(field: String, direction: Any): Query - fun orderBy(field: FieldPath, direction: Any): Query - fun startAfter(document: DocumentSnapshot): Query - fun startAfter(vararg fieldValues: Any): Query - fun startAt(document: DocumentSnapshot): Query - fun startAt(vararg fieldValues: Any): Query - fun endBefore(document: DocumentSnapshot): Query - fun endBefore(vararg fieldValues: Any): Query - fun endAt(document: DocumentSnapshot): Query - fun endAt(vararg fieldValues: Any): Query - } - - open class CollectionReference : Query { - val path: String - val parent: DocumentReference? - fun doc(path: String = definedExternally): DocumentReference - fun add(data: Any): Promise - } - - open class QuerySnapshot { - val docs: Array - fun docChanges(): Array - val empty: Boolean - val metadata: SnapshotMetadata - } - - open class DocumentChange { - val doc: DocumentSnapshot - val newIndex: Int - val oldIndex: Int - val type: String - } - - open class DocumentSnapshot { - val id: String - val ref: DocumentReference - val exists: Boolean - val metadata: SnapshotMetadata - fun data(options: Any? = definedExternally): Any? - fun get(fieldPath: String, options: Any? = definedExternally): Any? - fun get(fieldPath: FieldPath, options: Any? = definedExternally): Any? - } - - open class SnapshotMetadata { - val hasPendingWrites: Boolean - val fromCache: Boolean - } - - open class DocumentReference { - val id: String - val path: String - val parent: CollectionReference - - fun collection(path: String): CollectionReference - fun get(options: Any? = definedExternally): Promise - fun set(data: Any, options: Any? = definedExternally): Promise - fun update(data: Any): Promise - fun update(field: String, value: Any?, vararg moreFieldsAndValues: Any?): Promise - fun update(field: FieldPath, value: Any?, vararg moreFieldsAndValues: Any?): Promise - fun delete(): Promise - fun onSnapshot(next: (snapshot: DocumentSnapshot) -> Unit, error: (error: Error) -> Unit): ()->Unit - } - - open class WriteBatch { - fun commit(): Promise - fun delete(documentReference: DocumentReference): WriteBatch - fun set(documentReference: DocumentReference, data: Any, options: Any? = definedExternally): WriteBatch - fun update(documentReference: DocumentReference, data: Any): WriteBatch - fun update(documentReference: DocumentReference, field: String, value: Any?, vararg moreFieldsAndValues: Any?): WriteBatch - fun update(documentReference: DocumentReference, field: FieldPath, value: Any?, vararg moreFieldsAndValues: Any?): WriteBatch - } - - open class Transaction { - fun get(documentReference: DocumentReference): Promise - fun set(documentReference: DocumentReference, data: Any, options: Any? = definedExternally): Transaction - fun update(documentReference: DocumentReference, data: Any): Transaction - fun update(documentReference: DocumentReference, field: String, value: Any?, vararg moreFieldsAndValues: Any?): Transaction - fun update(documentReference: DocumentReference, field: FieldPath, value: Any?, vararg moreFieldsAndValues: Any?): Transaction - fun delete(documentReference: DocumentReference): Transaction - } - - open class FieldPath(vararg fieldNames: String) { - companion object { - val documentId: FieldPath - } - } - - abstract class FieldValue { - companion object { - fun serverTimestamp(): FieldValue - fun delete(): FieldValue - fun increment(value: Int): FieldValue - fun arrayRemove(vararg elements: Any): FieldValue - fun arrayUnion(vararg elements: Any): FieldValue - } - } - } - fun remoteConfig(app: App? = definedExternally): remoteConfig.RemoteConfig object remoteConfig { diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt similarity index 94% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app.kt rename to firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt index dd23959bb..161e5ebfd 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt @@ -1,7 +1,7 @@ @file:JsModule("firebase/app") @file:JsNonModule -package dev.gitlive.firebase.externals +package dev.gitlive.firebase.externals.app external fun initializeApp(options: Any, name: String = definedExternally): FirebaseApp diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth/auth.kt similarity index 98% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth.kt rename to firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth/auth.kt index cf0bf31e3..fe3ebf175 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth/auth.kt @@ -1,9 +1,10 @@ @file:JsModule("firebase/auth") @file:JsNonModule -package dev.gitlive.firebase.externals +package dev.gitlive.firebase.externals.auth import dev.gitlive.firebase.Unsubscribe +import dev.gitlive.firebase.externals.app.FirebaseApp import kotlin.js.Json import kotlin.js.Promise diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt similarity index 97% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database.kt rename to firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt index 71999426e..be90ed990 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt @@ -1,9 +1,10 @@ @file:JsModule("firebase/database") @file:JsNonModule -package dev.gitlive.firebase.externals +package dev.gitlive.firebase.externals.database import dev.gitlive.firebase.* +import dev.gitlive.firebase.externals.app.FirebaseApp import kotlin.js.Promise external fun child(parent: DatabaseReference, path: String): DatabaseReference diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore/firestore.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore/firestore.kt new file mode 100644 index 000000000..1546142f9 --- /dev/null +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore/firestore.kt @@ -0,0 +1,255 @@ +@file:JsModule("firebase/firestore") +@file:JsNonModule + +package dev.gitlive.firebase.externals.firestore + +import dev.gitlive.firebase.Unsubscribe +import dev.gitlive.firebase.externals.app.FirebaseApp +import dev.gitlive.firebase.externals.database.QueryConstraint +import kotlin.js.Json +import kotlin.js.Promise + +external class FieldPath(vararg fieldNames: String) { + companion object { + val documentId: FieldPath + } +} + +external fun addDoc(reference: CollectionReference, data: Any): Promise + +external fun arrayRemove(vararg elements: Any): FieldValue + +external fun arrayUnion(vararg elements: Any): FieldValue + +external fun clearIndexedDbPersistence(firestore: Firestore): Promise + +external fun collection(firestore: Firestore, collectionPath: String): CollectionReference + +external fun collection(reference: DocumentReference, collectionPath: String): CollectionReference + +external fun collectionGroup(firestore: Firestore, collectionId: String): Query + +external fun connectFirestoreEmulator( + firestore: Firestore, + host: String, + port: Int, + options: Any? = definedExternally +) + +external fun deleteDoc(reference: DocumentReference): Promise + +external fun deleteField(): FieldValue + +external fun disableNetwork(firestore: Firestore): Promise + +external fun doc(firestore: Firestore, documentPath: String): DocumentReference + +external fun doc(firestore: CollectionReference, documentPath: String? = definedExternally): DocumentReference + +external fun enableIndexedDbPersistence( + firestore: Firestore, + persistenceSettings: Any? = definedExternally +): Promise + +external fun enableNetwork(firestore: Firestore): Promise + +external fun endAt(document: DocumentSnapshot): QueryConstraint + +external fun endAt(vararg fieldValues: Any): QueryConstraint + +external fun endBefore(document: DocumentSnapshot): QueryConstraint + +external fun endBefore(vararg fieldValues: Any): QueryConstraint + +external fun getDoc( + reference: DocumentReference, + options: Any? = definedExternally +): Promise + +external fun get(query: Query): Promise + +external fun getFirestore(app: FirebaseApp? = definedExternally): Firestore + +external fun increment(n: Int): FieldValue + +external fun initializeFirestore(app: FirebaseApp, settings: Any): Firestore + +external fun limit(limit: Number): QueryConstraint + +external fun onSnapshot( + reference: DocumentReference, + next: (snapshot: DocumentSnapshot) -> Unit, + error: (error: Throwable) -> Unit +): Unsubscribe + +external fun onSnapshot( + reference: Query, + next: (snapshot: QuerySnapshot) -> Unit, + error: (error: Throwable) -> Unit +): Unsubscribe + +external fun onSnapshot( + reference: Query, + options: Json, + next: (snapshot: QuerySnapshot) -> Unit, + error: (error: Throwable) -> Unit +): Unsubscribe + +external fun orderBy(field: String, direction: Any): QueryConstraint + +external fun orderBy(field: FieldPath, direction: Any): QueryConstraint + +external fun query(query: Query, vararg queryConstraints: QueryConstraint): Query + +external fun runTransaction( + firestore: Firestore, + updateFunction: (transaction: Transaction) -> Promise, + options: Any? = definedExternally +): Promise + +external fun serverTimestamp(): FieldValue + +external fun setDoc( + documentReference: DocumentReference, + data: Any, + options: Any? = definedExternally +): Promise + +external fun setLogLevel(logLevel: String) + +external fun startAfter(document: DocumentSnapshot): QueryConstraint + +external fun startAfter(vararg fieldValues: Any): QueryConstraint + +external fun startAt(document: DocumentSnapshot): QueryConstraint + +external fun startAt(vararg fieldValues: Any): QueryConstraint + +external fun update(reference: DocumentReference, data: Any): Promise + +external fun update( + reference: DocumentReference, + field: String, + value: Any?, + vararg moreFieldsAndValues: Any? +): Promise + +external fun update( + reference: DocumentReference, + field: FieldPath, + value: Any?, + vararg moreFieldsAndValues: Any? +): Promise + +external fun where(field: String, opStr: String, value: Any?): QueryConstraint + +external fun where(field: FieldPath, opStr: String, value: Any?): QueryConstraint + +external fun writeBatch(firestore: Firestore): WriteBatch + +external interface Firestore { + val app: FirebaseApp +} + +external interface CollectionReference : Query { + val id: String + val path: String + val parent: DocumentReference? +} + +external interface DocumentChange { + val doc: DocumentSnapshot + val newIndex: Int + val oldIndex: Int + val type: String +} + +external interface DocumentReference { + val id: String + val path: String + val parent: CollectionReference +} + +external interface DocumentSnapshot { + val id: String + val ref: DocumentReference + val exists: Boolean + val metadata: SnapshotMetadata + fun data(options: Any? = definedExternally): Any? + fun get(fieldPath: String, options: Any? = definedExternally): Any? + fun get(fieldPath: FieldPath, options: Any? = definedExternally): Any? +} + +external interface FieldValue + +external interface Query + +external interface QueryConstraint + +external interface QuerySnapshot { + val docs: Array + val empty: Boolean + val metadata: SnapshotMetadata + fun docChanges(): Array +} + +external interface SnapshotMetadata { + val hasPendingWrites: Boolean + val fromCache: Boolean +} + +external interface Transaction { + fun get(documentReference: DocumentReference): Promise + + fun set( + documentReference: DocumentReference, + data: Any, + options: Any? = definedExternally + ): Transaction + + fun update(documentReference: DocumentReference, data: Any): Transaction + + fun update( + documentReference: DocumentReference, + field: String, + value: Any?, + vararg moreFieldsAndValues: Any? + ): Transaction + + fun update( + documentReference: DocumentReference, + field: FieldPath, + value: Any?, + vararg moreFieldsAndValues: Any? + ): Transaction + + fun delete(documentReference: DocumentReference): Transaction +} + +external interface WriteBatch { + fun commit(): Promise + + fun delete(documentReference: DocumentReference): WriteBatch + + fun set( + documentReference: DocumentReference, + data: Any, + options: Any? = definedExternally + ): WriteBatch + + fun update(documentReference: DocumentReference, data: Any): WriteBatch + + fun update( + documentReference: DocumentReference, + field: String, + value: Any?, + vararg moreFieldsAndValues: Any? + ): WriteBatch + + fun update( + documentReference: DocumentReference, + field: FieldPath, + value: Any?, + vararg moreFieldsAndValues: Any? + ): WriteBatch +} diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt index 75d5e6443..da22b5fd9 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt @@ -4,21 +4,9 @@ package dev.gitlive.firebase -import dev.gitlive.firebase.externals.DataSnapshot +import dev.gitlive.firebase.externals.database.DataSnapshot import kotlin.js.Promise -@JsModule("firebase/compat/auth") -@JsName("default") -external object auth - -@JsModule("firebase/compat/database") -@JsName("default") -external object database - -@JsModule("firebase/compat/firestore") -@JsName("default") -external object firestore - @JsModule("firebase/compat/functions") @JsName("default") external object functions diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt index 467f5f423..6748a7b6f 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -6,7 +6,7 @@ package dev.gitlive.firebase.database import dev.gitlive.firebase.* import dev.gitlive.firebase.FirebaseApp -import dev.gitlive.firebase.externals.* +import dev.gitlive.firebase.externals.database.* import kotlinx.coroutines.* import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow @@ -16,18 +16,18 @@ import kotlinx.coroutines.selects.select import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationStrategy import kotlin.js.Promise -import dev.gitlive.firebase.externals.DataSnapshot as JsDataSnapshot -import dev.gitlive.firebase.externals.DatabaseReference as JsDatabaseReference -import dev.gitlive.firebase.externals.OnDisconnect as JsOnDisconnect -import dev.gitlive.firebase.externals.Query as JsQuery -import dev.gitlive.firebase.externals.endAt as jsEndAt -import dev.gitlive.firebase.externals.equalTo as jsEqualTo -import dev.gitlive.firebase.externals.limitToFirst as jsLimitToFirst -import dev.gitlive.firebase.externals.limitToLast as jsLimitToLast -import dev.gitlive.firebase.externals.orderByChild as jsOrderByChild -import dev.gitlive.firebase.externals.orderByKey as jsOrderByKey -import dev.gitlive.firebase.externals.orderByValue as jsOrderByValue -import dev.gitlive.firebase.externals.startAt as jsStartAt +import dev.gitlive.firebase.externals.database.DataSnapshot as JsDataSnapshot +import dev.gitlive.firebase.externals.database.DatabaseReference as JsDatabaseReference +import dev.gitlive.firebase.externals.database.OnDisconnect as JsOnDisconnect +import dev.gitlive.firebase.externals.database.Query as JsQuery +import dev.gitlive.firebase.externals.database.endAt as jsEndAt +import dev.gitlive.firebase.externals.database.equalTo as jsEqualTo +import dev.gitlive.firebase.externals.database.limitToFirst as jsLimitToFirst +import dev.gitlive.firebase.externals.database.limitToLast as jsLimitToLast +import dev.gitlive.firebase.externals.database.orderByChild as jsOrderByChild +import dev.gitlive.firebase.externals.database.orderByKey as jsOrderByKey +import dev.gitlive.firebase.externals.database.orderByValue as jsOrderByValue +import dev.gitlive.firebase.externals.database.startAt as jsStartAt @PublishedApi internal inline fun encode(value: T, shouldEncodeElementDefault: Boolean) = diff --git a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index fbde82667..8158188a2 100644 --- a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -471,7 +471,7 @@ actual class FieldPath private constructor(val android: com.google.firebase.fire } actual object FieldValue { - actual val serverTimestamp = Double.POSITIVE_INFINITY + actual val serverTimestamp: Any = Double.POSITIVE_INFINITY actual val delete: Any get() = FieldValue.delete() actual fun increment(value: Int): Any = FieldValue.increment(value.toDouble()) actual fun arrayUnion(vararg elements: Any): Any = FieldValue.arrayUnion(*elements) 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 410e23b71..9e2352592 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 @@ -241,7 +241,7 @@ expect class FieldPath(vararg fieldNames: String) { } expect object FieldValue { - val serverTimestamp: Double + val serverTimestamp: Any val delete: Any fun increment(value: Int): Any fun arrayUnion(vararg elements: Any): Any diff --git a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index 458b83b71..cf2b504a3 100644 --- a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -444,7 +444,7 @@ actual class FieldPath private constructor(val ios: FIRFieldPath) { } actual object FieldValue { - actual val serverTimestamp = Double.POSITIVE_INFINITY + actual val serverTimestamp: Any = Double.POSITIVE_INFINITY actual val delete: Any get() = FIRFieldValue.fieldValueForDelete() actual fun increment(value: Int): Any = FIRFieldValue.fieldValueForIntegerIncrement(value.toLong()) actual fun arrayUnion(vararg elements: Any): Any = FIRFieldValue.fieldValueForArrayUnion(elements.asList()) diff --git a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index 7f11641b9..05544ef13 100644 --- a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -5,6 +5,7 @@ package dev.gitlive.firebase.firestore import dev.gitlive.firebase.* +import dev.gitlive.firebase.externals.firestore.* import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.await import kotlinx.coroutines.channels.awaitClose @@ -13,6 +14,26 @@ import kotlinx.coroutines.promise import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationStrategy import kotlin.js.json +import dev.gitlive.firebase.externals.firestore.CollectionReference as JsCollectionReference +import dev.gitlive.firebase.externals.firestore.DocumentChange as JsDocumentChange +import dev.gitlive.firebase.externals.firestore.DocumentReference as JsDocumentReference +import dev.gitlive.firebase.externals.firestore.DocumentSnapshot as JsDocumentSnapshot +import dev.gitlive.firebase.externals.firestore.FieldPath as JsFieldPath +import dev.gitlive.firebase.externals.firestore.Query as JsQuery +import dev.gitlive.firebase.externals.firestore.QuerySnapshot as JsQuerySnapshot +import dev.gitlive.firebase.externals.firestore.SnapshotMetadata as JsSnapshotMetadata +import dev.gitlive.firebase.externals.firestore.Transaction as JsTransaction +import dev.gitlive.firebase.externals.firestore.WriteBatch as JsWriteBatch +import dev.gitlive.firebase.externals.firestore.arrayRemove as jsArrayRemove +import dev.gitlive.firebase.externals.firestore.arrayUnion as jsArrayUnion +import dev.gitlive.firebase.externals.firestore.endAt as jsEndAt +import dev.gitlive.firebase.externals.firestore.endBefore as jsEndBefore +import dev.gitlive.firebase.externals.firestore.increment as jsIncrement +import dev.gitlive.firebase.externals.firestore.update as jsUpdate +import dev.gitlive.firebase.externals.firestore.limit as jsLimit +import dev.gitlive.firebase.externals.firestore.startAfter as jsStartAfter +import dev.gitlive.firebase.externals.firestore.startAt as jsStartAt +import dev.gitlive.firebase.externals.firestore.where as jsWhere @PublishedApi internal inline fun decode(value: Any?): T = @@ -23,58 +44,62 @@ internal fun decode(strategy: DeserializationStrategy, value: Any?): T = @PublishedApi internal inline fun encode(value: T, shouldEncodeElementDefault: Boolean) = - encode(value, shouldEncodeElementDefault, firebase.firestore.FieldValue.serverTimestamp()) + encode(value, shouldEncodeElementDefault, serverTimestamp()) private fun encode(strategy: SerializationStrategy , value: T, shouldEncodeElementDefault: Boolean): Any? = - encode(strategy, value, shouldEncodeElementDefault, firebase.firestore.FieldValue.serverTimestamp()) + encode(strategy, value, shouldEncodeElementDefault, serverTimestamp()) actual val Firebase.firestore get() = - rethrow { dev.gitlive.firebase.firestore; FirebaseFirestore(firebase.firestore()) } + rethrow { FirebaseFirestore(getFirestore()) } actual fun Firebase.firestore(app: FirebaseApp) = - rethrow { dev.gitlive.firebase.firestore; FirebaseFirestore(firebase.app().firestore()) } + rethrow { FirebaseFirestore(getFirestore(app.js)) } -actual class FirebaseFirestore(val js: firebase.firestore.Firestore) { +actual class FirebaseFirestore(jsFirestore: Firestore) { - actual fun collection(collectionPath: String) = rethrow { CollectionReference(js.collection(collectionPath)) } + var js: Firestore = jsFirestore + private set - actual fun collectionGroup(collectionId: String) = Query(js.collectionGroup(collectionId)) + actual fun collection(collectionPath: String) = rethrow { CollectionReference(collection(js, collectionPath)) } - actual fun document(documentPath: String) = rethrow { DocumentReference(js.doc(documentPath)) } + actual fun collectionGroup(collectionId: String) = rethrow { Query(collectionGroup(js, collectionId)) } - actual fun batch() = rethrow { WriteBatch(js.batch()) } + actual fun document(documentPath: String) = rethrow { DocumentReference(doc(js, documentPath)) } + + actual fun batch() = rethrow { WriteBatch(writeBatch(js)) } actual fun setLoggingEnabled(loggingEnabled: Boolean) = - rethrow { firebase.firestore.setLogLevel( if(loggingEnabled) "error" else "silent") } + rethrow { setLogLevel( if(loggingEnabled) "error" else "silent") } actual suspend fun runTransaction(func: suspend Transaction.() -> T) = - rethrow { js.runTransaction { GlobalScope.promise { Transaction(it).func() } }.await() } + rethrow { runTransaction(js, { GlobalScope.promise { Transaction(it).func() } } ).await() } actual suspend fun clearPersistence() = - rethrow { js.clearPersistence().await() } + rethrow { clearIndexedDbPersistence(js).await() } - actual fun useEmulator(host: String, port: Int) = rethrow { js.useEmulator(host, port) } + actual fun useEmulator(host: String, port: Int) = rethrow { connectFirestoreEmulator(js, host, port) } actual fun setSettings(persistenceEnabled: Boolean?, sslEnabled: Boolean?, host: String?, cacheSizeBytes: Long?) { - if(persistenceEnabled == true) js.enablePersistence() + if(persistenceEnabled == true) enableIndexedDbPersistence(js) - js.settings(json().apply { + val settings = json().apply { sslEnabled?.let { set("ssl", it) } host?.let { set("host", it) } cacheSizeBytes?.let { set("cacheSizeBytes", it) } - }) + } + js = initializeFirestore(js.app, settings) } actual suspend fun disableNetwork() { - rethrow { js.disableNetwork().await() } + rethrow { disableNetwork(js).await() } } actual suspend fun enableNetwork() { - rethrow { js.enableNetwork().await() } + rethrow { enableNetwork(js).await() } } } -actual class WriteBatch(val js: firebase.firestore.WriteBatch) { +actual class WriteBatch(val js: JsWriteBatch) { actual inline fun set(documentRef: DocumentReference, data: T, encodeDefaults: Boolean, merge: Boolean) = rethrow { js.set(documentRef.js, encode(data, encodeDefaults)!!, json("merge" to merge)) } @@ -140,7 +165,7 @@ actual class WriteBatch(val js: firebase.firestore.WriteBatch) { } -actual class Transaction(val js: firebase.firestore.Transaction) { +actual class Transaction(val js: JsTransaction) { actual fun set(documentRef: DocumentReference, data: Any, encodeDefaults: Boolean, merge: Boolean) = rethrow { js.set(documentRef.js, encode(data, encodeDefaults)!!, json("merge" to merge)) } @@ -206,7 +231,7 @@ actual class Transaction(val js: firebase.firestore.Transaction) { rethrow { DocumentSnapshot(js.get(documentRef.js).await()) } } -actual class DocumentReference(val js: firebase.firestore.DocumentReference) { +actual class DocumentReference(val js: JsDocumentReference) { actual val id: String get() = rethrow { js.id } @@ -217,62 +242,65 @@ actual class DocumentReference(val js: firebase.firestore.DocumentReference) { actual val parent: CollectionReference get() = rethrow { CollectionReference(js.parent) } - actual fun collection(collectionPath: String) = rethrow { CollectionReference(js.collection(collectionPath)) } + actual fun collection(collectionPath: String) = rethrow { CollectionReference(collection(js, collectionPath)) } actual suspend inline fun set(data: T, encodeDefaults: Boolean, merge: Boolean) = - rethrow { js.set(encode(data, encodeDefaults)!!, json("merge" to merge)).await() } + rethrow { setDoc(js, encode(data, encodeDefaults)!!, json("merge" to merge)).await() } actual suspend inline fun set(data: T, encodeDefaults: Boolean, vararg mergeFields: String) = - rethrow { js.set(encode(data, encodeDefaults)!!, json("mergeFields" to mergeFields)).await() } + rethrow { setDoc(js, encode(data, encodeDefaults)!!, json("mergeFields" to mergeFields)).await() } actual suspend inline fun set(data: T, encodeDefaults: Boolean, vararg mergeFieldPaths: FieldPath) = - rethrow { js.set(encode(data, encodeDefaults)!!, json("mergeFields" to mergeFieldPaths.map { it.js }.toTypedArray())).await() } + rethrow { setDoc(js, encode(data, encodeDefaults)!!, json("mergeFields" to mergeFieldPaths.map { it.js }.toTypedArray())).await() } actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, merge: Boolean) = - rethrow { js.set(encode(strategy, data, encodeDefaults)!!, json("merge" to merge)).await() } + rethrow { setDoc(js, encode(strategy, data, encodeDefaults)!!, json("merge" to merge)).await() } actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, vararg mergeFields: String) = - rethrow { js.set(encode(strategy, data, encodeDefaults)!!, json("mergeFields" to mergeFields)).await() } + rethrow { setDoc(js, encode(strategy, data, encodeDefaults)!!, json("mergeFields" to mergeFields)).await() } actual suspend fun set(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean, vararg mergeFieldPaths: FieldPath) = - rethrow { js.set(encode(strategy, data, encodeDefaults)!!, json("mergeFields" to mergeFieldPaths.map { it.js }.toTypedArray())).await() } + rethrow { setDoc(js, encode(strategy, data, encodeDefaults)!!, json("mergeFields" to mergeFieldPaths.map { it.js }.toTypedArray())).await() } actual suspend inline fun update(data: T, encodeDefaults: Boolean) = - rethrow { js.update(encode(data, encodeDefaults)!!).await() } + rethrow { jsUpdate(js, encode(data, encodeDefaults)!!).await() } actual suspend fun update(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean) = - rethrow { js.update(encode(strategy, data, encodeDefaults)!!).await() } + rethrow { jsUpdate(js, encode(strategy, data, encodeDefaults)!!).await() } actual suspend fun update(vararg fieldsAndValues: Pair) = rethrow { - js.takeUnless { fieldsAndValues.isEmpty() } - ?.update( + js.takeUnless { fieldsAndValues.isEmpty() }?.let { + jsUpdate( + it, fieldsAndValues[0].first, fieldsAndValues[0].second, *fieldsAndValues.drop(1).flatMap { (field, value) -> listOf(field, value?.let { encode(it, true) }) }.toTypedArray() - ) - ?.await() + ).await() + } }.run { Unit } actual suspend fun update(vararg fieldsAndValues: Pair) = rethrow { - js.takeUnless { fieldsAndValues.isEmpty() } - ?.update( + js.takeUnless { fieldsAndValues.isEmpty() }?.let { + jsUpdate( + js, fieldsAndValues[0].first.js, fieldsAndValues[0].second, *fieldsAndValues.flatMap { (field, value) -> listOf(field.js, value?.let { encode(it, true)!! }) }.toTypedArray() - ) - ?.await() + ).await() + } }.run { Unit } - actual suspend fun delete() = rethrow { js.delete().await() } + actual suspend fun delete() = rethrow { deleteDoc(js).await() } - actual suspend fun get() = rethrow { DocumentSnapshot(js.get().await()) } + actual suspend fun get() = rethrow { DocumentSnapshot(getDoc(js).await()) } actual val snapshots get() = callbackFlow { - val unsubscribe = js.onSnapshot( + val unsubscribe = onSnapshot( + js, { trySend(DocumentSnapshot(it)) }, { close(errorToException(it)) } ) @@ -280,23 +308,23 @@ actual class DocumentReference(val js: firebase.firestore.DocumentReference) { } } -actual open class Query(open val js: firebase.firestore.Query) { +actual open class Query(open val js: JsQuery) { - actual suspend fun get() = rethrow { QuerySnapshot(js.get().await()) } + actual suspend fun get() = rethrow { QuerySnapshot(get(js).await()) } - actual fun limit(limit: Number) = Query(js.limit(limit.toDouble())) + actual fun limit(limit: Number) = Query(query(js, jsLimit(limit))) - internal actual fun _where(field: String, equalTo: Any?) = rethrow { Query(js.where(field, "==", equalTo)) } - internal actual fun _where(path: FieldPath, equalTo: Any?) = rethrow { Query(js.where(path.js, "==", equalTo)) } + internal actual fun _where(field: String, equalTo: Any?) = rethrow { Query(query(js, jsWhere(field, "==", equalTo))) } + internal actual fun _where(path: FieldPath, equalTo: Any?) = rethrow { Query(query(js, jsWhere(path.js, "==", equalTo))) } - internal actual fun _where(field: String, equalTo: DocumentReference) = rethrow { Query(js.where(field, "==", equalTo.js)) } - internal actual fun _where(path: FieldPath, equalTo: DocumentReference) = rethrow { Query(js.where(path.js, "==", equalTo.js)) } + internal actual fun _where(field: String, equalTo: DocumentReference) = rethrow { Query(query(js, jsWhere(field, "==", equalTo.js))) } + internal actual fun _where(path: FieldPath, equalTo: DocumentReference) = rethrow { Query(query(js, jsWhere(path.js, "==", equalTo.js))) } internal actual fun _where(field: String, lessThan: Any?, greaterThan: Any?, arrayContains: Any?) = rethrow { Query( - (lessThan?.let {js.where(field, "<", it) } ?: js).let { js2 -> - (greaterThan?.let { js2.where(field, ">", it) } ?: js2).let { js3 -> - arrayContains?.let { js3.where(field, "array-contains", it) } ?: js3 + (lessThan?.let { query(js, jsWhere(field, "<", it)) } ?: js).let { js2 -> + (greaterThan?.let { query(js2, jsWhere(field, ">", it)) } ?: js2).let { js3 -> + arrayContains?.let { query(js3, jsWhere(field, "array-contains", it)) } ?: js3 } } ) @@ -304,53 +332,54 @@ actual open class Query(open val js: firebase.firestore.Query) { internal actual fun _where(path: FieldPath, lessThan: Any?, greaterThan: Any?, arrayContains: Any?) = rethrow { Query( - (lessThan?.let {js.where(path.js, "<", it) } ?: js).let { js2 -> - (greaterThan?.let { js2.where(path.js, ">", it) } ?: js2).let { js3 -> - arrayContains?.let { js3.where(path.js, "array-contains", it) } ?: js3 + (lessThan?.let { query(js, jsWhere(path.js, "<", it)) } ?: js).let { js2 -> + (greaterThan?.let { query(js2, jsWhere(path.js, ">", it)) } ?: js2).let { js3 -> + arrayContains?.let { query(js3, jsWhere(path.js, "array-contains", it)) } ?: js3 } } ) } internal actual fun _where(field: String, inArray: List?, arrayContainsAny: List?) = Query( - (inArray?.let { js.where(field, "in", it.toTypedArray()) } ?: js).let { js2 -> - arrayContainsAny?.let { js2.where(field, "array-contains-any", it.toTypedArray()) } ?: js2 + (inArray?.let { query(js, jsWhere(field, "in", it.toTypedArray())) } ?: js).let { js2 -> + arrayContainsAny?.let { query(js2, jsWhere(field, "array-contains-any", it.toTypedArray())) } ?: js2 } ) internal actual fun _where(path: FieldPath, inArray: List?, arrayContainsAny: List?) = Query( - (inArray?.let { js.where(path.js, "in", it.toTypedArray()) } ?: js).let { js2 -> - arrayContainsAny?.let { js2.where(path.js, "array-contains-any", it.toTypedArray()) } ?: js2 + (inArray?.let { query(js, jsWhere(path.js, "in", it.toTypedArray())) } ?: js).let { js2 -> + arrayContainsAny?.let { query(js2, jsWhere(path.js, "array-contains-any", it.toTypedArray())) } ?: js2 } ) internal actual fun _orderBy(field: String, direction: Direction) = rethrow { - Query(js.orderBy(field, direction.jsString)) + Query(query(js, orderBy(field, direction.jsString))) } internal actual fun _orderBy(field: FieldPath, direction: Direction) = rethrow { - Query(js.orderBy(field.js, direction.jsString)) + Query(query(js, orderBy(field.js, direction.jsString))) } - internal actual fun _startAfter(document: DocumentSnapshot) = rethrow { Query(js.startAfter(document.js)) } + internal actual fun _startAfter(document: DocumentSnapshot) = rethrow { Query(query(js, jsStartAfter(document.js))) } - internal actual fun _startAfter(vararg fieldValues: Any) = rethrow { Query(js.startAfter(*fieldValues)) } + internal actual fun _startAfter(vararg fieldValues: Any) = rethrow { Query(query(js, jsStartAfter(*fieldValues))) } - internal actual fun _startAt(document: DocumentSnapshot) = rethrow { Query(js.startAt(document.js)) } + internal actual fun _startAt(document: DocumentSnapshot) = rethrow { Query(query(js, jsStartAt(document.js))) } - internal actual fun _startAt(vararg fieldValues: Any) = rethrow { Query(js.startAt(*fieldValues)) } + internal actual fun _startAt(vararg fieldValues: Any) = rethrow { Query(query(js, jsStartAt(*fieldValues))) } - internal actual fun _endBefore(document: DocumentSnapshot) = rethrow { Query(js.endBefore(document.js)) } + internal actual fun _endBefore(document: DocumentSnapshot) = rethrow { Query(query(js, jsEndBefore(document.js))) } - internal actual fun _endBefore(vararg fieldValues: Any) = rethrow { Query(js.endBefore(*fieldValues)) } + internal actual fun _endBefore(vararg fieldValues: Any) = rethrow { Query(query(js, jsEndBefore(*fieldValues))) } - internal actual fun _endAt(document: DocumentSnapshot) = rethrow { Query(js.endAt(document.js)) } + internal actual fun _endAt(document: DocumentSnapshot) = rethrow { Query(query(js, jsEndAt(document.js))) } - internal actual fun _endAt(vararg fieldValues: Any) = rethrow { Query(js.endAt(*fieldValues)) } + internal actual fun _endAt(vararg fieldValues: Any) = rethrow { Query(query(js, jsEndAt(*fieldValues))) } actual val snapshots get() = callbackFlow { val unsubscribe = rethrow { - js.onSnapshot( + onSnapshot( + js, { trySend(QuerySnapshot(it)) }, { close(errorToException(it)) } ) @@ -360,7 +389,8 @@ actual open class Query(open val js: firebase.firestore.Query) { actual fun snapshots(includeMetadataChanges: Boolean) = callbackFlow { val unsubscribe = rethrow { - js.onSnapshot( + onSnapshot( + js, json("includeMetadataChanges" to includeMetadataChanges), { trySend(QuerySnapshot(it)) }, { close(errorToException(it)) } @@ -370,24 +400,24 @@ actual open class Query(open val js: firebase.firestore.Query) { } } -actual class CollectionReference(override val js: firebase.firestore.CollectionReference) : Query(js) { +actual class CollectionReference(override val js: JsCollectionReference) : Query(js) { actual val path: String get() = rethrow { js.path } - actual val document get() = rethrow { DocumentReference(js.doc()) } + actual val document get() = rethrow { DocumentReference(doc(js)) } actual val parent get() = rethrow { js.parent?.let{DocumentReference(it)} } - actual fun document(documentPath: String) = rethrow { DocumentReference(js.doc(documentPath)) } + actual fun document(documentPath: String) = rethrow { DocumentReference(doc(js, documentPath)) } actual suspend inline fun add(data: T, encodeDefaults: Boolean) = - rethrow { DocumentReference(js.add(encode(data, encodeDefaults)!!).await()) } + rethrow { DocumentReference(addDoc(js, encode(data, encodeDefaults)!!).await()) } actual suspend fun add(data: T, strategy: SerializationStrategy, encodeDefaults: Boolean) = - rethrow { DocumentReference(js.add(encode(strategy, data, encodeDefaults)!!).await()) } + rethrow { DocumentReference(addDoc(js, encode(strategy, data, encodeDefaults)!!).await()) } actual suspend fun add(strategy: SerializationStrategy, data: T, encodeDefaults: Boolean) = - rethrow { DocumentReference(js.add(encode(strategy, data, encodeDefaults)!!).await()) } + rethrow { DocumentReference(addDoc(js, encode(strategy, data, encodeDefaults)!!).await()) } } actual class FirebaseFirestoreException(cause: Throwable, val code: FirestoreExceptionCode) : FirebaseException(code.toString(), cause) @@ -395,7 +425,7 @@ actual class FirebaseFirestoreException(cause: Throwable, val code: FirestoreExc @Suppress("EXTENSION_SHADOWED_BY_MEMBER") actual val FirebaseFirestoreException.code: FirestoreExceptionCode get() = code -actual class QuerySnapshot(val js: firebase.firestore.QuerySnapshot) { +actual class QuerySnapshot(val js: JsQuerySnapshot) { actual val documents get() = js.docs.map { DocumentSnapshot(it) } actual val documentChanges @@ -403,7 +433,7 @@ actual class QuerySnapshot(val js: firebase.firestore.QuerySnapshot) { actual val metadata: SnapshotMetadata get() = SnapshotMetadata(js.metadata) } -actual class DocumentChange(val js: firebase.firestore.DocumentChange) { +actual class DocumentChange(val js: JsDocumentChange) { actual val document: DocumentSnapshot get() = DocumentSnapshot(js.doc) actual val newIndex: Int @@ -414,7 +444,7 @@ actual class DocumentChange(val js: firebase.firestore.DocumentChange) { get() = ChangeType.values().first { it.jsString == js.type } } -actual class DocumentSnapshot(val js: firebase.firestore.DocumentSnapshot) { +actual class DocumentSnapshot(val js: JsDocumentSnapshot) { actual val id get() = rethrow { js.id } actual val reference get() = rethrow { DocumentReference(js.ref) } @@ -439,24 +469,24 @@ actual class DocumentSnapshot(val js: firebase.firestore.DocumentSnapshot) { json("serverTimestamps" to serverTimestampBehavior.name.lowercase()) } -actual class SnapshotMetadata(val js: firebase.firestore.SnapshotMetadata) { +actual class SnapshotMetadata(val js: JsSnapshotMetadata) { actual val hasPendingWrites: Boolean get() = js.hasPendingWrites actual val isFromCache: Boolean get() = js.fromCache } -actual class FieldPath private constructor(val js: firebase.firestore.FieldPath) { +actual class FieldPath private constructor(val js: JsFieldPath) { actual constructor(vararg fieldNames: String) : this(dev.gitlive.firebase.firestore.rethrow { - js("Reflect").construct(firebase.firestore.FieldPath, fieldNames).unsafeCast() + js("Reflect").construct(JsFieldPath, fieldNames).unsafeCast() }) - actual val documentId: FieldPath get() = FieldPath(firebase.firestore.FieldPath.documentId) + actual val documentId: FieldPath get() = FieldPath(JsFieldPath.documentId) } actual object FieldValue { - actual val serverTimestamp = Double.POSITIVE_INFINITY - actual val delete: Any get() = rethrow { firebase.firestore.FieldValue.delete() } - actual fun increment(value: Int): Any = rethrow { firebase.firestore.FieldValue.increment(value) } - actual fun arrayUnion(vararg elements: Any): Any = rethrow { firebase.firestore.FieldValue.arrayUnion(*elements) } - actual fun arrayRemove(vararg elements: Any): Any = rethrow { firebase.firestore.FieldValue.arrayRemove(*elements) } + actual val serverTimestamp: Any = serverTimestamp() + actual val delete: Any get() = rethrow { deleteField() } + actual fun increment(value: Int): Any = rethrow { jsIncrement(value) } + actual fun arrayUnion(vararg elements: Any): Any = rethrow { jsArrayUnion(*elements) } + actual fun arrayRemove(vararg elements: Any): Any = rethrow { jsArrayRemove(*elements) } @JsName("deprecatedDelete") actual fun delete(): Any = delete } From 9e4422ebcea4274381638615c325e491056de9c1 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Sun, 12 Jun 2022 19:32:59 +0300 Subject: [PATCH 04/28] Revert formatting --- .../kotlin/dev/gitlive/firebase/firebase.kt | 17 ++-- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 12 +-- .../dev/gitlive/firebase/database/database.kt | 79 ++++++------------- 3 files changed, 34 insertions(+), 74 deletions(-) diff --git a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt index 4e40e52fd..85dc7ac50 100644 --- a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt +++ b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt @@ -10,9 +10,11 @@ import dev.gitlive.firebase.externals.app.initializeApp import kotlin.js.json import dev.gitlive.firebase.externals.app.FirebaseApp as JsFirebaseApp -actual val Firebase.app: FirebaseApp get() = FirebaseApp(getApp()) +actual val Firebase.app: FirebaseApp +get() = FirebaseApp(getApp()) -actual fun Firebase.app(name: String): FirebaseApp = FirebaseApp(getApp(name)) +actual fun Firebase.app(name: String): FirebaseApp = + FirebaseApp(getApp(name)) actual fun Firebase.initialize(context: Any?): FirebaseApp? = throw UnsupportedOperationException("Cannot initialize firebase without options in JS") @@ -28,16 +30,7 @@ actual class FirebaseApp internal constructor(val js: JsFirebaseApp) { get() = js.name actual val options: FirebaseOptions get() = js.options.run { - FirebaseOptions( - js.options.appId, - js.options.apiKey, - js.options.databaseURL, - js.options.gaTrackingId, - js.options.storageBucket, - js.options.projectId, - js.options.messagingSenderId, - js.options.authDomain - ) + FirebaseOptions(appId, apiKey, databaseURL, gaTrackingId, storageBucket, projectId, messagingSenderId, authDomain) } } 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 95cd6de18..3cbc83caa 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 @@ -43,16 +43,12 @@ actual class FirebaseAuth internal constructor(val js: Auth) { set(value) { js.languageCode = value } actual suspend fun applyActionCode(code: String) = rethrow { applyActionCode(js, code).await() } - actual suspend fun confirmPasswordReset(code: String, newPassword: String) = rethrow { - confirmPasswordReset(js, code, newPassword).await() - } + actual suspend fun confirmPasswordReset(code: String, newPassword: String) = rethrow { confirmPasswordReset(js, code, newPassword).await() } actual suspend fun createUserWithEmailAndPassword(email: String, password: String) = rethrow { AuthResult(createUserWithEmailAndPassword(js, email, password).await()) } - actual suspend fun fetchSignInMethodsForEmail(email: String): List = rethrow { - fetchSignInMethodsForEmail(js, email).await().asList() - } + actual suspend fun fetchSignInMethodsForEmail(email: String): List = rethrow { fetchSignInMethodsForEmail(js, email).await().asList() } actual suspend fun sendPasswordResetEmail(email: String, actionCodeSettings: ActionCodeSettings?) = rethrow { sendPasswordResetEmail(js, email, actionCodeSettings?.toJson()).await() } @@ -105,9 +101,7 @@ actual class FirebaseAuth internal constructor(val js: Auth) { } as T } - actual fun useEmulator(host: String, port: Int) = rethrow { - connectAuthEmulator(js, "http://$host:$port") - } + actual fun useEmulator(host: String, port: Int) = rethrow { connectAuthEmulator(js, "http://$host:$port") } } actual class AuthResult internal constructor(val js: JsAuthResult) { diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt index 6748a7b6f..d86b9a2cd 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.selects.select import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationStrategy import kotlin.js.Promise +import kotlin.js.json import dev.gitlive.firebase.externals.database.DataSnapshot as JsDataSnapshot import dev.gitlive.firebase.externals.database.DatabaseReference as JsDatabaseReference import dev.gitlive.firebase.externals.database.OnDisconnect as JsOnDisconnect @@ -33,19 +34,18 @@ import dev.gitlive.firebase.externals.database.startAt as jsStartAt internal inline fun encode(value: T, shouldEncodeElementDefault: Boolean) = encode(value, shouldEncodeElementDefault, serverTimestamp()) -internal fun encode( - strategy: SerializationStrategy, - value: T, - shouldEncodeElementDefault: Boolean -): Any? = encode(strategy, value, shouldEncodeElementDefault, serverTimestamp()) +internal fun encode(strategy: SerializationStrategy, value: T, shouldEncodeElementDefault: Boolean): Any? = + encode(strategy, value, shouldEncodeElementDefault, serverTimestamp()) -actual val Firebase.database get() = rethrow { FirebaseDatabase(getDatabase()) } +actual val Firebase.database + get() = rethrow { FirebaseDatabase(getDatabase()) } actual fun Firebase.database(app: FirebaseApp) = rethrow { FirebaseDatabase(getDatabase(app = app.js)) } -actual fun Firebase.database(url: String) = rethrow { FirebaseDatabase(getDatabase(url = url)) } +actual fun Firebase.database(url: String) = + rethrow { FirebaseDatabase(getDatabase(url = url)) } actual fun Firebase.database(app: FirebaseApp, url: String) = rethrow { FirebaseDatabase(getDatabase(app = app.js, url = url)) } @@ -55,9 +55,7 @@ actual class FirebaseDatabase internal constructor(val js: Database) { actual fun reference() = rethrow { DatabaseReference(ref(js)) } actual fun setPersistenceEnabled(enabled: Boolean) {} actual fun setLoggingEnabled(enabled: Boolean) = rethrow { enableLogging(enabled) } - - actual fun useEmulator(host: String, port: Int) = - rethrow { connectDatabaseEmulator(js, host, port) } + actual fun useEmulator(host: String, port: Int) = rethrow { connectDatabaseEmulator(js, host, port) } } actual open class Query internal constructor(open val js: JsQuery) { @@ -79,7 +77,6 @@ actual open class Query internal constructor(open val js: JsQuery) { } actual fun childEvents(vararg types: ChildEvent.Type) = callbackFlow { - val unsubscribes = rethrow { types.map { type -> val callback: ChangeSnapshotCallback = { snapshot, previousChildName -> @@ -105,48 +102,36 @@ actual open class Query internal constructor(open val js: JsQuery) { } } - awaitClose { rethrow { unsubscribes.forEach { it.invoke() } } } } - actual fun startAt(value: String, key: String?) = - Query(query(js, jsStartAt(value, key ?: undefined))) + actual fun startAt(value: String, key: String?) = Query(query(js, jsStartAt(value, key ?: undefined))) - actual fun startAt(value: Double, key: String?) = - Query(query(js, jsStartAt(value, key ?: undefined))) + actual fun startAt(value: Double, key: String?) = Query(query(js, jsStartAt(value, key ?: undefined))) - actual fun startAt(value: Boolean, key: String?) = - Query(query(js, jsStartAt(value, key ?: undefined))) + actual fun startAt(value: Boolean, key: String?) = Query(query(js, jsStartAt(value, key ?: undefined))) - actual fun endAt(value: String, key: String?) = - Query(query(js, jsEndAt(value, key ?: undefined))) + actual fun endAt(value: String, key: String?) = Query(query(js, jsEndAt(value, key ?: undefined))) - actual fun endAt(value: Double, key: String?) = - Query(query(js, jsEndAt(value, key ?: undefined))) + actual fun endAt(value: Double, key: String?) = Query(query(js, jsEndAt(value, key ?: undefined))) - actual fun endAt(value: Boolean, key: String?) = - Query(query(js, jsEndAt(value, key ?: undefined))) + actual fun endAt(value: Boolean, key: String?) = Query(query(js, jsEndAt(value, key ?: undefined))) actual fun limitToFirst(limit: Int) = Query(query(js, jsLimitToFirst(limit))) actual fun limitToLast(limit: Int) = Query(query(js, jsLimitToLast(limit))) - actual fun equalTo(value: String, key: String?) = - Query(query(js, jsEqualTo(value, key ?: undefined))) + actual fun equalTo(value: String, key: String?) = Query(query(js, jsEqualTo(value, key ?: undefined))) - actual fun equalTo(value: Double, key: String?) = - Query(query(js, jsEqualTo(value, key ?: undefined))) + actual fun equalTo(value: Double, key: String?) = Query(query(js, jsEqualTo(value, key ?: undefined))) - actual fun equalTo(value: Boolean, key: String?) = - Query(query(js, jsEqualTo(value, key ?: undefined))) + actual fun equalTo(value: Boolean, key: String?) = Query(query(js, jsEqualTo(value, key ?: undefined))) override fun toString() = js.toString() } -actual class DatabaseReference internal constructor( - override val js: JsDatabaseReference -) : Query(js) { +actual class DatabaseReference internal constructor(override val js: JsDatabaseReference) : Query(js) { actual val key get() = rethrow { js.key } actual fun push() = rethrow { DatabaseReference(push(js)) } @@ -155,7 +140,7 @@ actual class DatabaseReference internal constructor( actual fun onDisconnect() = rethrow { OnDisconnect(onDisconnect(js)) } actual suspend fun updateChildren(update: Map, encodeDefaults: Boolean) = - rethrow { update(js, encode(update, encodeDefaults)!!).awaitWhileOnline() } + rethrow { update(js, encode(update, encodeDefaults) ?: json()).awaitWhileOnline() } actual suspend fun removeValue() = rethrow { remove(js).awaitWhileOnline() } @@ -163,11 +148,8 @@ actual class DatabaseReference internal constructor( set(js, encode(value, encodeDefaults)).awaitWhileOnline() } - actual suspend fun setValue( - strategy: SerializationStrategy, - value: T, - encodeDefaults: Boolean - ) = rethrow { set(js, encode(strategy, value, encodeDefaults)).awaitWhileOnline() } + actual suspend fun setValue(strategy: SerializationStrategy, value: T, encodeDefaults: Boolean) = + rethrow { set(js, encode(strategy, value, encodeDefaults)).awaitWhileOnline() } } actual class DataSnapshot internal constructor(val js: JsDataSnapshot) { @@ -196,29 +178,20 @@ actual class OnDisconnect internal constructor(val js: JsOnDisconnect) { actual suspend fun cancel() = rethrow { js.cancel().awaitWhileOnline() } actual suspend fun updateChildren(update: Map, encodeDefaults: Boolean) = - rethrow { js.update(encode(update, encodeDefaults)!!).awaitWhileOnline() } + rethrow { js.update(encode(update, encodeDefaults) ?: json()).awaitWhileOnline() } actual suspend inline fun setValue(value: T, encodeDefaults: Boolean) = rethrow { js.set(encode(value, encodeDefaults)).awaitWhileOnline() } - actual suspend fun setValue( - strategy: SerializationStrategy, - value: T, - encodeDefaults: Boolean - ) = + actual suspend fun setValue(strategy: SerializationStrategy, value: T, encodeDefaults: Boolean) = rethrow { js.set(encode(strategy, value, encodeDefaults)).awaitWhileOnline() } } -actual class DatabaseException actual constructor(message: String?, cause: Throwable?) : - RuntimeException(message, cause) { - constructor(error: dynamic) : this( - "${error.code ?: "UNKNOWN"}: ${error.message}", - error.unsafeCast() - ) +actual class DatabaseException actual constructor(message: String?, cause: Throwable?) : RuntimeException(message, cause) { + constructor(error: dynamic) : this("${error.code ?: "UNKNOWN"}: ${error.message}", error.unsafeCast()) } -inline fun T.rethrow(function: T.() -> R): R = - dev.gitlive.firebase.database.rethrow { function() } +inline fun T.rethrow(function: T.() -> R): R = dev.gitlive.firebase.database.rethrow { function() } inline fun rethrow(function: () -> R): R { try { From bd371edddf98cc31f11a1302f0c4c5f31aaae59b Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Sun, 12 Jun 2022 19:45:02 +0300 Subject: [PATCH 05/28] Revert formatting --- .../kotlin/dev/gitlive/firebase/firebase.kt | 2 +- .../dev/gitlive/firebase/auth/credentials.kt | 23 +++--------- .../dev/gitlive/firebase/auth/multifactor.kt | 8 +---- .../kotlin/dev/gitlive/firebase/auth/user.kt | 36 +++++-------------- .../dev/gitlive/firebase/database/database.kt | 1 - 5 files changed, 16 insertions(+), 54 deletions(-) diff --git a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt index 85dc7ac50..ac8c42698 100644 --- a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt +++ b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt @@ -11,7 +11,7 @@ import kotlin.js.json import dev.gitlive.firebase.externals.app.FirebaseApp as JsFirebaseApp actual val Firebase.app: FirebaseApp -get() = FirebaseApp(getApp()) + get() = FirebaseApp(getApp()) actual fun Firebase.app(name: String): FirebaseApp = FirebaseApp(getApp(name)) diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 9b719a716..9715b567b 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -62,14 +62,8 @@ actual class OAuthProvider(val js: JsOAuthProvider) { js.setCustomParameters(customParameters) } } - actual companion object { - actual fun credential( - providerId: String, - accessToken: String?, - idToken: String?, - rawNonce: String? - ): OAuthCredential = rethrow { + actual fun credential(providerId: String, accessToken: String?, idToken: String?, rawNonce: String?): OAuthCredential = rethrow { JsOAuthProvider(providerId) .credential( json( @@ -88,15 +82,9 @@ actual class PhoneAuthProvider(val js: PhoneAuthProvider) { actual constructor(auth: FirebaseAuth) : this(PhoneAuthProvider(auth.js)) - actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = - PhoneAuthCredential(PhoneAuthProvider.credential(verificationId, smsCode)) - - actual suspend fun verifyPhoneNumber( - phoneNumber: String, - verificationProvider: PhoneVerificationProvider - ): AuthCredential = rethrow { - val verificationId = - js.verifyPhoneNumber(phoneNumber, verificationProvider.verifier).await() + actual fun credential(verificationId: String, smsCode: String): PhoneAuthCredential = PhoneAuthCredential(PhoneAuthProvider.credential(verificationId, smsCode)) + actual suspend fun verifyPhoneNumber(phoneNumber: String, verificationProvider: PhoneVerificationProvider): AuthCredential = rethrow { + val verificationId = js.verifyPhoneNumber(phoneNumber, verificationProvider.verifier).await() val verificationCode = verificationProvider.getVerificationCode(verificationId) credential(verificationId, verificationCode) } @@ -108,6 +96,5 @@ actual interface PhoneVerificationProvider { } actual object TwitterAuthProvider { - actual fun credential(token: String, secret: String): AuthCredential = - AuthCredential(TwitterAuthProvider.credential(token, secret)) + actual fun credential(token: String, secret: String): AuthCredential = AuthCredential(TwitterAuthProvider.credential(token, secret)) } diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index 45b1291d5..703ab09c0 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -11,16 +11,12 @@ import dev.gitlive.firebase.externals.auth.MultiFactorSession as JsMultiFactorSe actual class MultiFactor(val js: MultiFactorUser) { actual val enrolledFactors: List get() = rethrow { js.enrolledFactors.map { MultiFactorInfo(it) } } - actual suspend fun enroll(multiFactorAssertion: MultiFactorAssertion, displayName: String?) = rethrow { js.enroll(multiFactorAssertion.js, displayName).await() } - actual suspend fun getSession(): MultiFactorSession = rethrow { MultiFactorSession(js.getSession().await()) } - actual suspend fun unenroll(multiFactorInfo: MultiFactorInfo) = rethrow { js.unenroll(multiFactorInfo.js).await() } - actual suspend fun unenroll(factorUid: String) = rethrow { js.unenroll(factorUid).await() } } @@ -48,7 +44,5 @@ actual class MultiFactorResolver(val js: JsMultiFactorResolver) { actual val hints: List = rethrow { js.hints.map { MultiFactorInfo(it) } } actual val session: MultiFactorSession = rethrow { MultiFactorSession(js.session) } - actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = rethrow { - AuthResult(js.resolveSignIn(assertion.js).await()) - } + actual suspend fun resolveSignIn(assertion: MultiFactorAssertion): AuthResult = rethrow { AuthResult(js.resolveSignIn(assertion.js).await()) } } diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt index 38bf58322..9432ae9f5 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -30,35 +30,20 @@ actual class FirebaseUser internal constructor(val js: User) { get() = rethrow { js.providerId } actual suspend fun delete() = rethrow { js.delete().await() } actual suspend fun reload() = rethrow { js.reload().await() } - actual suspend fun getIdToken(forceRefresh: Boolean): String? = rethrow { - js.getIdToken(forceRefresh).await() - } - actual suspend fun getIdTokenResult(forceRefresh: Boolean): AuthTokenResult = rethrow { - AuthTokenResult(getIdTokenResult(js, forceRefresh).await()) - } - actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = rethrow { - AuthResult( linkWithCredential(js, credential.js).await()) - } + actual suspend fun getIdToken(forceRefresh: Boolean): String? = rethrow { js.getIdToken(forceRefresh).await() } + actual suspend fun getIdTokenResult(forceRefresh: Boolean): AuthTokenResult = rethrow { AuthTokenResult(getIdTokenResult(js, forceRefresh).await()) } + actual suspend fun linkWithCredential(credential: AuthCredential): AuthResult = rethrow { AuthResult( linkWithCredential(js, credential.js).await()) } actual suspend fun reauthenticate(credential: AuthCredential) = rethrow { reauthenticateWithCredential(js, credential.js).await() Unit } - actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = - rethrow { AuthResult(reauthenticateWithCredential(js, credential.js).await()) } + actual suspend fun reauthenticateAndRetrieveData(credential: AuthCredential): AuthResult = rethrow { AuthResult(reauthenticateWithCredential(js, credential.js).await()) } - actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = rethrow { - sendEmailVerification(js, actionCodeSettings?.toJson()).await() - } - actual suspend fun unlink(provider: String): FirebaseUser? = rethrow { - FirebaseUser(unlink(js, provider).await()) - } + actual suspend fun sendEmailVerification(actionCodeSettings: ActionCodeSettings?) = rethrow { sendEmailVerification(js, actionCodeSettings?.toJson()).await() } + actual suspend fun unlink(provider: String): FirebaseUser? = rethrow { FirebaseUser(unlink(js, provider).await()) } actual suspend fun updateEmail(email: String) = rethrow { updateEmail(js, email).await() } - actual suspend fun updatePassword(password: String) = rethrow { - updatePassword(js, password).await() - } - actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = rethrow { - updatePhoneNumber(js, credential.js).await() - } + actual suspend fun updatePassword(password: String) = rethrow { updatePassword(js, password).await() } + actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = rethrow { updatePhoneNumber(js, credential.js).await() } actual suspend fun updateProfile(displayName: String?, photoUrl: String?) = rethrow { val request = object : ProfileUpdateRequest { override val displayName: String? = displayName @@ -66,10 +51,7 @@ actual class FirebaseUser internal constructor(val js: User) { } updateProfile(js, request).await() } - actual suspend fun verifyBeforeUpdateEmail( - newEmail: String, - actionCodeSettings: ActionCodeSettings? - ) = rethrow { verifyBeforeUpdateEmail(js, newEmail, actionCodeSettings?.toJson()).await() } + actual suspend fun verifyBeforeUpdateEmail(newEmail: String, actionCodeSettings: ActionCodeSettings?) = rethrow { verifyBeforeUpdateEmail(js, newEmail, actionCodeSettings?.toJson()).await() } } actual class UserInfo(val js: JsUserInfo) { diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt index d86b9a2cd..56b481d57 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -99,7 +99,6 @@ actual open class Query internal constructor(open val js: JsQuery) { ChildEvent.Type.MOVED -> onChildMoved(js, callback, cancelCallback) ChildEvent.Type.REMOVED -> onChildRemoved(js, callback, cancelCallback) } - } } awaitClose { rethrow { unsubscribes.forEach { it.invoke() } } } From 6d3b904cd352f1bd477649fd78c8a96570f814a5 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Mon, 13 Jun 2022 10:24:45 +0300 Subject: [PATCH 06/28] Refactor remote config --- .../kotlin/dev/gitlive/firebase/externals.kt | 32 ------------- .../externals/remoteconfig/remoteconfig.kt | 47 +++++++++++++++++++ .../kotlin/dev/gitlive/firebase/externals2.kt | 4 -- .../remoteconfig/FirebaseRemoteConfig.kt | 28 +++++------ .../remoteconfig/FirebaseRemoteConfigValue.kt | 4 +- 5 files changed, 61 insertions(+), 54 deletions(-) create mode 100644 firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/remoteconfig/remoteconfig.kt diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt index f5f519517..713d20ff0 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt @@ -40,38 +40,6 @@ external object firebase { } - fun remoteConfig(app: App? = definedExternally): remoteConfig.RemoteConfig - - object remoteConfig { - interface RemoteConfig { - var defaultConfig: Any - var fetchTimeMillis: Long - var lastFetchStatus: String - val settings: Settings - fun activate(): Promise - fun ensureInitialized(): Promise - fun fetch(): Promise - fun fetchAndActivate(): Promise - fun getAll(): Json - fun getBoolean(key: String): Boolean - fun getNumber(key: String): Number - fun getString(key: String): String? - fun getValue(key: String): Value - } - - interface Settings { - var fetchTimeoutMillis: Number - var minimumFetchIntervalMillis: Number - } - - interface Value { - fun asBoolean(): Boolean - fun asNumber(): Number - fun asString(): String? - fun getSource(): String - } - } - fun installations(app: App? = definedExternally): installations.Installations object installations { diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/remoteconfig/remoteconfig.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/remoteconfig/remoteconfig.kt new file mode 100644 index 000000000..7ab94aded --- /dev/null +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/remoteconfig/remoteconfig.kt @@ -0,0 +1,47 @@ +@file:JsModule("firebase/remote-config") +@file:JsNonModule + +package dev.gitlive.firebase.externals.remoteconfig + +import dev.gitlive.firebase.externals.app.FirebaseApp +import kotlin.js.Json +import kotlin.js.Promise + +external fun activate(remoteConfig: RemoteConfig): Promise + +external fun ensureInitialized(remoteConfig: RemoteConfig): Promise + +external fun fetchAndActivate(remoteConfig: RemoteConfig): Promise + +external fun fetchConfig(remoteConfig: RemoteConfig): Promise + +external fun getAll(remoteConfig: RemoteConfig): Json + +external fun getBoolean(remoteConfig: RemoteConfig, key: String): Boolean + +external fun getNumber(remoteConfig: RemoteConfig, key: String): Number + +external fun getRemoteConfig(app: FirebaseApp? = definedExternally): RemoteConfig + +external fun getString(remoteConfig: RemoteConfig, key: String): String? + +external fun getValue(remoteConfig: RemoteConfig, key: String): Value + +external interface RemoteConfig { + var defaultConfig: Any + var fetchTimeMillis: Long + var lastFetchStatus: String + val settings: Settings +} + +external interface Settings { + var fetchTimeoutMillis: Number + var minimumFetchIntervalMillis: Number +} + +external interface Value { + fun asBoolean(): Boolean + fun asNumber(): Number + fun asString(): String? + fun getSource(): String +} diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt index da22b5fd9..6ccd6a536 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt @@ -13,10 +13,6 @@ external object functions external object installations -@JsModule("firebase/compat/remote-config") -@JsName("default") -external object remoteConfig - typealias ChangeSnapshotCallback = (data: DataSnapshot, previousChildName: String?) -> Unit typealias ValueSnapshotCallback = (data: DataSnapshot) -> Unit typealias CancelCallback = (error: Throwable) -> Unit diff --git a/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt b/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt index b1b19825f..ad40e8837 100644 --- a/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt +++ b/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt @@ -3,44 +3,40 @@ package dev.gitlive.firebase.remoteconfig import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseApp import dev.gitlive.firebase.FirebaseException -import dev.gitlive.firebase.firebase +import dev.gitlive.firebase.externals.remoteconfig.* import kotlinx.coroutines.await import kotlin.js.json actual val Firebase.remoteConfig: FirebaseRemoteConfig - get() = rethrow { - dev.gitlive.firebase.remoteConfig - FirebaseRemoteConfig(firebase.remoteConfig()) - } + get() = rethrow { FirebaseRemoteConfig(getRemoteConfig()) } actual fun Firebase.remoteConfig(app: FirebaseApp): FirebaseRemoteConfig = rethrow { - dev.gitlive.firebase.remoteConfig - FirebaseRemoteConfig(firebase.remoteConfig(app.js)) + FirebaseRemoteConfig(getRemoteConfig(app.js)) } -actual class FirebaseRemoteConfig internal constructor(val js: firebase.remoteConfig.RemoteConfig) { +actual class FirebaseRemoteConfig internal constructor(val js: RemoteConfig) { actual val all: Map get() = rethrow { getAllKeys().map { Pair(it, getValue(it)) }.toMap() } actual val info: FirebaseRemoteConfigInfo get() = rethrow { FirebaseRemoteConfigInfo( - configSettings = js.settings.toSettings(), + configSettings = js.settings.toFirebaseRemoteConfigSettings(), fetchTimeMillis = js.fetchTimeMillis, lastFetchStatus = js.lastFetchStatus.toFetchStatus() ) } - actual suspend fun activate(): Boolean = rethrow { js.activate().await() } - actual suspend fun ensureInitialized(): Unit = rethrow { js.activate().await() } + actual suspend fun activate(): Boolean = rethrow { activate(js).await() } + actual suspend fun ensureInitialized(): Unit = rethrow { ensureInitialized(js).await() } actual suspend fun fetch(minimumFetchIntervalInSeconds: Long?): Unit = - rethrow { js.fetch().await() } + rethrow { fetchConfig(js).await() } - actual suspend fun fetchAndActivate(): Boolean = rethrow { js.fetchAndActivate().await() } + actual suspend fun fetchAndActivate(): Boolean = rethrow { fetchAndActivate(js).await() } actual fun getValue(key: String): FirebaseRemoteConfigValue = rethrow { - FirebaseRemoteConfigValue(js.getValue(key)) + FirebaseRemoteConfigValue(getValue(js, key)) } actual fun getKeysByPrefix(prefix: String): Set { @@ -49,7 +45,7 @@ actual class FirebaseRemoteConfig internal constructor(val js: firebase.remoteCo private fun getAllKeys(): Set { val objectKeys = js("Object.keys") - return objectKeys(js.getAll()).unsafeCast>().toSet() + return objectKeys(getAll(js)).unsafeCast>().toSet() } actual suspend fun reset() { @@ -68,7 +64,7 @@ actual class FirebaseRemoteConfig internal constructor(val js: firebase.remoteCo js.defaultConfig = json(*defaults) } - private fun firebase.remoteConfig.Settings.toSettings(): FirebaseRemoteConfigSettings { + private fun Settings.toFirebaseRemoteConfigSettings(): FirebaseRemoteConfigSettings { return FirebaseRemoteConfigSettings( fetchTimeoutInSeconds = fetchTimeoutMillis.toLong() / 1000, minimumFetchIntervalInSeconds = minimumFetchIntervalMillis.toLong() / 1000 diff --git a/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfigValue.kt b/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfigValue.kt index 7465ff24d..0062a787e 100644 --- a/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfigValue.kt +++ b/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfigValue.kt @@ -1,8 +1,8 @@ package dev.gitlive.firebase.remoteconfig -import dev.gitlive.firebase.firebase +import dev.gitlive.firebase.externals.remoteconfig.Value -actual class FirebaseRemoteConfigValue(val js: firebase.remoteConfig.Value) { +actual class FirebaseRemoteConfigValue(val js: Value) { actual fun asBoolean(): Boolean = rethrow { js.asBoolean() } actual fun asByteArray(): ByteArray = rethrow { js.asString()?.encodeToByteArray() ?: byteArrayOf() } actual fun asDouble(): Double = rethrow { js.asNumber().toDouble() } From 99bceab3eab90ffaefdbee7b90685a8c8657eba1 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Mon, 13 Jun 2022 11:23:39 +0300 Subject: [PATCH 07/28] Refactor functions --- .../kotlin/dev/gitlive/firebase/externals.kt | 19 -------------- .../firebase/externals/functions/functions.kt | 24 +++++++++++++++++ .../kotlin/dev/gitlive/firebase/externals2.kt | 6 +++-- .../gitlive/firebase/functions/functions.kt | 3 +-- .../gitlive/firebase/functions/functions.kt | 26 ++++++++++++------- 5 files changed, 45 insertions(+), 33 deletions(-) create mode 100644 firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/functions.kt diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt index 713d20ff0..dd0b662ca 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt @@ -13,33 +13,14 @@ import kotlin.js.Promise external object firebase { open class App { - fun functions(region: String? = definedExternally): functions.Functions } - fun app(name: String? = definedExternally): App - interface FirebaseError { var code: String var message: String var name: String } - fun functions(app: App? = definedExternally): functions.Functions - - object functions { - class Functions { - fun httpsCallable(name: String, options: Json?): HttpsCallable - fun useFunctionsEmulator(origin: String) - fun useEmulator(host: String, port: Int) - } - interface HttpsCallableResult { - val data: Any? - } - interface HttpsCallable { - } - - } - fun installations(app: App? = definedExternally): installations.Installations object installations { diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/functions.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/functions.kt new file mode 100644 index 000000000..aee2a562f --- /dev/null +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/functions.kt @@ -0,0 +1,24 @@ +@file:JsModule("firebase/functions") +@file:JsNonModule + +package dev.gitlive.firebase.externals.functions + +import dev.gitlive.firebase.externals.app.FirebaseApp +import kotlin.js.Json + +external fun connectFunctionsEmulator(functions: Functions, host: String, port: Int) + +external fun getFunctions( + app: FirebaseApp? = definedExternally, + regionOrCustomDomain: String? = definedExternally +): Functions + +external fun httpsCallable(functions: Functions, name: String, options: Json?): HttpsCallable + +external interface Functions + +external interface HttpsCallableResult { + val data: Any? +} + +external interface HttpsCallable diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt index 6ccd6a536..a0e49a189 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt @@ -5,6 +5,8 @@ package dev.gitlive.firebase import dev.gitlive.firebase.externals.database.DataSnapshot +import dev.gitlive.firebase.externals.functions.HttpsCallable +import dev.gitlive.firebase.externals.functions.HttpsCallableResult import kotlin.js.Promise @JsModule("firebase/compat/functions") @@ -18,5 +20,5 @@ typealias ValueSnapshotCallback = (data: DataSnapshot) -> Unit typealias CancelCallback = (error: Throwable) -> Unit typealias Unsubscribe = () -> Unit -operator fun firebase.functions.HttpsCallable.invoke() = asDynamic()() as Promise -operator fun firebase.functions.HttpsCallable.invoke(data: Any?) = asDynamic()(data) as Promise +operator fun HttpsCallable.invoke() = asDynamic()() as Promise +operator fun HttpsCallable.invoke(data: Any?) = asDynamic()(data) as Promise diff --git a/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt b/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt index 9a35adbee..c80eed916 100644 --- a/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt +++ b/firebase-functions/src/commonMain/kotlin/dev/gitlive/firebase/functions/functions.kt @@ -14,7 +14,7 @@ expect class FirebaseFunctions { fun httpsCallable(name: String, timeout: Long? = null): HttpsCallableReference fun useEmulator(host: String, port: Int) - @Deprecated("Use useEmulator(java.lang.String,int) to connect to the emulator.") + @Deprecated("Use useEmulator(java.lang.String,int) to connect to the emulator.", level = DeprecationLevel.ERROR) fun useFunctionsEmulator(origin: String) } @@ -42,4 +42,3 @@ expect fun Firebase.functions(app: FirebaseApp): FirebaseFunctions expect fun Firebase.functions(app: FirebaseApp, region: String): FirebaseFunctions expect class FirebaseFunctionsException: FirebaseException - diff --git a/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt b/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt index b0b39bbd1..f8bd3802c 100644 --- a/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt +++ b/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt @@ -5,34 +5,40 @@ package dev.gitlive.firebase.functions import dev.gitlive.firebase.* +import dev.gitlive.firebase.externals.functions.* import kotlinx.coroutines.await import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationStrategy +import org.w3c.dom.url.URL import kotlin.js.json +import dev.gitlive.firebase.externals.functions.HttpsCallableResult as JsHttpsCallableResult actual val Firebase.functions: FirebaseFunctions - get() = rethrow { dev.gitlive.firebase.functions; FirebaseFunctions(firebase.functions()) } + get() = rethrow { FirebaseFunctions(getFunctions()) } actual fun Firebase.functions(region: String) = - rethrow { dev.gitlive.firebase.functions; FirebaseFunctions(firebase.app().functions(region)) } + rethrow { FirebaseFunctions(getFunctions(regionOrCustomDomain = region)) } actual fun Firebase.functions(app: FirebaseApp) = - rethrow { dev.gitlive.firebase.functions; FirebaseFunctions(firebase.functions(app.js)) } + rethrow { FirebaseFunctions(getFunctions(app.js)) } actual fun Firebase.functions(app: FirebaseApp, region: String) = - rethrow { dev.gitlive.firebase.functions; FirebaseFunctions(app.js.functions(region)) } + rethrow { FirebaseFunctions(getFunctions(app.js, region)) } -actual class FirebaseFunctions internal constructor(val js: firebase.functions.Functions) { +actual class FirebaseFunctions internal constructor(val js: Functions) { actual fun httpsCallable(name: String, timeout: Long?) = - rethrow { HttpsCallableReference(js.httpsCallable(name, timeout?.let { json("timeout" to timeout.toDouble()) })) } + rethrow { HttpsCallableReference(httpsCallable(js, name, timeout?.let { json("timeout" to timeout.toDouble()) })) } - actual fun useFunctionsEmulator(origin: String) = js.useFunctionsEmulator(origin) + actual fun useFunctionsEmulator(origin: String) { + val url = URL(origin) + useEmulator(url.host, url.port.toInt()) + } - actual fun useEmulator(host: String, port: Int) = js.useEmulator(host, port) + actual fun useEmulator(host: String, port: Int) = connectFunctionsEmulator(js, host, port) } @Suppress("UNCHECKED_CAST") -actual class HttpsCallableReference internal constructor(val js: firebase.functions.HttpsCallable) { +actual class HttpsCallableReference internal constructor(val js: HttpsCallable) { actual suspend operator fun invoke() = rethrow { HttpsCallableResult(js().await()) } @@ -44,7 +50,7 @@ actual class HttpsCallableReference internal constructor(val js: firebase.functi rethrow { HttpsCallableResult(js(encode(strategy, data, encodeDefaults)).await()) } } -actual class HttpsCallableResult constructor(val js: firebase.functions.HttpsCallableResult) { +actual class HttpsCallableResult constructor(val js: JsHttpsCallableResult) { actual inline fun data() = rethrow { decode(value = js.data) } From 322d629ef291501073ab00182c532c5889ea0c8b Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Mon, 13 Jun 2022 11:49:15 +0300 Subject: [PATCH 08/28] Refactor installations --- .../kotlin/dev/gitlive/firebase/externals.kt | 33 +++++-------------- .../externals/installations/installations.kt | 17 ++++++++++ .../kotlin/dev/gitlive/firebase/externals2.kt | 24 -------------- .../firebase/installations/installations.kt | 19 ++++------- 4 files changed, 33 insertions(+), 60 deletions(-) create mode 100644 firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/installations/installations.kt delete mode 100644 firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt index dd0b662ca..2ae7e44a4 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt @@ -2,32 +2,17 @@ * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. */ -@file:JsModule("firebase/compat/app") - package dev.gitlive.firebase -import kotlin.js.Json +import dev.gitlive.firebase.externals.database.DataSnapshot +import dev.gitlive.firebase.externals.functions.HttpsCallable +import dev.gitlive.firebase.externals.functions.HttpsCallableResult import kotlin.js.Promise -@JsName("default") -external object firebase { - - open class App { - } - - interface FirebaseError { - var code: String - var message: String - var name: String - } - - fun installations(app: App? = definedExternally): installations.Installations +typealias ChangeSnapshotCallback = (data: DataSnapshot, previousChildName: String?) -> Unit +typealias ValueSnapshotCallback = (data: DataSnapshot) -> Unit +typealias CancelCallback = (error: Throwable) -> Unit +typealias Unsubscribe = () -> Unit - object installations { - interface Installations { - fun delete(): Promise - fun getId(): Promise - fun getToken(forceRefresh: Boolean): Promise - } - } -} +operator fun HttpsCallable.invoke() = asDynamic()() as Promise +operator fun HttpsCallable.invoke(data: Any?) = asDynamic()(data) as Promise diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/installations/installations.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/installations/installations.kt new file mode 100644 index 000000000..81b05c52a --- /dev/null +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/installations/installations.kt @@ -0,0 +1,17 @@ +@file:JsModule("firebase/installations") +@file:JsNonModule + +package dev.gitlive.firebase.externals.installations + +import dev.gitlive.firebase.externals.app.FirebaseApp +import kotlin.js.Promise + +external fun delete(installations: Installations): Promise + +external fun getId(installations: Installations): Promise + +external fun getInstallations(app: FirebaseApp? = definedExternally): Installations + +external fun getToken(installations: Installations, forceRefresh: Boolean): Promise + +external interface Installations diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt deleted file mode 100644 index a0e49a189..000000000 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals2.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.gitlive.firebase - -import dev.gitlive.firebase.externals.database.DataSnapshot -import dev.gitlive.firebase.externals.functions.HttpsCallable -import dev.gitlive.firebase.externals.functions.HttpsCallableResult -import kotlin.js.Promise - -@JsModule("firebase/compat/functions") -@JsName("default") -external object functions - -external object installations - -typealias ChangeSnapshotCallback = (data: DataSnapshot, previousChildName: String?) -> Unit -typealias ValueSnapshotCallback = (data: DataSnapshot) -> Unit -typealias CancelCallback = (error: Throwable) -> Unit -typealias Unsubscribe = () -> Unit - -operator fun HttpsCallable.invoke() = asDynamic()() as Promise -operator fun HttpsCallable.invoke(data: Any?) = asDynamic()(data) as Promise diff --git a/firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/installations.kt b/firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/installations.kt index 0f33b3ac1..4668ccf2d 100644 --- a/firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/installations.kt +++ b/firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/installations.kt @@ -1,28 +1,23 @@ package dev.gitlive.firebase.installations import dev.gitlive.firebase.* +import dev.gitlive.firebase.externals.installations.* import kotlinx.coroutines.await actual val Firebase.installations - get() = rethrow { - dev.gitlive.firebase.installations - FirebaseInstallations(firebase.installations()) - } + get() = rethrow { FirebaseInstallations(getInstallations()) } actual fun Firebase.installations(app: FirebaseApp) = - rethrow { - dev.gitlive.firebase.installations - FirebaseInstallations(firebase.installations(app.js)) - } + rethrow { FirebaseInstallations(getInstallations(app.js)) } -actual class FirebaseInstallations internal constructor(val js: firebase.installations.Installations) { +actual class FirebaseInstallations internal constructor(val js: Installations) { - actual suspend fun delete() = rethrow { js.delete().await() } + actual suspend fun delete() = rethrow { delete(js).await() } - actual suspend fun getId(): String = rethrow { js.getId().await() } + actual suspend fun getId(): String = rethrow { getId(js).await() } actual suspend fun getToken(forceRefresh: Boolean): String = - rethrow { js.getToken(forceRefresh).await() } + rethrow { getToken(js, forceRefresh).await() } } actual open class FirebaseInstallationsException(code: String?, cause: Throwable): FirebaseException(code, cause) From 17e4ef3629016ed14c6187e8dd466a4c018ad8b7 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Mon, 13 Jun 2022 12:54:34 +0300 Subject: [PATCH 09/28] Fix firestore tests --- .../kotlin/dev/gitlive/firebase/externals/app/app.kt | 2 +- .../gitlive/firebase/externals/firestore/firestore.kt | 10 +++++----- .../kotlin/dev/gitlive/firebase/firestore/firestore.kt | 2 +- .../kotlin/dev/gitlive/firebase/firestore/firestore.kt | 2 +- .../kotlin/dev/gitlive/firebase/firestore/firestore.kt | 4 ++-- .../kotlin/dev/gitlive/firebase/firestore/firestore.kt | 2 +- .../kotlin/dev/gitlive/firebase/firestore/firestore.kt | 10 +++++----- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt index 161e5ebfd..4ca8a0c55 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt @@ -7,7 +7,7 @@ external fun initializeApp(options: Any, name: String = definedExternally): Fire external fun getApp(name: String = definedExternally): FirebaseApp -external fun getApps(): List +external fun getApps(): Array external interface FirebaseApp { val automaticDataCollectionEnabled: Boolean diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore/firestore.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore/firestore.kt index 1546142f9..593c5a630 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore/firestore.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore/firestore.kt @@ -66,7 +66,7 @@ external fun getDoc( options: Any? = definedExternally ): Promise -external fun get(query: Query): Promise +external fun getDocs(query: Query): Promise external fun getFirestore(app: FirebaseApp? = definedExternally): Firestore @@ -125,16 +125,16 @@ external fun startAt(document: DocumentSnapshot): QueryConstraint external fun startAt(vararg fieldValues: Any): QueryConstraint -external fun update(reference: DocumentReference, data: Any): Promise +external fun updateDoc(reference: DocumentReference, data: Any): Promise -external fun update( +external fun updateDoc( reference: DocumentReference, field: String, value: Any?, vararg moreFieldsAndValues: Any? ): Promise -external fun update( +external fun updateDoc( reference: DocumentReference, field: FieldPath, value: Any?, @@ -173,9 +173,9 @@ external interface DocumentReference { external interface DocumentSnapshot { val id: String val ref: DocumentReference - val exists: Boolean val metadata: SnapshotMetadata fun data(options: Any? = definedExternally): Any? + fun exists(): Boolean fun get(fieldPath: String, options: Any? = definedExternally): Any? fun get(fieldPath: FieldPath, options: Any? = definedExternally): Any? } diff --git a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index 8158188a2..95dcf09f1 100644 --- a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -471,7 +471,7 @@ actual class FieldPath private constructor(val android: com.google.firebase.fire } actual object FieldValue { - actual val serverTimestamp: Any = Double.POSITIVE_INFINITY + actual val serverTimestamp: Double = Double.POSITIVE_INFINITY actual val delete: Any get() = FieldValue.delete() actual fun increment(value: Int): Any = FieldValue.increment(value.toDouble()) actual fun arrayUnion(vararg elements: Any): Any = FieldValue.arrayUnion(*elements) 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 9e2352592..410e23b71 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 @@ -241,7 +241,7 @@ expect class FieldPath(vararg fieldNames: String) { } expect object FieldValue { - val serverTimestamp: Any + val serverTimestamp: Double val delete: Any fun increment(value: Int): Any fun arrayUnion(vararg elements: Any): Any 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 4acb10308..584a40cc5 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 @@ -32,9 +32,9 @@ class FirebaseFirestoreTest { @Serializable data class FirestoreTest( - val prop1: String, + val prop1: String, val time: Double = 0.0, - val count: Int = 0, + val count: Int = 0, val list: List = emptyList(), ) diff --git a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index cf2b504a3..4fceec61b 100644 --- a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -444,7 +444,7 @@ actual class FieldPath private constructor(val ios: FIRFieldPath) { } actual object FieldValue { - actual val serverTimestamp: Any = Double.POSITIVE_INFINITY + actual val serverTimestamp: Double = Double.POSITIVE_INFINITY actual val delete: Any get() = FIRFieldValue.fieldValueForDelete() actual fun increment(value: Int): Any = FIRFieldValue.fieldValueForIntegerIncrement(value.toLong()) actual fun arrayUnion(vararg elements: Any): Any = FIRFieldValue.fieldValueForArrayUnion(elements.asList()) diff --git a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index 05544ef13..f6df7e1b8 100644 --- a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -29,7 +29,7 @@ import dev.gitlive.firebase.externals.firestore.arrayUnion as jsArrayUnion import dev.gitlive.firebase.externals.firestore.endAt as jsEndAt import dev.gitlive.firebase.externals.firestore.endBefore as jsEndBefore import dev.gitlive.firebase.externals.firestore.increment as jsIncrement -import dev.gitlive.firebase.externals.firestore.update as jsUpdate +import dev.gitlive.firebase.externals.firestore.updateDoc as jsUpdate import dev.gitlive.firebase.externals.firestore.limit as jsLimit import dev.gitlive.firebase.externals.firestore.startAfter as jsStartAfter import dev.gitlive.firebase.externals.firestore.startAt as jsStartAt @@ -284,7 +284,7 @@ actual class DocumentReference(val js: JsDocumentReference) { actual suspend fun update(vararg fieldsAndValues: Pair) = rethrow { js.takeUnless { fieldsAndValues.isEmpty() }?.let { jsUpdate( - js, + it, fieldsAndValues[0].first.js, fieldsAndValues[0].second, *fieldsAndValues.flatMap { (field, value) -> @@ -310,7 +310,7 @@ actual class DocumentReference(val js: JsDocumentReference) { actual open class Query(open val js: JsQuery) { - actual suspend fun get() = rethrow { QuerySnapshot(get(js).await()) } + actual suspend fun get() = rethrow { QuerySnapshot(getDocs(js).await()) } actual fun limit(limit: Number) = Query(query(js, jsLimit(limit))) @@ -462,7 +462,7 @@ actual class DocumentSnapshot(val js: JsDocumentSnapshot) { rethrow { decode(strategy, js.get(field, getTimestampsOptions(serverTimestampBehavior))) } actual fun contains(field: String) = rethrow { js.get(field) != undefined } - actual val exists get() = rethrow { js.exists } + actual val exists get() = rethrow { js.exists() } actual val metadata: SnapshotMetadata get() = SnapshotMetadata(js.metadata) fun getTimestampsOptions(serverTimestampBehavior: ServerTimestampBehavior) = @@ -482,7 +482,7 @@ actual class FieldPath private constructor(val js: JsFieldPath) { } actual object FieldValue { - actual val serverTimestamp: Any = serverTimestamp() + actual val serverTimestamp: Double = Double.POSITIVE_INFINITY actual val delete: Any get() = rethrow { deleteField() } actual fun increment(value: Int): Any = rethrow { jsIncrement(value) } actual fun arrayUnion(vararg elements: Any): Any = rethrow { jsArrayUnion(*elements) } From fb4bd1caa2fdb624a428e6510baf60d525799deb Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Mon, 13 Jun 2022 13:08:42 +0300 Subject: [PATCH 10/28] Fix DataSnapshot size --- .../kotlin/dev/gitlive/firebase/externals/database/database.kt | 2 +- .../src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt index be90ed990..baa3c6509 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt @@ -115,10 +115,10 @@ external interface ThenableReference : DatabaseReference external interface DataSnapshot { val key: String? + val size: Int fun `val`(): Any fun exists(): Boolean fun forEach(action: (a: DataSnapshot) -> Boolean): Boolean - fun numChildren(): Int fun child(path: String): DataSnapshot } diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt index 56b481d57..d9c08a08f 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -164,7 +164,7 @@ actual class DataSnapshot internal constructor(val js: JsDataSnapshot) { actual fun child(path: String) = DataSnapshot(js.child(path)) actual val children: Iterable = rethrow { - ArrayList(js.numChildren()).also { + ArrayList(js.size).also { js.forEach { snapshot -> it.add(DataSnapshot(snapshot)) } } } From ab53f6f342e95ed094bea3a8ded8803961c13c2c Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Tue, 14 Jun 2022 00:13:37 +0300 Subject: [PATCH 11/28] Fix database tests --- .../dev.gitlive.firebase.database/database.kt | 13 +++++++++++-- .../dev/gitlive/firebase/database/database.kt | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt b/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt index 265f7b5f4..59089c98c 100644 --- a/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt +++ b/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt @@ -40,6 +40,8 @@ class FirebaseDatabaseTest { @Test fun testSetValue() = runTest { + awaitDatabaseConnection() + val testValue = "test" val testReference = Firebase.database.reference("testPath") @@ -52,9 +54,11 @@ class FirebaseDatabaseTest { assertEquals(testValue, testReferenceValue) } - + @Test fun testChildCount() = runTest { + awaitDatabaseConnection() + setupRealtimeData() val dataSnapshot = Firebase.database .reference("FirebaseRealtimeDatabaseTest") @@ -65,6 +69,11 @@ class FirebaseDatabaseTest { assertEquals(3, firebaseDatabaseChildCount) } + private suspend fun awaitDatabaseConnection() { + // workaround to avoid "Database not connected" exception with Firebase emulator + Firebase.database.reference(".info/connected").valueEvents.first { it.value() } + } + private suspend fun setupRealtimeData() { val firebaseDatabaseTestReference = Firebase.database .reference("FirebaseRealtimeDatabaseTest") @@ -77,4 +86,4 @@ class FirebaseDatabaseTest { firebaseDatabaseTestReference.child("2").setValue(firebaseDatabaseChildTest2) firebaseDatabaseTestReference.child("3").setValue(firebaseDatabaseChildTest3) } -} \ No newline at end of file +} diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt index d9c08a08f..eae44c1fa 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -165,7 +165,7 @@ actual class DataSnapshot internal constructor(val js: JsDataSnapshot) { actual val children: Iterable = rethrow { ArrayList(js.size).also { - js.forEach { snapshot -> it.add(DataSnapshot(snapshot)) } + js.forEach { snapshot -> it.add(DataSnapshot(snapshot)); false /* don't cancel enumeration */ } } } From b6eb04ba77a1bdd3c12f845deeb4a4d925a1238c Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Tue, 14 Jun 2022 01:17:46 +0300 Subject: [PATCH 12/28] Revert non-js changes --- .../kotlin/dev/gitlive/firebase/firestore/firestore.kt | 2 +- .../iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index 95dcf09f1..fbde82667 100644 --- a/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -471,7 +471,7 @@ actual class FieldPath private constructor(val android: com.google.firebase.fire } actual object FieldValue { - actual val serverTimestamp: Double = Double.POSITIVE_INFINITY + actual val serverTimestamp = Double.POSITIVE_INFINITY actual val delete: Any get() = FieldValue.delete() actual fun increment(value: Int): Any = FieldValue.increment(value.toDouble()) actual fun arrayUnion(vararg elements: Any): Any = FieldValue.arrayUnion(*elements) diff --git a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index 4fceec61b..458b83b71 100644 --- a/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/iosMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -444,7 +444,7 @@ actual class FieldPath private constructor(val ios: FIRFieldPath) { } actual object FieldValue { - actual val serverTimestamp: Double = Double.POSITIVE_INFINITY + actual val serverTimestamp = Double.POSITIVE_INFINITY actual val delete: Any get() = FIRFieldValue.fieldValueForDelete() actual fun increment(value: Int): Any = FIRFieldValue.fieldValueForIntegerIncrement(value.toLong()) actual fun arrayUnion(vararg elements: Any): Any = FIRFieldValue.fieldValueForArrayUnion(elements.asList()) From 4ff80b2c622a4d41fa6d371febb86859182c25f4 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Tue, 14 Jun 2022 01:18:25 +0300 Subject: [PATCH 13/28] Fix infinite test task --- .../dev/gitlive/firebase/externals/database/database.kt | 4 ++++ .../kotlin/dev.gitlive.firebase.database/database.kt | 6 +++++- .../kotlin/dev.gitlive.firebase.database/database.kt | 7 ++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt index baa3c6509..aabf9d662 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt @@ -39,6 +39,10 @@ external fun limitToLast(limit: Int): QueryConstraint external fun off(query: Query, eventType: String?, callback: Any?) +external fun goOffline(db: Database) + +external fun goOnline(db: Database) + external fun onChildAdded( query: Query, callback: ChangeSnapshotCallback, diff --git a/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt b/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt index 59089c98c..1e33d8fae 100644 --- a/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt +++ b/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt @@ -6,8 +6,10 @@ package dev.gitlive.firebase.database import dev.gitlive.firebase.* import kotlinx.coroutines.flow.first +import kotlinx.coroutines.withTimeout import kotlinx.serialization.* import kotlin.test.* +import kotlin.time.Duration.Companion.seconds expect val emulatorHost: String expect val context: Any @@ -71,7 +73,9 @@ class FirebaseDatabaseTest { private suspend fun awaitDatabaseConnection() { // workaround to avoid "Database not connected" exception with Firebase emulator - Firebase.database.reference(".info/connected").valueEvents.first { it.value() } + withTimeout(5.seconds) { + Firebase.database.reference(".info/connected").valueEvents.first { it.value() } + } } private suspend fun setupRealtimeData() { diff --git a/firebase-database/src/jsTest/kotlin/dev.gitlive.firebase.database/database.kt b/firebase-database/src/jsTest/kotlin/dev.gitlive.firebase.database/database.kt index e0854b0f2..0cc83d9c9 100644 --- a/firebase-database/src/jsTest/kotlin/dev.gitlive.firebase.database/database.kt +++ b/firebase-database/src/jsTest/kotlin/dev.gitlive.firebase.database/database.kt @@ -4,6 +4,9 @@ package dev.gitlive.firebase.database +import dev.gitlive.firebase.externals.database.getDatabase +import dev.gitlive.firebase.externals.database.goOffline +import dev.gitlive.firebase.externals.database.goOnline import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.promise @@ -14,7 +17,10 @@ actual val context: Any = Unit actual fun runTest(test: suspend () -> Unit) = GlobalScope .promise { try { + val db = getDatabase() + goOnline(db) test() + goOffline(db) // infinitely running test task workaround } catch (e: Throwable) { e.log() throw e @@ -28,4 +34,3 @@ internal fun Throwable.log() { it.log() } } - From 79e4635dbb7b2bd197f5370ef77dabc0667dc9e4 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Tue, 14 Jun 2022 09:39:29 +0300 Subject: [PATCH 14/28] Split externals --- .../jsMain/kotlin/dev/gitlive/firebase/externals.kt | 11 ----------- .../gitlive/firebase/externals/database/externals.kt | 9 +++++++++ .../gitlive/firebase/externals/functions/externals.kt | 10 ++++++++++ 3 files changed, 19 insertions(+), 11 deletions(-) create mode 100644 firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/externals.kt create mode 100644 firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/externals.kt diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt index 2ae7e44a4..087d4f86b 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt @@ -4,15 +4,4 @@ package dev.gitlive.firebase -import dev.gitlive.firebase.externals.database.DataSnapshot -import dev.gitlive.firebase.externals.functions.HttpsCallable -import dev.gitlive.firebase.externals.functions.HttpsCallableResult -import kotlin.js.Promise - -typealias ChangeSnapshotCallback = (data: DataSnapshot, previousChildName: String?) -> Unit -typealias ValueSnapshotCallback = (data: DataSnapshot) -> Unit -typealias CancelCallback = (error: Throwable) -> Unit typealias Unsubscribe = () -> Unit - -operator fun HttpsCallable.invoke() = asDynamic()() as Promise -operator fun HttpsCallable.invoke(data: Any?) = asDynamic()(data) as Promise diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/externals.kt new file mode 100644 index 000000000..ce714f5f5 --- /dev/null +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/externals.kt @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.externals.database + +typealias ChangeSnapshotCallback = (data: DataSnapshot, previousChildName: String?) -> Unit +typealias ValueSnapshotCallback = (data: DataSnapshot) -> Unit +typealias CancelCallback = (error: Throwable) -> Unit diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/externals.kt new file mode 100644 index 000000000..98fc97edf --- /dev/null +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/externals.kt @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.gitlive.firebase.externals.functions + +import kotlin.js.Promise + +operator fun HttpsCallable.invoke() = asDynamic()() as Promise +operator fun HttpsCallable.invoke(data: Any?) = asDynamic()(data) as Promise From 94ef8632cc94716cb5337c3fb3089db1013d1dbf Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Tue, 14 Jun 2022 10:16:24 +0300 Subject: [PATCH 15/28] Fix Android test results path --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 411208bc1..ffd409391 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -58,4 +58,4 @@ jobs: if: failure() with: name: "Android Test Report HTML" - path: "firebase-firestore/build/reports/tests/androidTests/" + path: "firebase-firestore/build/reports/androidTests/" From e6fccc306737797d4f93e117be542c2605046c24 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Tue, 14 Jun 2022 10:17:27 +0300 Subject: [PATCH 16/28] Increase waiting connection to database timeout --- .../commonTest/kotlin/dev.gitlive.firebase.database/database.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt b/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt index 1e33d8fae..458dc579b 100644 --- a/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt +++ b/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt @@ -73,7 +73,7 @@ class FirebaseDatabaseTest { private suspend fun awaitDatabaseConnection() { // workaround to avoid "Database not connected" exception with Firebase emulator - withTimeout(5.seconds) { + withTimeout(30.seconds) { Firebase.database.reference(".info/connected").valueEvents.first { it.value() } } } From a9b9f33bf8b33a510da795a29b6a88bc0ddcb84d Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Thu, 6 Apr 2023 16:29:36 +0300 Subject: [PATCH 17/28] Fixes after merging upstream master branch --- .../kotlin/dev/gitlive/firebase/firebase.kt | 5 +- .../dev/gitlive/firebase/externals/app/app.kt | 4 + .../firebase/externals/database/database.kt | 11 +++ firebase-database/build.gradle.kts | 2 +- .../dev/gitlive/firebase/database/database.kt | 3 +- .../dev/gitlive/firebase/database/database.kt | 1 - .../dev/gitlive/firebase/database/database.kt | 1 - .../dev.gitlive.firebase.database/database.kt | 93 ------------------- .../dev/gitlive/firebase/database/database.kt | 8 +- .../dev/gitlive/firebase/database/database.kt | 24 ++--- .../dev.gitlive.firebase.database/database.kt | 36 ------- .../dev/gitlive/firebase/database/database.kt | 29 +++++- .../dev/gitlive/firebase/perf/externals.kt | 27 ++++++ .../gitlive/firebase/perf/metrics/Trace.kt | 4 +- .../dev/gitlive/firebase/perf/performance.kt | 11 +-- 15 files changed, 92 insertions(+), 167 deletions(-) delete mode 100644 firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt delete mode 100644 firebase-database/src/jsTest/kotlin/dev.gitlive.firebase.database/database.kt create mode 100644 firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/externals.kt diff --git a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt index b4705b2cb..c54a93081 100644 --- a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt +++ b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt @@ -4,6 +4,7 @@ package dev.gitlive.firebase +import dev.gitlive.firebase.externals.app.deleteApp import dev.gitlive.firebase.externals.app.getApp import dev.gitlive.firebase.externals.app.getApps import dev.gitlive.firebase.externals.app.initializeApp @@ -33,7 +34,9 @@ actual class FirebaseApp internal constructor(val js: JsFirebaseApp) { FirebaseOptions(appId, apiKey, databaseURL, gaTrackingId, storageBucket, projectId, messagingSenderId, authDomain) } - actual fun delete() = js.delete() + actual fun delete() { + deleteApp(js) + } } actual fun Firebase.apps(context: Any?) = getApps().map { FirebaseApp(it) } diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt index 4ca8a0c55..b65579a51 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt @@ -3,12 +3,16 @@ package dev.gitlive.firebase.externals.app +import kotlin.js.Promise + external fun initializeApp(options: Any, name: String = definedExternally): FirebaseApp external fun getApp(name: String = definedExternally): FirebaseApp external fun getApps(): Array +external fun deleteApp(app: FirebaseApp): Promise + external interface FirebaseApp { val automaticDataCollectionEnabled: Boolean val name: String diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt index aabf9d662..40828d5dc 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt +++ b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt @@ -99,6 +99,12 @@ external fun startAt(value: Any?, key: String? = definedExternally): QueryConstr external fun update(ref: DatabaseReference, values: Any): Promise +external fun runTransaction( + ref: DatabaseReference, + transactionUpdate: (currentData: T) -> T, + options: Any? = definedExternally +): Promise + external interface Database { val app: FirebaseApp } @@ -132,3 +138,8 @@ external interface OnDisconnect { fun set(value: Any?): Promise fun update(value: Any): Promise } + +external interface TransactionResult { + val committed: Boolean + val snapshot: DataSnapshot +} diff --git a/firebase-database/build.gradle.kts b/firebase-database/build.gradle.kts index ef75443c2..75620f425 100644 --- a/firebase-database/build.gradle.kts +++ b/firebase-database/build.gradle.kts @@ -21,6 +21,7 @@ android { defaultConfig { minSdk = property("minSdkVersion") as Int targetSdk = property("targetSdkVersion") as Int + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } sourceSets { getByName("main") { @@ -143,4 +144,3 @@ signing { useInMemoryPgpKeys(signingKey, signingPassword) sign(publishing.publications) } - diff --git a/firebase-database/src/androidAndroidTest/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/androidAndroidTest/kotlin/dev/gitlive/firebase/database/database.kt index 91653371b..8bd4b60a5 100644 --- a/firebase-database/src/androidAndroidTest/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/androidAndroidTest/kotlin/dev/gitlive/firebase/database/database.kt @@ -6,8 +6,9 @@ package dev.gitlive.firebase.database import androidx.test.platform.app.InstrumentationRegistry +import kotlinx.coroutines.test.TestResult actual val emulatorHost: String = "10.0.2.2" actual val context: Any = InstrumentationRegistry.getInstrumentation().targetContext -actual fun runTest(test: suspend () -> Unit) = kotlinx.coroutines.test.runTest { test() } +actual fun runTest(test: suspend () -> Unit): TestResult = kotlinx.coroutines.test.runTest { test() } diff --git a/firebase-database/src/androidMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/androidMain/kotlin/dev/gitlive/firebase/database/database.kt index 7e51e4fdd..24c25b65c 100644 --- a/firebase-database/src/androidMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/androidMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -264,4 +264,3 @@ actual class OnDisconnect internal constructor( } actual typealias DatabaseException = com.google.firebase.database.DatabaseException - diff --git a/firebase-database/src/commonMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/commonMain/kotlin/dev/gitlive/firebase/database/database.kt index 0936c1123..40eb896f3 100644 --- a/firebase-database/src/commonMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/commonMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -99,4 +99,3 @@ expect class OnDisconnect { suspend fun setValue(strategy: SerializationStrategy, value: T, encodeDefaults: Boolean = true) suspend fun updateChildren(update: Map, encodeDefaults: Boolean = true) } - diff --git a/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt b/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt deleted file mode 100644 index 458dc579b..000000000 --- a/firebase-database/src/commonTest/kotlin/dev.gitlive.firebase.database/database.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.gitlive.firebase.database - -import dev.gitlive.firebase.* -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.withTimeout -import kotlinx.serialization.* -import kotlin.test.* -import kotlin.time.Duration.Companion.seconds - -expect val emulatorHost: String -expect val context: Any -expect fun runTest(test: suspend () -> Unit) - -class FirebaseDatabaseTest { - - @Serializable - data class FirebaseDatabaseChildTest(val prop1: String? = null, val time: Double = 0.0) - - @BeforeTest - fun initializeFirebase() { - Firebase - .takeIf { Firebase.apps(context).isEmpty() } - ?.apply { - initialize( - context, - FirebaseOptions( - applicationId = "1:846484016111:ios:dd1f6688bad7af768c841a", - apiKey = "AIzaSyCK87dcMFhzCz_kJVs2cT2AVlqOTLuyWV0", - databaseUrl = "https://fir-kotlin-sdk.firebaseio.com", - storageBucket = "fir-kotlin-sdk.appspot.com", - projectId = "fir-kotlin-sdk", - gcmSenderId = "846484016111" - ) - ) - Firebase.database.useEmulator(emulatorHost, 9000) - } - } - - @Test - fun testSetValue() = runTest { - awaitDatabaseConnection() - - val testValue = "test" - val testReference = Firebase.database.reference("testPath") - - testReference.setValue(testValue) - - val testReferenceValue = testReference - .valueEvents - .first() - .value() - - assertEquals(testValue, testReferenceValue) - } - - @Test - fun testChildCount() = runTest { - awaitDatabaseConnection() - - setupRealtimeData() - val dataSnapshot = Firebase.database - .reference("FirebaseRealtimeDatabaseTest") - .valueEvents - .first() - - val firebaseDatabaseChildCount = dataSnapshot.children.count() - assertEquals(3, firebaseDatabaseChildCount) - } - - private suspend fun awaitDatabaseConnection() { - // workaround to avoid "Database not connected" exception with Firebase emulator - withTimeout(30.seconds) { - Firebase.database.reference(".info/connected").valueEvents.first { it.value() } - } - } - - private suspend fun setupRealtimeData() { - val firebaseDatabaseTestReference = Firebase.database - .reference("FirebaseRealtimeDatabaseTest") - - val firebaseDatabaseChildTest1 = FirebaseDatabaseChildTest("aaa") - val firebaseDatabaseChildTest2 = FirebaseDatabaseChildTest("bbb") - val firebaseDatabaseChildTest3 = FirebaseDatabaseChildTest("ccc") - - firebaseDatabaseTestReference.child("1").setValue(firebaseDatabaseChildTest1) - firebaseDatabaseTestReference.child("2").setValue(firebaseDatabaseChildTest2) - firebaseDatabaseTestReference.child("3").setValue(firebaseDatabaseChildTest3) - } -} diff --git a/firebase-database/src/commonTest/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/commonTest/kotlin/dev/gitlive/firebase/database/database.kt index 4ea455772..c88bef91a 100644 --- a/firebase-database/src/commonTest/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/commonTest/kotlin/dev/gitlive/firebase/database/database.kt @@ -2,21 +2,19 @@ package dev.gitlive.firebase.database import dev.gitlive.firebase.* import kotlinx.coroutines.flow.first +import kotlinx.coroutines.test.TestResult import kotlinx.serialization.* import kotlin.test.* expect val emulatorHost: String expect val context: Any -expect fun runTest(test: suspend () -> Unit) +expect fun runTest(test: suspend () -> Unit): TestResult class FirebaseDatabaseTest { @Serializable data class FirebaseDatabaseChildTest(val prop1: String? = null, val time: Double = 0.0) - @Serializable - data class DatabaseTest(val title: String, val likes: Int = 0) - @BeforeTest fun initializeFirebase() { Firebase @@ -138,4 +136,4 @@ class FirebaseDatabaseTest { } } -} \ No newline at end of file +} diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt index e8499868a..2c85f596d 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -151,21 +151,15 @@ actual class DatabaseReference internal constructor(override val js: JsDatabaseR actual suspend fun setValue(strategy: SerializationStrategy, value: T, encodeDefaults: Boolean) = rethrow { set(js, encode(strategy, value, encodeDefaults)).awaitWhileOnline() } - actual suspend fun runTransaction(strategy: KSerializer, transactionUpdate: (currentData: T) -> T): DataSnapshot { - val deferred = CompletableDeferred() - js.transaction( - transactionUpdate, - { error, _, snapshot -> - if (error != null) { - deferred.completeExceptionally(error) - } else { - deferred.complete(DataSnapshot(snapshot!!)) - } - }, - applyLocally = false - ) - return deferred.await() - } + actual suspend fun runTransaction(strategy: KSerializer, transactionUpdate: (currentData: T) -> T): DataSnapshot = + rethrow { + val result = dev.gitlive.firebase.externals.database.runTransaction( + js, + transactionUpdate, + ).awaitWhileOnline() + + DataSnapshot(result.snapshot) + } } actual class DataSnapshot internal constructor(val js: JsDataSnapshot) { diff --git a/firebase-database/src/jsTest/kotlin/dev.gitlive.firebase.database/database.kt b/firebase-database/src/jsTest/kotlin/dev.gitlive.firebase.database/database.kt deleted file mode 100644 index 0cc83d9c9..000000000 --- a/firebase-database/src/jsTest/kotlin/dev.gitlive.firebase.database/database.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.gitlive.firebase.database - -import dev.gitlive.firebase.externals.database.getDatabase -import dev.gitlive.firebase.externals.database.goOffline -import dev.gitlive.firebase.externals.database.goOnline -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.promise - -actual val emulatorHost: String = "localhost" - -actual val context: Any = Unit - -actual fun runTest(test: suspend () -> Unit) = GlobalScope - .promise { - try { - val db = getDatabase() - goOnline(db) - test() - goOffline(db) // infinitely running test task workaround - } catch (e: Throwable) { - e.log() - throw e - } - }.asDynamic() - -internal fun Throwable.log() { - console.error(this) - cause?.let { - console.error("Caused by:") - it.log() - } -} diff --git a/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt index 1ba05f836..bbb7efc4d 100644 --- a/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt @@ -1,8 +1,29 @@ package dev.gitlive.firebase.database -actual val emulatorHost: String = "localhost" +import dev.gitlive.firebase.Firebase +import dev.gitlive.firebase.externals.database.getDatabase +import dev.gitlive.firebase.externals.database.goOffline +import dev.gitlive.firebase.externals.database.goOnline +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.withContext +import kotlinx.coroutines.withTimeout +import kotlin.time.Duration.Companion.seconds + +actual val emulatorHost: String = "127.0.0.1" // in JS connection is refused if we use localhost actual val context: Any = Unit -actual fun runTest(test: suspend () -> Unit) { - runTest { test() } -} \ No newline at end of file +actual fun runTest(test: suspend () -> Unit) = kotlinx.coroutines.test.runTest { + val db = getDatabase() + goOnline(db) + awaitDatabaseConnection() + test() + // in JS tests are running infinitely without going database offline + goOffline(db) +} + +private suspend fun awaitDatabaseConnection() = withContext(Dispatchers.Default) { + withTimeout(5.seconds) { + Firebase.database.reference(".info/connected").valueEvents.first { it.value() } + } +} diff --git a/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/externals.kt b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/externals.kt new file mode 100644 index 000000000..0b613255f --- /dev/null +++ b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/externals.kt @@ -0,0 +1,27 @@ +@file:JsModule("firebase/performance") +@file:JsNonModule + +package dev.gitlive.firebase.perf + +import dev.gitlive.firebase.externals.app.FirebaseApp + +external fun getPerformance(app: FirebaseApp? = definedExternally): JsFirebasePerformance + +external fun trace(performance: JsFirebasePerformance, name: String): JsPerformanceTrace + +external interface JsFirebasePerformance { + var dataCollectionEnabled: Boolean + var instrumentationEnabled: Boolean +} + +external interface JsPerformanceTrace { + fun getAttribute(attr: String): String? + fun getAttributes(): Map + fun getMetric(metricName: String): Int + fun incrementMetric(metricName: String, num: Int? = definedExternally) + fun putAttribute(attr: String, value: String) + fun putMetric(metricName: String, num: Int) + fun removeAttribute(attr: String) + fun start() + fun stop() +} diff --git a/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/metrics/Trace.kt b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/metrics/Trace.kt index ae3ff9be4..2c66391ef 100644 --- a/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/metrics/Trace.kt +++ b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/metrics/Trace.kt @@ -1,10 +1,10 @@ package dev.gitlive.firebase.perf.metrics -import dev.gitlive.firebase.firebase +import dev.gitlive.firebase.perf.JsPerformanceTrace import dev.gitlive.firebase.perf.rethrow -actual class Trace internal constructor(private val js: firebase.performance.PerformanceTrace) { +actual class Trace internal constructor(private val js: JsPerformanceTrace) { actual fun start() = rethrow { js.start() } actual fun stop() = rethrow { js.stop() } diff --git a/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/performance.kt b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/performance.kt index e96e36777..21bcad98b 100644 --- a/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/performance.kt +++ b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/performance.kt @@ -3,24 +3,21 @@ package dev.gitlive.firebase.perf import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseApp import dev.gitlive.firebase.FirebaseException -import dev.gitlive.firebase.firebase import dev.gitlive.firebase.perf.metrics.Trace actual val Firebase.performance: FirebasePerformance get() = rethrow { - dev.gitlive.firebase.performance - FirebasePerformance(firebase.performance()) + FirebasePerformance(getPerformance()) } actual fun Firebase.performance(app: FirebaseApp): FirebasePerformance = rethrow { - dev.gitlive.firebase.performance - FirebasePerformance(firebase.performance(app.js)) + FirebasePerformance(getPerformance(app.js)) } -actual class FirebasePerformance internal constructor(val js: firebase.performance) { +actual class FirebasePerformance internal constructor(val js: JsFirebasePerformance) { actual fun newTrace(traceName: String): Trace = rethrow { - Trace(js.trace(traceName)) + Trace(trace(js, traceName)) } actual fun isPerformanceCollectionEnabled(): Boolean = js.dataCollectionEnabled From 117ac635d2e5587514bca4666a7c637eedb707da Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Thu, 6 Apr 2023 16:29:54 +0300 Subject: [PATCH 18/28] Enable firebase-database JS tests --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index ba864d90a..f3b20a1a3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,7 +40,7 @@ firebase-app.skipJsTests=false firebase-auth.skipJsTests=false firebase-common.skipJsTests=false firebase-config.skipJsTests=false -firebase-database.skipJsTests=true +firebase-database.skipJsTests=false firebase-firestore.skipJsTests=false firebase-functions.skipJsTests=false firebase-installations.skipJsTests=false From 541ea9974de0b37a4093584eaa9f3bac3fc7ee7c Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Thu, 6 Apr 2023 17:41:38 +0300 Subject: [PATCH 19/28] Move externals to related modules --- .../dev/gitlive/firebase/externals}/app.kt | 2 +- .../kotlin/dev/gitlive/firebase/firebase.kt | 10 ++--- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 4 +- .../dev/gitlive/firebase/auth/credentials.kt | 18 ++++---- .../gitlive/firebase/auth/externals}/auth.kt | 4 +- .../dev/gitlive/firebase/auth/multifactor.kt | 10 ++--- .../kotlin/dev/gitlive/firebase/auth/user.kt | 4 +- .../remoteconfig/FirebaseRemoteConfig.kt | 2 +- .../remoteconfig/FirebaseRemoteConfigValue.kt | 2 +- .../remoteconfig/externals}/remoteconfig.kt | 4 +- .../dev/gitlive/firebase/database/database.kt | 28 ++++++------ .../firebase/database/externals/callbacks.kt | 2 +- .../firebase/database/externals}/database.kt | 4 +- .../dev/gitlive/firebase/database/database.kt | 6 +-- .../firestore/externals}/firestore.kt | 5 +-- .../gitlive/firebase/firestore/firestore.kt | 43 ++++++++++--------- .../functions/externals/HttpsCallableExt.kt | 2 +- .../functions/externals}/functions.kt | 4 +- .../gitlive/firebase/functions/functions.kt | 4 +- .../installations/externals}/installations.kt | 4 +- .../firebase/installations/installations.kt | 2 +- .../performance.kt} | 12 +++--- .../gitlive/firebase/perf/metrics/Trace.kt | 4 +- .../dev/gitlive/firebase/perf/performance.kt | 3 ++ 24 files changed, 93 insertions(+), 90 deletions(-) rename {firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app => firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/externals}/app.kt (94%) rename {firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth => firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals}/auth.kt (98%) rename {firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/remoteconfig => firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/externals}/remoteconfig.kt (92%) rename firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/externals.kt => firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/callbacks.kt (86%) rename {firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database => firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals}/database.kt (97%) rename {firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore => firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals}/firestore.kt (97%) rename firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/externals.kt => firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/externals/HttpsCallableExt.kt (86%) rename {firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions => firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/externals}/functions.kt (83%) rename {firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/installations => firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/externals}/installations.kt (80%) rename firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/{externals.kt => externals/performance.kt} (67%) diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/externals/app.kt similarity index 94% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt rename to firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/externals/app.kt index b65579a51..ab2066cf9 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/app/app.kt +++ b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/externals/app.kt @@ -1,7 +1,7 @@ @file:JsModule("firebase/app") @file:JsNonModule -package dev.gitlive.firebase.externals.app +package dev.gitlive.firebase.externals import kotlin.js.Promise diff --git a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt index c54a93081..6bffaa7be 100644 --- a/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt +++ b/firebase-app/src/jsMain/kotlin/dev/gitlive/firebase/firebase.kt @@ -4,12 +4,12 @@ package dev.gitlive.firebase -import dev.gitlive.firebase.externals.app.deleteApp -import dev.gitlive.firebase.externals.app.getApp -import dev.gitlive.firebase.externals.app.getApps -import dev.gitlive.firebase.externals.app.initializeApp +import dev.gitlive.firebase.externals.deleteApp +import dev.gitlive.firebase.externals.getApp +import dev.gitlive.firebase.externals.getApps +import dev.gitlive.firebase.externals.initializeApp import kotlin.js.json -import dev.gitlive.firebase.externals.app.FirebaseApp as JsFirebaseApp +import dev.gitlive.firebase.externals.FirebaseApp as JsFirebaseApp actual val Firebase.app: FirebaseApp get() = FirebaseApp(getApp()) 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 3cbc83caa..61d8ecdf0 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 @@ -6,12 +6,12 @@ package dev.gitlive.firebase.auth import dev.gitlive.firebase.* import dev.gitlive.firebase.FirebaseApp -import dev.gitlive.firebase.externals.auth.* +import dev.gitlive.firebase.auth.externals.* import kotlinx.coroutines.await import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow import kotlin.js.json -import dev.gitlive.firebase.externals.auth.AuthResult as JsAuthResult +import dev.gitlive.firebase.auth.externals.AuthResult as JsAuthResult actual val Firebase.auth get() = rethrow { FirebaseAuth(getAuth()) } diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt index 9715b567b..eb6fb9efe 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/credentials.kt @@ -1,16 +1,16 @@ package dev.gitlive.firebase.auth -import dev.gitlive.firebase.externals.auth.* -import dev.gitlive.firebase.externals.auth.EmailAuthProvider -import dev.gitlive.firebase.externals.auth.FacebookAuthProvider -import dev.gitlive.firebase.externals.auth.GithubAuthProvider -import dev.gitlive.firebase.externals.auth.GoogleAuthProvider -import dev.gitlive.firebase.externals.auth.PhoneAuthProvider -import dev.gitlive.firebase.externals.auth.TwitterAuthProvider +import dev.gitlive.firebase.auth.externals.ApplicationVerifier +import dev.gitlive.firebase.auth.externals.EmailAuthProvider +import dev.gitlive.firebase.auth.externals.FacebookAuthProvider +import dev.gitlive.firebase.auth.externals.GithubAuthProvider +import dev.gitlive.firebase.auth.externals.GoogleAuthProvider +import dev.gitlive.firebase.auth.externals.PhoneAuthProvider +import dev.gitlive.firebase.auth.externals.TwitterAuthProvider import kotlinx.coroutines.await import kotlin.js.json -import dev.gitlive.firebase.externals.auth.AuthCredential as JsAuthCredential -import dev.gitlive.firebase.externals.auth.OAuthProvider as JsOAuthProvider +import dev.gitlive.firebase.auth.externals.AuthCredential as JsAuthCredential +import dev.gitlive.firebase.auth.externals.OAuthProvider as JsOAuthProvider actual open class AuthCredential(val js: JsAuthCredential) { actual val providerId: String diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth/auth.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals/auth.kt similarity index 98% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth/auth.kt rename to firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals/auth.kt index fe3ebf175..927523e28 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/auth/auth.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/externals/auth.kt @@ -1,10 +1,10 @@ @file:JsModule("firebase/auth") @file:JsNonModule -package dev.gitlive.firebase.externals.auth +package dev.gitlive.firebase.auth.externals import dev.gitlive.firebase.Unsubscribe -import dev.gitlive.firebase.externals.app.FirebaseApp +import dev.gitlive.firebase.externals.FirebaseApp import kotlin.js.Json import kotlin.js.Promise diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt index 703ab09c0..d4ad636a7 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/multifactor.kt @@ -1,12 +1,12 @@ package dev.gitlive.firebase.auth -import dev.gitlive.firebase.externals.auth.MultiFactorUser +import dev.gitlive.firebase.auth.externals.MultiFactorUser import kotlinx.coroutines.await import kotlin.js.Date -import dev.gitlive.firebase.externals.auth.MultiFactorAssertion as JsMultiFactorAssertion -import dev.gitlive.firebase.externals.auth.MultiFactorInfo as JsMultiFactorInfo -import dev.gitlive.firebase.externals.auth.MultiFactorResolver as JsMultiFactorResolver -import dev.gitlive.firebase.externals.auth.MultiFactorSession as JsMultiFactorSession +import dev.gitlive.firebase.auth.externals.MultiFactorAssertion as JsMultiFactorAssertion +import dev.gitlive.firebase.auth.externals.MultiFactorInfo as JsMultiFactorInfo +import dev.gitlive.firebase.auth.externals.MultiFactorResolver as JsMultiFactorResolver +import dev.gitlive.firebase.auth.externals.MultiFactorSession as JsMultiFactorSession actual class MultiFactor(val js: MultiFactorUser) { actual val enrolledFactors: List diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt index 9432ae9f5..a22c2b10b 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -1,9 +1,9 @@ package dev.gitlive.firebase.auth -import dev.gitlive.firebase.externals.auth.* +import dev.gitlive.firebase.auth.externals.* import kotlinx.coroutines.await import kotlin.js.Date -import dev.gitlive.firebase.externals.auth.UserInfo as JsUserInfo +import dev.gitlive.firebase.auth.externals.UserInfo as JsUserInfo actual class FirebaseUser internal constructor(val js: User) { actual val uid: String diff --git a/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt b/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt index ad40e8837..bba268c12 100644 --- a/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt +++ b/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt @@ -3,7 +3,7 @@ package dev.gitlive.firebase.remoteconfig import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseApp import dev.gitlive.firebase.FirebaseException -import dev.gitlive.firebase.externals.remoteconfig.* +import dev.gitlive.firebase.remoteconfig.externals.* import kotlinx.coroutines.await import kotlin.js.json diff --git a/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfigValue.kt b/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfigValue.kt index 0062a787e..2891f926a 100644 --- a/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfigValue.kt +++ b/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfigValue.kt @@ -1,6 +1,6 @@ package dev.gitlive.firebase.remoteconfig -import dev.gitlive.firebase.externals.remoteconfig.Value +import dev.gitlive.firebase.remoteconfig.externals.Value actual class FirebaseRemoteConfigValue(val js: Value) { actual fun asBoolean(): Boolean = rethrow { js.asBoolean() } diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/remoteconfig/remoteconfig.kt b/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/externals/remoteconfig.kt similarity index 92% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/remoteconfig/remoteconfig.kt rename to firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/externals/remoteconfig.kt index 7ab94aded..b2a42dc84 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/remoteconfig/remoteconfig.kt +++ b/firebase-config/src/jsMain/kotlin/dev/gitlive/firebase/remoteconfig/externals/remoteconfig.kt @@ -1,9 +1,9 @@ @file:JsModule("firebase/remote-config") @file:JsNonModule -package dev.gitlive.firebase.externals.remoteconfig +package dev.gitlive.firebase.remoteconfig.externals -import dev.gitlive.firebase.externals.app.FirebaseApp +import dev.gitlive.firebase.externals.FirebaseApp import kotlin.js.Json import kotlin.js.Promise diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt index 2c85f596d..2053cbda6 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -6,7 +6,7 @@ package dev.gitlive.firebase.database import dev.gitlive.firebase.* import dev.gitlive.firebase.FirebaseApp -import dev.gitlive.firebase.externals.database.* +import dev.gitlive.firebase.database.externals.* import kotlinx.coroutines.* import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.callbackFlow @@ -18,18 +18,18 @@ import kotlinx.serialization.KSerializer import kotlinx.serialization.SerializationStrategy import kotlin.js.Promise import kotlin.js.json -import dev.gitlive.firebase.externals.database.DataSnapshot as JsDataSnapshot -import dev.gitlive.firebase.externals.database.DatabaseReference as JsDatabaseReference -import dev.gitlive.firebase.externals.database.OnDisconnect as JsOnDisconnect -import dev.gitlive.firebase.externals.database.Query as JsQuery -import dev.gitlive.firebase.externals.database.endAt as jsEndAt -import dev.gitlive.firebase.externals.database.equalTo as jsEqualTo -import dev.gitlive.firebase.externals.database.limitToFirst as jsLimitToFirst -import dev.gitlive.firebase.externals.database.limitToLast as jsLimitToLast -import dev.gitlive.firebase.externals.database.orderByChild as jsOrderByChild -import dev.gitlive.firebase.externals.database.orderByKey as jsOrderByKey -import dev.gitlive.firebase.externals.database.orderByValue as jsOrderByValue -import dev.gitlive.firebase.externals.database.startAt as jsStartAt +import dev.gitlive.firebase.database.externals.DataSnapshot as JsDataSnapshot +import dev.gitlive.firebase.database.externals.DatabaseReference as JsDatabaseReference +import dev.gitlive.firebase.database.externals.OnDisconnect as JsOnDisconnect +import dev.gitlive.firebase.database.externals.Query as JsQuery +import dev.gitlive.firebase.database.externals.endAt as jsEndAt +import dev.gitlive.firebase.database.externals.equalTo as jsEqualTo +import dev.gitlive.firebase.database.externals.limitToFirst as jsLimitToFirst +import dev.gitlive.firebase.database.externals.limitToLast as jsLimitToLast +import dev.gitlive.firebase.database.externals.orderByChild as jsOrderByChild +import dev.gitlive.firebase.database.externals.orderByKey as jsOrderByKey +import dev.gitlive.firebase.database.externals.orderByValue as jsOrderByValue +import dev.gitlive.firebase.database.externals.startAt as jsStartAt @PublishedApi internal inline fun encode(value: T, shouldEncodeElementDefault: Boolean) = @@ -153,7 +153,7 @@ actual class DatabaseReference internal constructor(override val js: JsDatabaseR actual suspend fun runTransaction(strategy: KSerializer, transactionUpdate: (currentData: T) -> T): DataSnapshot = rethrow { - val result = dev.gitlive.firebase.externals.database.runTransaction( + val result = runTransaction( js, transactionUpdate, ).awaitWhileOnline() diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/externals.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/callbacks.kt similarity index 86% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/externals.kt rename to firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/callbacks.kt index ce714f5f5..86a592432 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/externals.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/callbacks.kt @@ -2,7 +2,7 @@ * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. */ -package dev.gitlive.firebase.externals.database +package dev.gitlive.firebase.database.externals typealias ChangeSnapshotCallback = (data: DataSnapshot, previousChildName: String?) -> Unit typealias ValueSnapshotCallback = (data: DataSnapshot) -> Unit diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/database.kt similarity index 97% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt rename to firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/database.kt index 40828d5dc..81687797c 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/database/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/database.kt @@ -1,10 +1,10 @@ @file:JsModule("firebase/database") @file:JsNonModule -package dev.gitlive.firebase.externals.database +package dev.gitlive.firebase.database.externals import dev.gitlive.firebase.* -import dev.gitlive.firebase.externals.app.FirebaseApp +import dev.gitlive.firebase.externals.FirebaseApp import kotlin.js.Promise external fun child(parent: DatabaseReference, path: String): DatabaseReference diff --git a/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt index bbb7efc4d..08eb97c96 100644 --- a/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt @@ -1,9 +1,9 @@ package dev.gitlive.firebase.database import dev.gitlive.firebase.Firebase -import dev.gitlive.firebase.externals.database.getDatabase -import dev.gitlive.firebase.externals.database.goOffline -import dev.gitlive.firebase.externals.database.goOnline +import dev.gitlive.firebase.database.externals.getDatabase +import dev.gitlive.firebase.database.externals.goOffline +import dev.gitlive.firebase.database.externals.goOnline import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.withContext diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore/firestore.kt b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt similarity index 97% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore/firestore.kt rename to firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt index 593c5a630..fa6730bf9 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/firestore/firestore.kt +++ b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt @@ -1,11 +1,10 @@ @file:JsModule("firebase/firestore") @file:JsNonModule -package dev.gitlive.firebase.externals.firestore +package dev.gitlive.firebase.firestore.externals import dev.gitlive.firebase.Unsubscribe -import dev.gitlive.firebase.externals.app.FirebaseApp -import dev.gitlive.firebase.externals.database.QueryConstraint +import dev.gitlive.firebase.externals.FirebaseApp import kotlin.js.Json import kotlin.js.Promise diff --git a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index f6df7e1b8..2ad5a366a 100644 --- a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -5,7 +5,8 @@ package dev.gitlive.firebase.firestore import dev.gitlive.firebase.* -import dev.gitlive.firebase.externals.firestore.* +import dev.gitlive.firebase.FirebaseApp +import dev.gitlive.firebase.firestore.externals.* import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.await import kotlinx.coroutines.channels.awaitClose @@ -14,26 +15,26 @@ import kotlinx.coroutines.promise import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationStrategy import kotlin.js.json -import dev.gitlive.firebase.externals.firestore.CollectionReference as JsCollectionReference -import dev.gitlive.firebase.externals.firestore.DocumentChange as JsDocumentChange -import dev.gitlive.firebase.externals.firestore.DocumentReference as JsDocumentReference -import dev.gitlive.firebase.externals.firestore.DocumentSnapshot as JsDocumentSnapshot -import dev.gitlive.firebase.externals.firestore.FieldPath as JsFieldPath -import dev.gitlive.firebase.externals.firestore.Query as JsQuery -import dev.gitlive.firebase.externals.firestore.QuerySnapshot as JsQuerySnapshot -import dev.gitlive.firebase.externals.firestore.SnapshotMetadata as JsSnapshotMetadata -import dev.gitlive.firebase.externals.firestore.Transaction as JsTransaction -import dev.gitlive.firebase.externals.firestore.WriteBatch as JsWriteBatch -import dev.gitlive.firebase.externals.firestore.arrayRemove as jsArrayRemove -import dev.gitlive.firebase.externals.firestore.arrayUnion as jsArrayUnion -import dev.gitlive.firebase.externals.firestore.endAt as jsEndAt -import dev.gitlive.firebase.externals.firestore.endBefore as jsEndBefore -import dev.gitlive.firebase.externals.firestore.increment as jsIncrement -import dev.gitlive.firebase.externals.firestore.updateDoc as jsUpdate -import dev.gitlive.firebase.externals.firestore.limit as jsLimit -import dev.gitlive.firebase.externals.firestore.startAfter as jsStartAfter -import dev.gitlive.firebase.externals.firestore.startAt as jsStartAt -import dev.gitlive.firebase.externals.firestore.where as jsWhere +import dev.gitlive.firebase.firestore.externals.CollectionReference as JsCollectionReference +import dev.gitlive.firebase.firestore.externals.DocumentChange as JsDocumentChange +import dev.gitlive.firebase.firestore.externals.DocumentReference as JsDocumentReference +import dev.gitlive.firebase.firestore.externals.DocumentSnapshot as JsDocumentSnapshot +import dev.gitlive.firebase.firestore.externals.FieldPath as JsFieldPath +import dev.gitlive.firebase.firestore.externals.Query as JsQuery +import dev.gitlive.firebase.firestore.externals.QuerySnapshot as JsQuerySnapshot +import dev.gitlive.firebase.firestore.externals.SnapshotMetadata as JsSnapshotMetadata +import dev.gitlive.firebase.firestore.externals.Transaction as JsTransaction +import dev.gitlive.firebase.firestore.externals.WriteBatch as JsWriteBatch +import dev.gitlive.firebase.firestore.externals.arrayRemove as jsArrayRemove +import dev.gitlive.firebase.firestore.externals.arrayUnion as jsArrayUnion +import dev.gitlive.firebase.firestore.externals.endAt as jsEndAt +import dev.gitlive.firebase.firestore.externals.endBefore as jsEndBefore +import dev.gitlive.firebase.firestore.externals.increment as jsIncrement +import dev.gitlive.firebase.firestore.externals.limit as jsLimit +import dev.gitlive.firebase.firestore.externals.startAfter as jsStartAfter +import dev.gitlive.firebase.firestore.externals.startAt as jsStartAt +import dev.gitlive.firebase.firestore.externals.updateDoc as jsUpdate +import dev.gitlive.firebase.firestore.externals.where as jsWhere @PublishedApi internal inline fun decode(value: Any?): T = diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/externals.kt b/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/externals/HttpsCallableExt.kt similarity index 86% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/externals.kt rename to firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/externals/HttpsCallableExt.kt index 98fc97edf..ef4d3f6f0 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/externals.kt +++ b/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/externals/HttpsCallableExt.kt @@ -2,7 +2,7 @@ * Copyright (c) 2020 GitLive Ltd. Use of this source code is governed by the Apache 2.0 license. */ -package dev.gitlive.firebase.externals.functions +package dev.gitlive.firebase.functions.externals import kotlin.js.Promise diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/functions.kt b/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/externals/functions.kt similarity index 83% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/functions.kt rename to firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/externals/functions.kt index aee2a562f..7cf5388c6 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/functions/functions.kt +++ b/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/externals/functions.kt @@ -1,9 +1,9 @@ @file:JsModule("firebase/functions") @file:JsNonModule -package dev.gitlive.firebase.externals.functions +package dev.gitlive.firebase.functions.externals -import dev.gitlive.firebase.externals.app.FirebaseApp +import dev.gitlive.firebase.externals.FirebaseApp import kotlin.js.Json external fun connectFunctionsEmulator(functions: Functions, host: String, port: Int) diff --git a/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt b/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt index f8bd3802c..e4fcf5d97 100644 --- a/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt +++ b/firebase-functions/src/jsMain/kotlin/dev/gitlive/firebase/functions/functions.kt @@ -5,13 +5,13 @@ package dev.gitlive.firebase.functions import dev.gitlive.firebase.* -import dev.gitlive.firebase.externals.functions.* +import dev.gitlive.firebase.functions.externals.* import kotlinx.coroutines.await import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.SerializationStrategy import org.w3c.dom.url.URL import kotlin.js.json -import dev.gitlive.firebase.externals.functions.HttpsCallableResult as JsHttpsCallableResult +import dev.gitlive.firebase.functions.externals.HttpsCallableResult as JsHttpsCallableResult actual val Firebase.functions: FirebaseFunctions get() = rethrow { FirebaseFunctions(getFunctions()) } diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/installations/installations.kt b/firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/externals/installations.kt similarity index 80% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/installations/installations.kt rename to firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/externals/installations.kt index 81b05c52a..c2b236f76 100644 --- a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals/installations/installations.kt +++ b/firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/externals/installations.kt @@ -1,9 +1,9 @@ @file:JsModule("firebase/installations") @file:JsNonModule -package dev.gitlive.firebase.externals.installations +package dev.gitlive.firebase.installations.externals -import dev.gitlive.firebase.externals.app.FirebaseApp +import dev.gitlive.firebase.externals.FirebaseApp import kotlin.js.Promise external fun delete(installations: Installations): Promise diff --git a/firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/installations.kt b/firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/installations.kt index 4668ccf2d..7329c3626 100644 --- a/firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/installations.kt +++ b/firebase-installations/src/jsMain/kotlin/dev/gitlive/firebase/installations/installations.kt @@ -1,7 +1,7 @@ package dev.gitlive.firebase.installations import dev.gitlive.firebase.* -import dev.gitlive.firebase.externals.installations.* +import dev.gitlive.firebase.installations.externals.* import kotlinx.coroutines.await actual val Firebase.installations diff --git a/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/externals.kt b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/externals/performance.kt similarity index 67% rename from firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/externals.kt rename to firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/externals/performance.kt index 0b613255f..dc6a04d0a 100644 --- a/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/externals.kt +++ b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/externals/performance.kt @@ -1,20 +1,20 @@ @file:JsModule("firebase/performance") @file:JsNonModule -package dev.gitlive.firebase.perf +package dev.gitlive.firebase.perf.externals -import dev.gitlive.firebase.externals.app.FirebaseApp +import dev.gitlive.firebase.externals.FirebaseApp -external fun getPerformance(app: FirebaseApp? = definedExternally): JsFirebasePerformance +external fun getPerformance(app: FirebaseApp? = definedExternally): FirebasePerformance -external fun trace(performance: JsFirebasePerformance, name: String): JsPerformanceTrace +external fun trace(performance: FirebasePerformance, name: String): PerformanceTrace -external interface JsFirebasePerformance { +external interface FirebasePerformance { var dataCollectionEnabled: Boolean var instrumentationEnabled: Boolean } -external interface JsPerformanceTrace { +external interface PerformanceTrace { fun getAttribute(attr: String): String? fun getAttributes(): Map fun getMetric(metricName: String): Int diff --git a/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/metrics/Trace.kt b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/metrics/Trace.kt index 2c66391ef..2f89a26c7 100644 --- a/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/metrics/Trace.kt +++ b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/metrics/Trace.kt @@ -1,10 +1,10 @@ package dev.gitlive.firebase.perf.metrics -import dev.gitlive.firebase.perf.JsPerformanceTrace +import dev.gitlive.firebase.perf.externals.PerformanceTrace import dev.gitlive.firebase.perf.rethrow -actual class Trace internal constructor(private val js: JsPerformanceTrace) { +actual class Trace internal constructor(private val js: PerformanceTrace) { actual fun start() = rethrow { js.start() } actual fun stop() = rethrow { js.stop() } diff --git a/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/performance.kt b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/performance.kt index 21bcad98b..ed27b5001 100644 --- a/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/performance.kt +++ b/firebase-perf/src/jsMain/kotlin/dev/gitlive/firebase/perf/performance.kt @@ -3,7 +3,10 @@ package dev.gitlive.firebase.perf import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseApp import dev.gitlive.firebase.FirebaseException +import dev.gitlive.firebase.perf.externals.getPerformance +import dev.gitlive.firebase.perf.externals.trace import dev.gitlive.firebase.perf.metrics.Trace +import dev.gitlive.firebase.perf.externals.FirebasePerformance as JsFirebasePerformance actual val Firebase.performance: FirebasePerformance get() = rethrow { From dd2e9d728ee2c4434da71028de74464ab77e432f Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Thu, 6 Apr 2023 22:38:49 +0300 Subject: [PATCH 20/28] Add externals signInWithPopup, signInWithRedirect, getRedirectResult --- .../gitlive/firebase/auth/externals/auth.kt | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) 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 927523e28..e27208d1b 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 @@ -77,6 +77,12 @@ external fun signInWithEmailAndPassword( external fun signInWithEmailLink(auth: Auth, email: String, link: String): Promise +external fun signInWithPopup(auth: Auth, provider: AuthProvider): Promise + +external fun signInWithRedirect(auth: Auth, provider: AuthProvider): Promise + +external fun getRedirectResult(auth: Auth): Promise + external fun signOut(auth: Auth): Promise external fun unlink(user: User, providerId: String): Promise @@ -169,6 +175,18 @@ external interface AuthCredential { val signInMethod: String } +external interface OAuthCredential : AuthCredential { + val accessToken: String? + val idToken: String? + val secret: String? +} + +external interface UserCredential { + val operationType: String + val providerId: String? + val user: User +} + external interface ProfileUpdateRequest { val displayName: String? val photoURL: String? @@ -206,6 +224,8 @@ external interface MultiFactorResolver { external interface AuthProvider +external interface AuthError + external object EmailAuthProvider : AuthProvider { fun credential(email: String, password: String): AuthCredential fun credentialWithLink(email: String, emailLink: String): AuthCredential @@ -219,8 +239,13 @@ external object GithubAuthProvider : AuthProvider { fun credential(token: String): AuthCredential } -external object GoogleAuthProvider : AuthProvider { - fun credential(idToken: String?, accessToken: String?): AuthCredential +external class GoogleAuthProvider : AuthProvider { + fun addScope(scope: String) + companion object { + fun credential(idToken: String?, accessToken: String?): AuthCredential + fun credentialFromResult(userCredential: UserCredential): OAuthCredential? + fun credentialFromError(error: AuthError): OAuthCredential? + } } external class OAuthProvider(providerId: String) : AuthProvider { From 5bb89b8bc987168895df4548d885b1d9475b07e9 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Sun, 9 Apr 2023 20:37:31 +0300 Subject: [PATCH 21/28] Resolve conflicts --- .../dev/gitlive/firebase/database/ServerValue.kt | 9 ++++----- .../firebase/database/externals/database.kt | 2 +- .../dev/gitlive/firebase/firestore/Timestamp.kt | 4 +--- .../firebase/firestore/externals/firestore.kt | 16 +++++++++++++++- .../dev/gitlive/firebase/firestore/firestore.kt | 13 ++++++++----- 5 files changed, 29 insertions(+), 15 deletions(-) diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/ServerValue.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/ServerValue.kt index 5625a6dac..cfb14b69b 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/ServerValue.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/ServerValue.kt @@ -1,9 +1,8 @@ package dev.gitlive.firebase.database -import dev.gitlive.firebase.firebase +import dev.gitlive.firebase.database.externals.serverTimestamp import kotlinx.serialization.Serializable - -private typealias NativeServerValue = firebase.database.ServerValue +import dev.gitlive.firebase.database.externals.increment as jsIncrement /** Represents a Firebase ServerValue. */ @Serializable(with = ServerValueSerializer::class) @@ -11,8 +10,8 @@ actual class ServerValue internal actual constructor( internal actual val nativeValue: Any ){ actual companion object { - actual val TIMESTAMP: ServerValue get() = ServerValue(NativeServerValue.TIMESTAMP) - actual fun increment(delta: Double): ServerValue = ServerValue(NativeServerValue.increment(delta)) + actual val TIMESTAMP: ServerValue get() = ServerValue(serverTimestamp()) + actual fun increment(delta: Double): ServerValue = ServerValue(jsIncrement(delta)) } override fun equals(other: Any?): Boolean = diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/database.kt index 81687797c..4621fcbd5 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/database.kt @@ -31,7 +31,7 @@ external fun getDatabase( url: String? = definedExternally ): Database -external fun increment(delta: Long): Any +external fun increment(delta: Double): Any external fun limitToFirst(limit: Int): QueryConstraint diff --git a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt index b82cf083a..32c630839 100644 --- a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt +++ b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt @@ -1,6 +1,5 @@ package dev.gitlive.firebase.firestore -import dev.gitlive.firebase.* import kotlinx.serialization.Serializable /** A base class that could be used to combine [Timestamp] and [Timestamp.ServerTimestamp] in the same field. */ @@ -8,7 +7,7 @@ import kotlinx.serialization.Serializable actual sealed class BaseTimestamp /** A class representing a platform specific Firebase Timestamp. */ -actual typealias NativeTimestamp = firebase.firestore.Timestamp +actual typealias NativeTimestamp = dev.gitlive.firebase.firestore.externals.Timestamp /** A class representing a Firebase Timestamp. */ @Serializable(with = TimestampSerializer::class) @@ -33,4 +32,3 @@ actual class Timestamp internal actual constructor( @Serializable(with = ServerTimestampSerializer::class) actual object ServerTimestamp: BaseTimestamp() } - diff --git a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt index fa6730bf9..4e4399ab8 100644 --- a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt +++ b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt @@ -179,7 +179,9 @@ external interface DocumentSnapshot { fun get(fieldPath: FieldPath, options: Any? = definedExternally): Any? } -external interface FieldValue +external class FieldValue { + fun isEqual(other: FieldValue): Boolean +} external interface Query @@ -252,3 +254,15 @@ external interface WriteBatch { vararg moreFieldsAndValues: Any? ): WriteBatch } + +external class Timestamp(seconds: Double, nanoseconds: Double) { + companion object { + fun now(): Timestamp + } + + val seconds: Double + val nanoseconds: Double + fun toMillis(): Double + + fun isEqual(other: Timestamp): Boolean +} diff --git a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index 0440a249d..1dbd449a3 100644 --- a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -4,8 +4,11 @@ package dev.gitlive.firebase.firestore -import dev.gitlive.firebase.* +import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseApp +import dev.gitlive.firebase.FirebaseException +import dev.gitlive.firebase.decode +import dev.gitlive.firebase.encode import dev.gitlive.firebase.firestore.externals.* import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.await @@ -52,7 +55,7 @@ private fun performUpdate( /** Helper method to perform an update operation. */ private fun performUpdate( fieldsAndValues: Array>, - update: (firebase.firestore.FieldPath, Any?, Array) -> R + update: (dev.gitlive.firebase.firestore.externals.FieldPath, Any?, Array) -> R ) = performUpdate(fieldsAndValues, { it.js }, { encode(it, true) }, update) actual class FirebaseFirestore(jsFirestore: Firestore) { @@ -246,13 +249,13 @@ actual class DocumentReference(val js: JsDocumentReference) { actual suspend fun update(vararg fieldsAndValues: Pair) = rethrow { performUpdate(fieldsAndValues) { field, value, moreFieldsAndValues -> - js.update(field, value, *moreFieldsAndValues) + jsUpdate(js, field, value, *moreFieldsAndValues) }?.await() }.run { Unit } actual suspend fun update(vararg fieldsAndValues: Pair) = rethrow { performUpdate(fieldsAndValues) { field, value, moreFieldsAndValues -> - js.update(field, value, *moreFieldsAndValues) + jsUpdate(js, field, value, *moreFieldsAndValues) }?.await() }.run { Unit } @@ -444,7 +447,7 @@ actual class FieldPath private constructor(val js: JsFieldPath) { } /** Represents a platform specific Firebase FieldValue. */ -private typealias NativeFieldValue = firebase.firestore.FieldValue +private typealias NativeFieldValue = dev.gitlive.firebase.firestore.externals.FieldValue /** Represents a Firebase FieldValue. */ @Serializable(with = FieldValueSerializer::class) From d66734c69c77de6d69992022965900c0ced9287d Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Sun, 9 Apr 2023 21:55:14 +0300 Subject: [PATCH 22/28] Fix tests --- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 3 +- .../kotlin/dev/gitlive/firebase/auth/auth.kt | 4 +-- .../remoteconfig/FirebaseRemoteConfig.kt | 3 +- .../remoteconfig/FirebaseRemoteConfig.kt | 4 +-- .../firebase/crashlytics/crashlytics.kt | 4 +-- .../dev/gitlive/firebase/database/database.kt | 2 +- .../gitlive/firebase/firestore/firestore.kt | 2 +- .../gitlive/firebase/firestore/firestore.kt | 34 +++++++++---------- .../gitlive/firebase/firestore/firestore.kt | 4 +-- .../dev/gitlive/firebase/perf/performance.kt | 3 +- .../dev/gitlive/firebase/perf/performance.kt | 4 +-- 11 files changed, 30 insertions(+), 37 deletions(-) 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 12250e31e..1635540c0 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 @@ -5,12 +5,13 @@ package dev.gitlive.firebase.auth import dev.gitlive.firebase.* +import kotlinx.coroutines.test.TestResult import kotlin.random.Random import kotlin.test.* expect val emulatorHost: String expect val context: Any -expect fun runTest(test: suspend () -> Unit) +expect fun runTest(test: suspend () -> Unit): TestResult class FirebaseAuthTest { diff --git a/firebase-auth/src/jsTest/kotlin/dev/gitlive/firebase/auth/auth.kt b/firebase-auth/src/jsTest/kotlin/dev/gitlive/firebase/auth/auth.kt index be90b4c54..58c87cded 100644 --- a/firebase-auth/src/jsTest/kotlin/dev/gitlive/firebase/auth/auth.kt +++ b/firebase-auth/src/jsTest/kotlin/dev/gitlive/firebase/auth/auth.kt @@ -9,6 +9,4 @@ actual val emulatorHost: String = "localhost" actual val context: Any = Unit -actual fun runTest(test: suspend () -> Unit) { - kotlinx.coroutines.test.runTest { test() } -} +actual fun runTest(test: suspend () -> Unit) = kotlinx.coroutines.test.runTest { test() } diff --git a/firebase-config/src/commonTest/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt b/firebase-config/src/commonTest/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt index 8c1751c3d..6ae20572a 100644 --- a/firebase-config/src/commonTest/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt +++ b/firebase-config/src/commonTest/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt @@ -8,6 +8,7 @@ import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseOptions import dev.gitlive.firebase.apps import dev.gitlive.firebase.initialize +import kotlinx.coroutines.test.TestResult import kotlin.test.AfterTest import kotlin.test.BeforeTest import kotlin.test.Ignore @@ -15,7 +16,7 @@ import kotlin.test.Test import kotlin.test.assertEquals expect val context: Any -expect fun runTest(test: suspend () -> Unit) +expect fun runTest(test: suspend () -> Unit): TestResult class FirebaseRemoteConfigTest { private val defaults = arrayOf( diff --git a/firebase-config/src/jsTest/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt b/firebase-config/src/jsTest/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt index 74650729c..585e73bc4 100644 --- a/firebase-config/src/jsTest/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt +++ b/firebase-config/src/jsTest/kotlin/dev/gitlive/firebase/remoteconfig/FirebaseRemoteConfig.kt @@ -3,6 +3,4 @@ package dev.gitlive.firebase.remoteconfig actual val context: Any = Unit -actual fun runTest(test: suspend () -> Unit) { - kotlinx.coroutines.test.runTest { test() } -} +actual fun runTest(test: suspend () -> Unit) = kotlinx.coroutines.test.runTest { test() } diff --git a/firebase-crashlytics/src/commonTest/kotlin/dev/gitlive/firebase/crashlytics/crashlytics.kt b/firebase-crashlytics/src/commonTest/kotlin/dev/gitlive/firebase/crashlytics/crashlytics.kt index 92ac6d480..c1e46c6ec 100644 --- a/firebase-crashlytics/src/commonTest/kotlin/dev/gitlive/firebase/crashlytics/crashlytics.kt +++ b/firebase-crashlytics/src/commonTest/kotlin/dev/gitlive/firebase/crashlytics/crashlytics.kt @@ -9,14 +9,14 @@ import dev.gitlive.firebase.FirebaseOptions import dev.gitlive.firebase.apps import dev.gitlive.firebase.initialize import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.test.TestResult import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertFalse -import kotlin.test.assertNotNull expect val emulatorHost: String expect val context: Any -expect fun runTest(test: suspend CoroutineScope.() -> Unit) +expect fun runTest(test: suspend CoroutineScope.() -> Unit): TestResult class FirebaseCrashlyticsTest { diff --git a/firebase-database/src/androidAndroidTest/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/androidAndroidTest/kotlin/dev/gitlive/firebase/database/database.kt index 8bd4b60a5..0745baa19 100644 --- a/firebase-database/src/androidAndroidTest/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/androidAndroidTest/kotlin/dev/gitlive/firebase/database/database.kt @@ -11,4 +11,4 @@ import kotlinx.coroutines.test.TestResult actual val emulatorHost: String = "10.0.2.2" actual val context: Any = InstrumentationRegistry.getInstrumentation().targetContext -actual fun runTest(test: suspend () -> Unit): TestResult = kotlinx.coroutines.test.runTest { test() } +actual fun runTest(test: suspend () -> Unit) = kotlinx.coroutines.test.runTest { test() } diff --git a/firebase-firestore/src/androidAndroidTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/androidAndroidTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt index 9c3f485e2..9985c9a98 100644 --- a/firebase-firestore/src/androidAndroidTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/androidAndroidTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -13,4 +13,4 @@ actual val emulatorHost: String = "10.0.2.2" actual val context: Any = InstrumentationRegistry.getInstrumentation().targetContext -actual fun runTest(test: suspend CoroutineScope.() -> Unit) = runBlocking { test() } +actual fun runTest(test: suspend CoroutineScope.() -> Unit) = kotlinx.coroutines.test.runTest { test() } 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 d0ca9c597..170e56541 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 @@ -9,11 +9,13 @@ import dev.gitlive.firebase.FirebaseOptions import dev.gitlive.firebase.apps import dev.gitlive.firebase.initialize 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.withTimeout +import kotlinx.coroutines.test.TestResult +import kotlinx.coroutines.withContext import kotlinx.serialization.Serializable import kotlin.random.Random import kotlin.test.BeforeTest @@ -26,7 +28,7 @@ import kotlin.test.assertTrue expect val emulatorHost: String expect val context: Any -expect fun runTest(test: suspend CoroutineScope.() -> Unit) +expect fun runTest(test: suspend CoroutineScope.() -> Unit): TestResult class FirebaseFirestoreTest { @@ -157,11 +159,9 @@ class FirebaseFirestoreTest { .document("test${Random.nextInt()}") val deferredPendingWritesSnapshot = async { - withTimeout(5000) { - doc.snapshots.filter { it.exists }.first() - } + doc.snapshots.filter { it.exists }.first() } - delay(100) // makes possible to catch pending writes snapshot + nonSkippedDelay(100) // makes possible to catch pending writes snapshot doc.set( FirestoreTimeTest.serializer(), @@ -180,11 +180,9 @@ class FirebaseFirestoreTest { .document("test${Random.nextInt()}") val deferredPendingWritesSnapshot = async { - withTimeout(5000) { - doc.snapshots.filter { it.exists }.first() - } + doc.snapshots.filter { it.exists }.first() } - delay(100) // makes possible to catch pending writes snapshot + nonSkippedDelay(100) // makes possible to catch pending writes snapshot doc.set(FirestoreTimeTest.serializer(), FirestoreTimeTest("ServerTimestampBehavior", Timestamp.ServerTimestamp)) @@ -201,11 +199,9 @@ class FirebaseFirestoreTest { .document("test${Random.nextInt()}") val deferredPendingWritesSnapshot = async { - withTimeout(5000) { - doc.snapshots.filter { it.exists }.first() - } + doc.snapshots.filter { it.exists }.first() } - delay(100) // makes possible to catch pending writes snapshot + nonSkippedDelay(100) // makes possible to catch pending writes snapshot doc.set(FirestoreTimeTest.serializer(), FirestoreTimeTest("ServerTimestampBehavior", Timestamp.ServerTimestamp)) @@ -445,11 +441,9 @@ class FirebaseFirestoreTest { .document("test${Random.nextInt()}") val deferredPendingWritesSnapshot = async { - withTimeout(5000) { - doc.snapshots.filter { it.exists }.first() - } + doc.snapshots.filter { it.exists }.first() } - delay(100) // makes possible to catch pending writes snapshot + nonSkippedDelay(100) // makes possible to catch pending writes snapshot doc.set(DoubleTimestamp.serializer(), DoubleTimestamp(DoubleAsTimestampSerializer.serverTimestamp)) @@ -470,4 +464,8 @@ class FirebaseFirestoreTest { .document("three") .set(FirestoreTest.serializer(), FirestoreTest("ccc")) } + + private suspend fun nonSkippedDelay(timeout: Long) = withContext(Dispatchers.Default) { + delay(timeout) + } } diff --git a/firebase-firestore/src/jsTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/jsTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt index f4cc24ae9..e5037604f 100644 --- a/firebase-firestore/src/jsTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/jsTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -11,6 +11,4 @@ actual val emulatorHost: String = "localhost" actual val context: Any = Unit -actual fun runTest(test: suspend CoroutineScope.() -> Unit) { - runTest { test() } -} +actual fun runTest(test: suspend CoroutineScope.() -> Unit) = runTest { test() } diff --git a/firebase-perf/src/commonTest/kotlin/dev/gitlive/firebase/perf/performance.kt b/firebase-perf/src/commonTest/kotlin/dev/gitlive/firebase/perf/performance.kt index 5a69e221c..6f4fb98ac 100644 --- a/firebase-perf/src/commonTest/kotlin/dev/gitlive/firebase/perf/performance.kt +++ b/firebase-perf/src/commonTest/kotlin/dev/gitlive/firebase/perf/performance.kt @@ -9,11 +9,12 @@ import dev.gitlive.firebase.FirebaseOptions import dev.gitlive.firebase.apps import dev.gitlive.firebase.initialize import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.test.TestResult import kotlin.test.* expect val emulatorHost: String expect val context: Any -expect fun runTest(test: suspend CoroutineScope.() -> Unit) +expect fun runTest(test: suspend CoroutineScope.() -> Unit): TestResult class FirebasePerformanceTest { diff --git a/firebase-perf/src/jsTest/kotlin/dev/gitlive/firebase/perf/performance.kt b/firebase-perf/src/jsTest/kotlin/dev/gitlive/firebase/perf/performance.kt index 85fcd695b..7f68c87d2 100644 --- a/firebase-perf/src/jsTest/kotlin/dev/gitlive/firebase/perf/performance.kt +++ b/firebase-perf/src/jsTest/kotlin/dev/gitlive/firebase/perf/performance.kt @@ -15,9 +15,7 @@ actual val emulatorHost: String = "localhost" actual val context: Any = Unit -actual fun runTest(test: suspend CoroutineScope.() -> Unit) { - kotlinx.coroutines.test.runTest { test() } -} +actual fun runTest(test: suspend CoroutineScope.() -> Unit) = kotlinx.coroutines.test.runTest { test() } class JsPerformanceTest { From de2d1e2c2be57e9af05602361fddacc3a4749049 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Mon, 10 Apr 2023 01:31:50 +0300 Subject: [PATCH 23/28] Switch firebase-database tests to karma --- firebase-database/build.gradle.kts | 8 ++++---- .../kotlin/dev/gitlive/firebase/database/database.kt | 7 ++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/firebase-database/build.gradle.kts b/firebase-database/build.gradle.kts index 75620f425..d5f679569 100644 --- a/firebase-database/build.gradle.kts +++ b/firebase-database/build.gradle.kts @@ -70,15 +70,15 @@ kotlin { useCommonJs() nodejs { testTask { - useMocha { - timeout = "5s" + useKarma { + useChromeHeadless() } } } browser { testTask { - useMocha { - timeout = "5s" + useKarma { + useChromeHeadless() } } } diff --git a/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt index 08eb97c96..f40fcf915 100644 --- a/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsTest/kotlin/dev/gitlive/firebase/database/database.kt @@ -10,16 +10,13 @@ import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeout import kotlin.time.Duration.Companion.seconds -actual val emulatorHost: String = "127.0.0.1" // in JS connection is refused if we use localhost +actual val emulatorHost: String = "127.0.0.1" // in JS tests connection is refused if we use localhost actual val context: Any = Unit actual fun runTest(test: suspend () -> Unit) = kotlinx.coroutines.test.runTest { - val db = getDatabase() - goOnline(db) + // in JS tests we need to wait for the database to be connected awaitDatabaseConnection() test() - // in JS tests are running infinitely without going database offline - goOffline(db) } private suspend fun awaitDatabaseConnection() = withContext(Dispatchers.Default) { From 6e65b8a970f920b024ef7c8409ecaff9532a98e6 Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Mon, 10 Apr 2023 10:00:50 +0300 Subject: [PATCH 24/28] Increase JS tests timeout --- firebase-firestore/karma.config.d/karma.conf.js | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 firebase-firestore/karma.config.d/karma.conf.js diff --git a/firebase-firestore/karma.config.d/karma.conf.js b/firebase-firestore/karma.config.d/karma.conf.js new file mode 100644 index 000000000..e2301eddd --- /dev/null +++ b/firebase-firestore/karma.config.d/karma.conf.js @@ -0,0 +1,8 @@ +// Some tests are fluky in GitHub Actions, so we increase the timeout. +config.set({ + client: { + mocha: { + timeout: 5000 + } + }, +}); From f6d0156be3ac2c8ab3255973e84cfe2832572f6e Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Mon, 10 Apr 2023 12:10:41 +0300 Subject: [PATCH 25/28] Rename externals.kt to Unsubscribe.kt --- .../kotlin/dev/gitlive/firebase/{externals.kt => Unsubscribe.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/{externals.kt => Unsubscribe.kt} (100%) diff --git a/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt b/firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/Unsubscribe.kt similarity index 100% rename from firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/externals.kt rename to firebase-common/src/jsMain/kotlin/dev/gitlive/firebase/Unsubscribe.kt From fddc5b82249db079cba1d3b470520c3e7e718d3c Mon Sep 17 00:00:00 2001 From: Alex Shepeliev Date: Mon, 10 Apr 2023 15:13:10 +0300 Subject: [PATCH 26/28] Increase JS tests timeout for modules that interact with Firebase emulator --- firebase-auth/karma.config.d/karma.conf.js | 8 ++++++++ firebase-database/karma.config.d/karma.conf.js | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 firebase-auth/karma.config.d/karma.conf.js create mode 100644 firebase-database/karma.config.d/karma.conf.js diff --git a/firebase-auth/karma.config.d/karma.conf.js b/firebase-auth/karma.config.d/karma.conf.js new file mode 100644 index 000000000..e2301eddd --- /dev/null +++ b/firebase-auth/karma.config.d/karma.conf.js @@ -0,0 +1,8 @@ +// Some tests are fluky in GitHub Actions, so we increase the timeout. +config.set({ + client: { + mocha: { + timeout: 5000 + } + }, +}); diff --git a/firebase-database/karma.config.d/karma.conf.js b/firebase-database/karma.config.d/karma.conf.js new file mode 100644 index 000000000..e2301eddd --- /dev/null +++ b/firebase-database/karma.config.d/karma.conf.js @@ -0,0 +1,8 @@ +// Some tests are fluky in GitHub Actions, so we increase the timeout. +config.set({ + client: { + mocha: { + timeout: 5000 + } + }, +}); From be096bdf82e3ed1ccf20623a45809edf2a6164a1 Mon Sep 17 00:00:00 2001 From: nbransby Date: Mon, 28 Aug 2023 18:06:19 +0300 Subject: [PATCH 27/28] upgrade storage to js v9 --- .../gitlive/firebase/auth/externals/auth.kt | 2 +- .../kotlin/dev/gitlive/firebase/auth/user.kt | 2 +- .../dev/gitlive/firebase/database/database.kt | 2 +- .../firebase/database/externals/database.kt | 2 + .../gitlive/firebase/firestore/GeoPoint.kt | 2 +- .../firebase/firestore/externals/firestore.kt | 19 +++++- .../gitlive/firebase/firestore/firestore.kt | 2 +- .../dev/gitlive/firebase/storage/storage.kt | 7 +- .../dev/gitlive/firebase/storage/storage.kt | 4 ++ .../dev/gitlive/firebase/storage/storage.kt | 4 ++ .../firebase/storage/externals/storage.kt | 67 +++++++++++++++++++ .../dev/gitlive/firebase/storage/storage.kt | 38 ++++++----- .../gitlive/firebase/storage/storage.jvm.kt | 7 ++ 13 files changed, 134 insertions(+), 24 deletions(-) create mode 100644 firebase-storage/src/jsMain/kotlin/dev/gitlive/firebase/storage/externals/storage.kt 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 e27208d1b..0681ee8a6 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 @@ -95,7 +95,7 @@ external fun updatePassword(user: User, newPassword: String): Promise external fun updatePhoneNumber(user: User, phoneCredential: AuthCredential): Promise -external fun updateProfile(user: User, profile: ProfileUpdateRequest): Promise +external fun updateProfile(user: User, profile: Json): Promise external fun verifyBeforeUpdateEmail( user: User, diff --git a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt index e7181b49e..41570f0c2 100644 --- a/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt +++ b/firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/user.kt @@ -45,7 +45,7 @@ actual class FirebaseUser internal constructor(val js: User) { actual suspend fun updateEmail(email: String) = rethrow { updateEmail(js, email).await() } actual suspend fun updatePassword(password: String) = rethrow { updatePassword(js, password).await() } actual suspend fun updatePhoneNumber(credential: PhoneAuthCredential) = rethrow { updatePhoneNumber(js, credential.js).await() } - actual suspend fun updateProfile(displayName: String?, photoUrl: String?) = rethrow { + actual suspend fun updateProfile(displayName: String?, photoUrl: String?): Unit = rethrow { val request = listOfNotNull( displayName.takeUnless { it === UNCHANGED }?.let { "displayName" to it }, photoUrl.takeUnless { it === UNCHANGED }?.let { "photoURL" to it } diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt index faf7676dc..d4d47b6be 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt @@ -223,7 +223,7 @@ inline fun rethrow(function: () -> R): R { } } -suspend fun Promise.awaitWhileOnline(database: firebase.database.Database): T = coroutineScope { +suspend fun Promise.awaitWhileOnline(database: Database): T = coroutineScope { val notConnected = FirebaseDatabase(database) .reference(".info/connected") diff --git a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/database.kt b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/database.kt index 4621fcbd5..52f71422b 100644 --- a/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/database.kt +++ b/firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/externals/database.kt @@ -126,10 +126,12 @@ external interface ThenableReference : DatabaseReference external interface DataSnapshot { val key: String? val size: Int + val ref: DatabaseReference fun `val`(): Any fun exists(): Boolean fun forEach(action: (a: DataSnapshot) -> Boolean): Boolean fun child(path: String): DataSnapshot + fun hasChildren(): Boolean; } external interface OnDisconnect { diff --git a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/GeoPoint.kt b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/GeoPoint.kt index 808704cf5..9b14b7af3 100644 --- a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/GeoPoint.kt +++ b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/GeoPoint.kt @@ -4,7 +4,7 @@ import dev.gitlive.firebase.* import kotlinx.serialization.Serializable /** A class representing a platform specific Firebase GeoPoint. */ -actual typealias NativeGeoPoint = firebase.firestore.GeoPoint +actual typealias NativeGeoPoint = dev.gitlive.firebase.firestore.externals.GeoPoint /** A class representing a Firebase GeoPoint. */ @Serializable(with = GeoPointSerializer::class) diff --git a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt index 4e4399ab8..6fa365353 100644 --- a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt +++ b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt @@ -12,8 +12,12 @@ external class FieldPath(vararg fieldNames: String) { companion object { val documentId: FieldPath } + fun isEqual(other: FieldPath): Boolean + } +external fun refEqual(left: DocumentReference, right: DocumentReference): Boolean + external fun addDoc(reference: CollectionReference, data: Any): Promise external fun arrayRemove(vararg elements: Any): FieldValue @@ -81,6 +85,13 @@ external fun onSnapshot( error: (error: Throwable) -> Unit ): Unsubscribe +external fun onSnapshot( + reference: DocumentReference, + options: Json, + next: (snapshot: DocumentSnapshot) -> Unit, + error: (error: Throwable) -> Unit +): Unsubscribe + external fun onSnapshot( reference: Query, next: (snapshot: QuerySnapshot) -> Unit, @@ -150,6 +161,12 @@ external interface Firestore { val app: FirebaseApp } +external class GeoPoint constructor(latitude: Double, longitude: Double) { + val latitude: Double + val longitude: Double + fun isEqual(other: GeoPoint): Boolean +} + external interface CollectionReference : Query { val id: String val path: String @@ -163,7 +180,7 @@ external interface DocumentChange { val type: String } -external interface DocumentReference { +external class DocumentReference { val id: String val path: String val parent: CollectionReference diff --git a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt index 33dd2d0c8..46833d684 100644 --- a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt +++ b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt @@ -282,7 +282,7 @@ actual class DocumentReference actual constructor(internal actual val nativeValu } override fun equals(other: Any?): Boolean = - this === other || other is DocumentReference && nativeValue.isEqual(other.nativeValue) + this === other || other is DocumentReference && refEqual(nativeValue, other.nativeValue) override fun hashCode(): Int = nativeValue.hashCode() override fun toString(): String = "DocumentReference(path=$path)" } diff --git a/firebase-storage/src/androidMain/kotlin/dev/gitlive/firebase/storage/storage.kt b/firebase-storage/src/androidMain/kotlin/dev/gitlive/firebase/storage/storage.kt index af32eea56..868d380a5 100644 --- a/firebase-storage/src/androidMain/kotlin/dev/gitlive/firebase/storage/storage.kt +++ b/firebase-storage/src/androidMain/kotlin/dev/gitlive/firebase/storage/storage.kt @@ -43,7 +43,10 @@ actual class FirebaseStorage(val android: com.google.firebase.storage.FirebaseSt android.useEmulator(host, port) } - actual val reference = StorageReference(android.reference) + actual val reference get() = StorageReference(android.reference) + + actual fun reference(location: String )= StorageReference(android.getReference(location)) + } actual class StorageReference(val android: com.google.firebase.storage.StorageReference) { @@ -62,6 +65,8 @@ actual class StorageReference(val android: com.google.firebase.storage.StorageRe actual suspend fun listAll(): ListResult = ListResult(android.listAll().await()) + actual suspend fun putFile(file: File) = android.putFile(file.uri).await().run {} + actual fun putFileResumable(file: File): ProgressFlow { val android = android.putFile(file.uri) diff --git a/firebase-storage/src/commonMain/kotlin/dev/gitlive/firebase/storage/storage.kt b/firebase-storage/src/commonMain/kotlin/dev/gitlive/firebase/storage/storage.kt index 949d8d425..ada31266b 100644 --- a/firebase-storage/src/commonMain/kotlin/dev/gitlive/firebase/storage/storage.kt +++ b/firebase-storage/src/commonMain/kotlin/dev/gitlive/firebase/storage/storage.kt @@ -20,6 +20,8 @@ expect class FirebaseStorage { fun useEmulator(host: String, port: Int) val reference: StorageReference + fun reference(location: String): StorageReference + } expect class StorageReference { @@ -38,6 +40,8 @@ expect class StorageReference { suspend fun listAll(): ListResult + suspend fun putFile(file: File) + fun putFileResumable(file: File): ProgressFlow } diff --git a/firebase-storage/src/iosMain/kotlin/dev/gitlive/firebase/storage/storage.kt b/firebase-storage/src/iosMain/kotlin/dev/gitlive/firebase/storage/storage.kt index e554a574c..3a988926e 100644 --- a/firebase-storage/src/iosMain/kotlin/dev/gitlive/firebase/storage/storage.kt +++ b/firebase-storage/src/iosMain/kotlin/dev/gitlive/firebase/storage/storage.kt @@ -50,6 +50,8 @@ actual class FirebaseStorage(val ios: FIRStorage) { } actual val reference get() = StorageReference(ios.reference()) + + actual fun reference(location: String) = StorageReference(ios.referenceWithPath(location)) } actual class StorageReference(val ios: FIRStorageReference) { @@ -74,6 +76,8 @@ actual class StorageReference(val ios: FIRStorageReference) { } } + actual suspend fun putFile(file: File) = ios.awaitResult { putFile(file.url, null, completion = it) }.run {} + actual fun putFileResumable(file: File): ProgressFlow { val ios = ios.putFile(file.url) diff --git a/firebase-storage/src/jsMain/kotlin/dev/gitlive/firebase/storage/externals/storage.kt b/firebase-storage/src/jsMain/kotlin/dev/gitlive/firebase/storage/externals/storage.kt new file mode 100644 index 000000000..dbd7768d4 --- /dev/null +++ b/firebase-storage/src/jsMain/kotlin/dev/gitlive/firebase/storage/externals/storage.kt @@ -0,0 +1,67 @@ +@file:JsModule("firebase/storage") +@file:JsNonModule + +package dev.gitlive.firebase.storage.externals + +import dev.gitlive.firebase.externals.FirebaseApp +import kotlin.js.Promise + +external fun getStorage(app: FirebaseApp? = definedExternally): FirebaseStorage + +external fun ref(storage: FirebaseStorage, url: String? = definedExternally): StorageReference +external fun ref(ref: StorageReference, url: String? = definedExternally): StorageReference + +external fun getDownloadURL(ref: StorageReference): Promise + +external fun uploadBytes(ref: StorageReference, file: dynamic): Promise + +external fun uploadBytesResumable(ref: StorageReference, data: dynamic): UploadTask + +external fun deleteObject(ref: StorageReference): Promise; + +external fun listAll(ref: StorageReference): Promise; + +external fun connectFirestoreEmulator( + storage: FirebaseStorage, + host: String, + port: Double, + options: Any? = definedExternally +) + +external interface FirebaseStorage { + var maxOperationRetryTime: Double + var maxUploadRetryTime: Double +} + +external interface StorageReference { + val bucket: String + val fullPath: String + val name: String + val parent: StorageReference? + val root: StorageReference + val storage: FirebaseStorage +} + +external open class ListResult { + val items: Array + val nextPageToken: String + val prefixes: Array +} + +external interface StorageError + +external interface UploadTaskSnapshot { + val bytesTransferred: Number + val ref: StorageReference + val state: String + val task: UploadTask + val totalBytes: Number +} + +external class UploadTask : Promise { + fun cancel(): Boolean; + fun on(event: String, next: (snapshot: UploadTaskSnapshot) -> Unit, error: (a: StorageError) -> Unit, complete: () -> Unit): () -> Unit + fun pause(): Boolean; + fun resume(): Boolean; + val snapshot: UploadTaskSnapshot +} diff --git a/firebase-storage/src/jsMain/kotlin/dev/gitlive/firebase/storage/storage.kt b/firebase-storage/src/jsMain/kotlin/dev/gitlive/firebase/storage/storage.kt index ea7e51bab..9ba0380d5 100644 --- a/firebase-storage/src/jsMain/kotlin/dev/gitlive/firebase/storage/storage.kt +++ b/firebase-storage/src/jsMain/kotlin/dev/gitlive/firebase/storage/storage.kt @@ -7,7 +7,7 @@ package dev.gitlive.firebase.storage import dev.gitlive.firebase.Firebase import dev.gitlive.firebase.FirebaseApp import dev.gitlive.firebase.FirebaseException -import dev.gitlive.firebase.firebase +import dev.gitlive.firebase.storage.externals.* import kotlinx.coroutines.await import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.awaitClose @@ -15,33 +15,35 @@ import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.emitAll - -actual val Firebase.storage get() = - rethrow { dev.gitlive.firebase.storage; FirebaseStorage(firebase.storage()) } +actual val Firebase.storage + get() = FirebaseStorage(getStorage()) actual fun Firebase.storage(app: FirebaseApp) = - rethrow { dev.gitlive.firebase.storage; FirebaseStorage(firebase.app().storage()) } + FirebaseStorage(getStorage(app.js)) -actual class FirebaseStorage(val js: firebase.storage.Storage) { +actual class FirebaseStorage(val js: dev.gitlive.firebase.storage.externals.FirebaseStorage) { actual val maxOperationRetryTimeMillis = js.maxOperationRetryTime.toLong() actual val maxUploadRetryTimeMillis = js.maxUploadRetryTime.toLong() actual fun setMaxOperationRetryTimeMillis(maxOperationRetryTimeMillis: Long) { - js.setMaxOperationRetryTime(maxOperationRetryTimeMillis.toDouble()) + js.maxOperationRetryTime = maxOperationRetryTimeMillis.toDouble() } actual fun setMaxUploadRetryTimeMillis(maxUploadRetryTimeMillis: Long) { - js.setMaxUploadRetryTime(maxUploadRetryTimeMillis.toDouble()) + js.maxUploadRetryTime = maxUploadRetryTimeMillis.toDouble() } actual fun useEmulator(host: String, port: Int) { - js.useEmulator(host, port) + connectFirestoreEmulator(js, host, port.toDouble()) } - actual val reference: StorageReference get() = StorageReference(js.ref()) + actual val reference: StorageReference get() = StorageReference(ref(js)) + + actual fun reference(location: String) = rethrow { StorageReference(ref(js, location)) } + } -actual class StorageReference(val js: firebase.storage.Reference) { +actual class StorageReference(val js: dev.gitlive.firebase.storage.externals.StorageReference) { actual val path: String get() = js.fullPath actual val name: String get() = js.name actual val bucket: String get() = js.bucket @@ -49,16 +51,18 @@ actual class StorageReference(val js: firebase.storage.Reference) { actual val root: StorageReference get() = StorageReference(js.root) actual val storage: FirebaseStorage get() = FirebaseStorage(js.storage) - actual fun child(path: String): StorageReference = StorageReference(js.child(path)) + actual fun child(path: String): StorageReference = StorageReference(ref(js, path)) + + actual suspend fun delete() = rethrow { deleteObject(js).await() } - actual suspend fun delete() = rethrow { js.delete().await() } + actual suspend fun getDownloadUrl(): String = rethrow { getDownloadURL(js).await().toString() } - actual suspend fun getDownloadUrl(): String = rethrow { js.getDownloadURL().await().toString() } + actual suspend fun listAll(): ListResult = rethrow { ListResult(listAll(js).await()) } - actual suspend fun listAll(): ListResult = rethrow { ListResult(js.listAll().await()) } + actual suspend fun putFile(file: File): Unit = rethrow { uploadBytes(js, file).await() } actual fun putFileResumable(file: File): ProgressFlow = rethrow { - val uploadTask = js.put(file) + val uploadTask = uploadBytesResumable(js, file) val flow = callbackFlow { val unsubscribe = uploadTask.on( @@ -88,7 +92,7 @@ actual class StorageReference(val js: firebase.storage.Reference) { } -actual class ListResult(js: firebase.storage.ListResult) { +actual class ListResult(js: dev.gitlive.firebase.storage.externals.ListResult) { actual val prefixes: List = js.prefixes.map { StorageReference(it) } actual val items: List = js.items.map { StorageReference(it) } actual val pageToken: String? = js.nextPageToken diff --git a/firebase-storage/src/jvmMain/kotlin/dev/gitlive/firebase/storage/storage.jvm.kt b/firebase-storage/src/jvmMain/kotlin/dev/gitlive/firebase/storage/storage.jvm.kt index 284915533..2d1f07ca4 100644 --- a/firebase-storage/src/jvmMain/kotlin/dev/gitlive/firebase/storage/storage.jvm.kt +++ b/firebase-storage/src/jvmMain/kotlin/dev/gitlive/firebase/storage/storage.jvm.kt @@ -31,6 +31,10 @@ actual class FirebaseStorage { actual val reference: StorageReference get() = TODO("Not yet implemented") + actual fun reference(location: String): StorageReference { + TODO("Not yet implemented") + } + } actual class StorageReference { @@ -66,6 +70,9 @@ actual class StorageReference { TODO("Not yet implemented") } + actual suspend fun putFile(file: File) { + } + } actual class ListResult { From a7e335fe6be4d969976b863be46d0da90b313981 Mon Sep 17 00:00:00 2001 From: nbransby Date: Tue, 29 Aug 2023 01:55:23 +0300 Subject: [PATCH 28/28] fix js tests --- firebase-app/package.json | 4 +-- firebase-auth/package.json | 4 +-- firebase-common/package.json | 2 +- firebase-config/package.json | 4 +-- firebase-crashlytics/package.json | 4 +-- firebase-database/package.json | 4 +-- firebase-firestore/package.json | 4 +-- .../firebase/firestore/TimestampTests.kt | 13 ++++----- .../gitlive/firebase/firestore/firestore.kt | 27 ++++++++++--------- .../gitlive/firebase/firestore/Timestamp.kt | 2 +- firebase-functions/package.json | 4 +-- firebase-installations/package.json | 4 +-- firebase-perf/package.json | 4 +-- firebase-storage/package.json | 4 +-- gradle.properties | 22 +++++++-------- test/firebase.json | 3 +++ 16 files changed, 57 insertions(+), 52 deletions(-) diff --git a/firebase-app/package.json b/firebase-app/package.json index 2f5402a70..ad462e03f 100644 --- a/firebase-app/package.json +++ b/firebase-app/package.json @@ -1,6 +1,6 @@ { "name": "@gitlive/firebase-app", - "version": "1.9.2", + "version": "1.10.0", "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": "1.9.2", + "@gitlive/firebase-common": "1.10.0", "firebase": "9.19.1", "kotlin": "1.8.20", "kotlinx-coroutines-core": "1.6.4" diff --git a/firebase-auth/package.json b/firebase-auth/package.json index ccc83d566..fe344e504 100644 --- a/firebase-auth/package.json +++ b/firebase-auth/package.json @@ -1,6 +1,6 @@ { "name": "@gitlive/firebase-auth", - "version": "1.9.2", + "version": "1.10.0", "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": "1.9.2", + "@gitlive/firebase-app": "1.10.0", "firebase": "9.19.1", "kotlin": "1.8.20", "kotlinx-coroutines-core": "1.6.4" diff --git a/firebase-common/package.json b/firebase-common/package.json index 08f0a1368..ad254de8f 100644 --- a/firebase-common/package.json +++ b/firebase-common/package.json @@ -1,6 +1,6 @@ { "name": "@gitlive/firebase-common", - "version": "1.9.2", + "version": "1.10.0", "description": "Wrapper around firebase for usage in Kotlin Multiplatform projects", "main": "firebase-common.js", "scripts": { diff --git a/firebase-config/package.json b/firebase-config/package.json index b8b7d0d22..195116866 100644 --- a/firebase-config/package.json +++ b/firebase-config/package.json @@ -1,6 +1,6 @@ { "name": "@gitlive/firebase-config", - "version": "1.9.2", + "version": "1.10.0", "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": "1.9.2", + "@gitlive/firebase-app": "1.10.0", "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 57cbcfa3f..1a32ade20 100644 --- a/firebase-crashlytics/package.json +++ b/firebase-crashlytics/package.json @@ -1,6 +1,6 @@ { "name": "@gitlive/firebase-crashlytics", - "version": "1.9.2", + "version": "1.10.0", "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": "1.9.2", + "@gitlive/firebase-app": "1.10.0", "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 0542e3f4d..966515c71 100644 --- a/firebase-database/package.json +++ b/firebase-database/package.json @@ -1,6 +1,6 @@ { "name": "@gitlive/firebase-database", - "version": "1.9.2", + "version": "1.10.0", "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": "1.9.2", + "@gitlive/firebase-app": "1.10.0", "firebase": "9.19.1", "kotlin": "1.8.20", "kotlinx-coroutines-core": "1.6.4" diff --git a/firebase-firestore/package.json b/firebase-firestore/package.json index 74e91d3fc..dd417f8b3 100644 --- a/firebase-firestore/package.json +++ b/firebase-firestore/package.json @@ -1,6 +1,6 @@ { "name": "@gitlive/firebase-firestore", - "version": "1.9.2", + "version": "1.10.0", "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": "1.9.2", + "@gitlive/firebase-app": "1.10.0", "firebase": "9.19.1", "kotlin": "1.8.20", "kotlinx-coroutines-core": "1.6.4" diff --git a/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/TimestampTests.kt b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/TimestampTests.kt index d310df37b..21ceaf2e4 100644 --- a/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/TimestampTests.kt +++ b/firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/TimestampTests.kt @@ -68,7 +68,7 @@ class TimestampTests { "updatedAt" to timestamp.nativeValue, "deletedAt" to timestamp.nativeValue ) - val decoded: TestData = decode(obj) + val decoded: TestData = decode(TestData.serializer(), obj) assertEquals("uid123", decoded.uid) with(decoded.createdAt) { assertEquals(timestamp, this) @@ -95,7 +95,7 @@ class TimestampTests { "updatedAt" to Timestamp.now().nativeValue, "deletedAt" to null ) - val decoded: TestData = decode(obj) + val decoded: TestData = decode(TestData.serializer(), obj) assertEquals("uid123", decoded.uid) assertNotNull(decoded.updatedAt) assertNull(decoded.deletedAt) @@ -103,10 +103,11 @@ class TimestampTests { @Test fun serializers() = runTest { - assertEquals(BaseTimestampSerializer, (Timestamp(0, 0) as BaseTimestamp).firebaseSerializer()) - assertEquals(BaseTimestampSerializer, (Timestamp.ServerTimestamp as BaseTimestamp).firebaseSerializer()) - assertEquals(TimestampSerializer, Timestamp(0, 0).firebaseSerializer()) - assertEquals(ServerTimestampSerializer, Timestamp.ServerTimestamp.firebaseSerializer()) + //todo dont work in js due to use of reified type in firebaseSerializer - uncomment once switched to IR +// assertEquals(BaseTimestampSerializer, (Timestamp(0, 0) as BaseTimestamp).firebaseSerializer()) +// assertEquals(BaseTimestampSerializer, (Timestamp.ServerTimestamp as BaseTimestamp).firebaseSerializer()) +// assertEquals(TimestampSerializer, Timestamp(0, 0).firebaseSerializer()) +// assertEquals(ServerTimestampSerializer, Timestamp.ServerTimestamp.firebaseSerializer()) } @Test 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 c31151335..86c180622 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 @@ -17,6 +17,7 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.TestResult import kotlinx.coroutines.withContext import kotlinx.serialization.Serializable +import kotlinx.serialization.builtins.nullable import kotlin.random.Random import kotlin.test.BeforeTest import kotlin.test.Test @@ -148,7 +149,7 @@ class FirebaseFirestoreTest { doc.set(FirestoreTimeTest.serializer(), FirestoreTimeTest("ServerTimestamp", Timestamp.ServerTimestamp)) - assertNotEquals(Timestamp.ServerTimestamp, doc.get().get("time")) + assertNotEquals(Timestamp.ServerTimestamp, doc.get().get("time", BaseTimestamp.serializer())) assertNotEquals(Timestamp.ServerTimestamp, doc.get().data(FirestoreTimeTest.serializer()).time) } @@ -170,7 +171,7 @@ class FirebaseFirestoreTest { val pendingWritesSnapshot = deferredPendingWritesSnapshot.await() assertTrue(pendingWritesSnapshot.metadata.hasPendingWrites) - assertNull(pendingWritesSnapshot.get("time", ServerTimestampBehavior.NONE)) + assertNull(pendingWritesSnapshot.get("time", BaseTimestamp.serializer().nullable, ServerTimestampBehavior.NONE)) } @Test @@ -188,7 +189,7 @@ class FirebaseFirestoreTest { val pendingWritesSnapshot = deferredPendingWritesSnapshot.await() assertTrue(pendingWritesSnapshot.metadata.hasPendingWrites) - assertNotNull(pendingWritesSnapshot.get("time", ServerTimestampBehavior.ESTIMATE)) + assertNotNull(pendingWritesSnapshot.get("time", BaseTimestamp.serializer().nullable, ServerTimestampBehavior.ESTIMATE)) assertNotEquals(Timestamp.ServerTimestamp, pendingWritesSnapshot.data(FirestoreTimeTest.serializer(), ServerTimestampBehavior.ESTIMATE).time) } @@ -207,7 +208,7 @@ class FirebaseFirestoreTest { val pendingWritesSnapshot = deferredPendingWritesSnapshot.await() assertTrue(pendingWritesSnapshot.metadata.hasPendingWrites) - assertNull(pendingWritesSnapshot.get("time", ServerTimestampBehavior.PREVIOUS)) + assertNull(pendingWritesSnapshot.get("time", BaseTimestamp.serializer().nullable, ServerTimestampBehavior.PREVIOUS)) } @Test @@ -472,9 +473,9 @@ class FirebaseFirestoreTest { val ms = 12345678.0 - doc.set(LegacyDocument(time = ms)) + doc.set(LegacyDocument.serializer(), LegacyDocument(time = ms)) - val fetched: NewDocument = doc.get().data() + val fetched: NewDocument = doc.get().data(NewDocument.serializer()) assertEquals(ms, fetched.time.toMilliseconds()) } @@ -488,27 +489,27 @@ class FirebaseFirestoreTest { val collection = Firebase.firestore .collection("testQueryByTimestamp") - val timestamp = Timestamp.now() + 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(pastTimestamp)) - collection.add(DocumentWithTimestamp(futureTimestamp)) + collection.add(DocumentWithTimestamp.serializer(), DocumentWithTimestamp(pastTimestamp)) + collection.add(DocumentWithTimestamp.serializer(), DocumentWithTimestamp(futureTimestamp)) val equalityQueryResult = collection.where( path = FieldPath(DocumentWithTimestamp::time.name), equalTo = pastTimestamp - ).get().documents.map { it.data() } + ).get().documents.map { it.data(DocumentWithTimestamp.serializer()) }.toSet() - assertEquals(listOf(DocumentWithTimestamp(pastTimestamp)), equalityQueryResult) + assertEquals(setOf(DocumentWithTimestamp(pastTimestamp)), equalityQueryResult) val gtQueryResult = collection.where( path = FieldPath(DocumentWithTimestamp::time.name), greaterThan = timestamp - ).get().documents.map { it.data() } + ).get().documents.map { it.data(DocumentWithTimestamp.serializer()) }.toSet() - assertEquals(listOf(DocumentWithTimestamp(futureTimestamp)), gtQueryResult) + assertEquals(setOf(DocumentWithTimestamp(futureTimestamp)), gtQueryResult) } private suspend fun setupFirestoreData() { diff --git a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt index 32c630839..dabec0055 100644 --- a/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt +++ b/firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt @@ -21,7 +21,7 @@ actual class Timestamp internal actual constructor( override fun equals(other: Any?): Boolean = this === other || other is Timestamp && nativeValue.isEqual(other.nativeValue) - override fun hashCode(): Int = nativeValue.hashCode() + override fun hashCode(): Int = nativeValue.toMillis().hashCode() override fun toString(): String = nativeValue.toString() actual companion object { diff --git a/firebase-functions/package.json b/firebase-functions/package.json index ffbab6376..e0db81fe6 100644 --- a/firebase-functions/package.json +++ b/firebase-functions/package.json @@ -1,6 +1,6 @@ { "name": "@gitlive/firebase-functions", - "version": "1.9.2", + "version": "1.10.0", "description": "Wrapper around firebase for usage in Kotlin Multiplatform projects", "main": "firebase-functions.js", "scripts": { @@ -23,7 +23,7 @@ }, "homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk", "dependencies": { - "@gitlive/firebase-app": "1.9.2", + "@gitlive/firebase-app": "1.10.0", "firebase": "9.19.1", "kotlin": "1.8.20", "kotlinx-coroutines-core": "1.6.4" diff --git a/firebase-installations/package.json b/firebase-installations/package.json index 8a5b64500..94aaac8c5 100644 --- a/firebase-installations/package.json +++ b/firebase-installations/package.json @@ -1,6 +1,6 @@ { "name": "@gitlive/firebase-installations", - "version": "1.9.2", + "version": "1.10.0", "description": "Wrapper around firebase for usage in Kotlin Multiplatform projects", "main": "firebase-installations.js", "scripts": { @@ -23,7 +23,7 @@ }, "homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk", "dependencies": { - "@gitlive/firebase-app": "1.9.2", + "@gitlive/firebase-app": "1.10.0", "firebase": "9.19.1", "kotlin": "1.8.20", "kotlinx-coroutines-core": "1.6.4" diff --git a/firebase-perf/package.json b/firebase-perf/package.json index 4c9accf57..ac32fe16c 100644 --- a/firebase-perf/package.json +++ b/firebase-perf/package.json @@ -1,6 +1,6 @@ { "name": "@gitlive/firebase-perf", - "version": "1.9.2", + "version": "1.10.0", "description": "Wrapper around firebase for usage in Kotlin Multiplatform projects", "main": "firebase-perf.js", "scripts": { @@ -23,7 +23,7 @@ }, "homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk", "dependencies": { - "@gitlive/firebase-app": "1.9.2", + "@gitlive/firebase-app": "1.10.0", "firebase": "9.19.1", "kotlin": "1.6.10", "kotlinx-coroutines-core": "1.6.1-native-mt" diff --git a/firebase-storage/package.json b/firebase-storage/package.json index a5d56c9a3..6b757c5ec 100644 --- a/firebase-storage/package.json +++ b/firebase-storage/package.json @@ -1,6 +1,6 @@ { "name": "@gitlive/firebase-storage", - "version": "1.9.2", + "version": "1.10.0", "description": "Wrapper around firebase for usage in Kotlin Multiplatform projects", "main": "firebase-storage.js", "scripts": { @@ -23,7 +23,7 @@ }, "homepage": "https://github.com/GitLiveApp/firebase-kotlin-sdk", "dependencies": { - "@gitlive/firebase-app": "1.9.2", + "@gitlive/firebase-app": "1.10.0", "firebase": "9.19.1", "kotlin": "1.6.10", "kotlinx-coroutines-core": "1.6.1-native-mt" diff --git a/gradle.properties b/gradle.properties index 1973c550b..6384d22a4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -49,14 +49,14 @@ firebase-perf.skipJsTests=false firebase-storage.skipJsTests=false # Versions: -firebase-app.version=1.9.2 -firebase-auth.version=1.9.2 -firebase-common.version=1.9.2 -firebase-config.version=1.9.2 -firebase-database.version=1.9.2 -firebase-firestore.version=1.9.2 -firebase-functions.version=1.9.2 -firebase-installations.version=1.9.2 -firebase-perf.version=1.9.2 -firebase-crashlytics.version=1.9.2 -firebase-storage.version=1.9.2 +firebase-app.version=1.10.0 +firebase-auth.version=1.10.0 +firebase-common.version=1.10.0 +firebase-config.version=1.10.0 +firebase-database.version=1.10.0 +firebase-firestore.version=1.10.0 +firebase-functions.version=1.10.0 +firebase-installations.version=1.10.0 +firebase-perf.version=1.10.0 +firebase-crashlytics.version=1.10.0 +firebase-storage.version=1.10.0 diff --git a/test/firebase.json b/test/firebase.json index fa2ab410a..5b55e4f2c 100644 --- a/test/firebase.json +++ b/test/firebase.json @@ -2,6 +2,9 @@ "firestore": { "rules": "firestore.rules" }, + "storage": { + "rules": "storage.rules" + }, "database": { "rules": "database.rules.json" },