55package dev.gitlive.firebase.database
66
77import dev.gitlive.firebase.*
8- import kotlinx.coroutines.await
8+ import kotlinx.coroutines.*
99import kotlinx.coroutines.channels.awaitClose
1010import kotlinx.coroutines.flow.callbackFlow
11+ import kotlinx.coroutines.flow.filter
12+ import kotlinx.coroutines.flow.produceIn
13+ import kotlinx.coroutines.selects.select
1114import kotlinx.serialization.DeserializationStrategy
1215import kotlinx.serialization.SerializationStrategy
16+ import kotlin.js.Promise
1317
1418@PublishedApi
1519internal inline fun <reified T > encode (value : T , shouldEncodeElementDefault : Boolean ) =
@@ -113,16 +117,16 @@ actual class DatabaseReference internal constructor(override val js: firebase.da
113117 actual fun onDisconnect () = rethrow { OnDisconnect (js.onDisconnect()) }
114118
115119 actual suspend fun updateChildren (update : Map <String , Any ?>, encodeDefaults : Boolean ) =
116- rethrow { js.update(encode(update, encodeDefaults)).await () }
120+ rethrow { js.update(encode(update, encodeDefaults)).awaitWhileOnline () }
117121
118- actual suspend fun removeValue () = rethrow { js.remove().await () }
122+ actual suspend fun removeValue () = rethrow { js.remove().awaitWhileOnline () }
119123
120124 actual suspend inline fun <reified T > setValue (value : T ? , encodeDefaults : Boolean ) = rethrow {
121- js.set(encode(value, encodeDefaults)).await ()
125+ js.set(encode(value, encodeDefaults)).awaitWhileOnline ()
122126 }
123127
124128 actual suspend fun <T > setValue (strategy : SerializationStrategy <T >, value : T , encodeDefaults : Boolean ) =
125- rethrow { js.set(encode(strategy, value, encodeDefaults)).await () }
129+ rethrow { js.set(encode(strategy, value, encodeDefaults)).awaitWhileOnline () }
126130}
127131
128132actual class DataSnapshot internal constructor(val js : firebase.database.DataSnapshot ) {
@@ -147,17 +151,17 @@ actual class DataSnapshot internal constructor(val js: firebase.database.DataSna
147151
148152actual class OnDisconnect internal constructor(val js : firebase.database.OnDisconnect ) {
149153
150- actual suspend fun removeValue () = rethrow { js.remove().await () }
151- actual suspend fun cancel () = rethrow { js.cancel().await () }
154+ actual suspend fun removeValue () = rethrow { js.remove().awaitWhileOnline () }
155+ actual suspend fun cancel () = rethrow { js.cancel().awaitWhileOnline () }
152156
153157 actual suspend fun updateChildren (update : Map <String , Any ?>, encodeDefaults : Boolean ) =
154- rethrow { js.update(encode(update, encodeDefaults)).await () }
158+ rethrow { js.update(encode(update, encodeDefaults)).awaitWhileOnline () }
155159
156160 actual suspend inline fun <reified T > setValue (value : T , encodeDefaults : Boolean ) =
157- rethrow { js.set(encode(value, encodeDefaults)).await () }
161+ rethrow { js.set(encode(value, encodeDefaults)).awaitWhileOnline () }
158162
159163 actual suspend fun <T > setValue (strategy : SerializationStrategy <T >, value : T , encodeDefaults : Boolean ) =
160- rethrow { js.set(encode(strategy, value, encodeDefaults)).await () }
164+ rethrow { js.set(encode(strategy, value, encodeDefaults)).awaitWhileOnline () }
161165}
162166
163167actual class DatabaseException (error : dynamic ) :
@@ -174,3 +178,18 @@ inline fun <R> rethrow(function: () -> R): R {
174178 throw DatabaseException (e)
175179 }
176180}
181+
182+ suspend fun <T > Promise<T>.awaitWhileOnline (): T = coroutineScope {
183+
184+ val notConnected = Firebase .database
185+ .reference(" .info/connected" )
186+ .valueEvents
187+ .filter { ! it.value<Boolean >() }
188+ .produceIn(this )
189+
190+ select<T > {
191+ this @awaitWhileOnline.asDeferred().onAwait { it.also { notConnected.cancel() } }
192+ notConnected.onReceive { throw DatabaseException (" Database not connected" ) }
193+ }
194+
195+ }
0 commit comments