5
5
package dev.gitlive.firebase.database
6
6
7
7
import dev.gitlive.firebase.*
8
- import kotlinx.coroutines.await
8
+ import kotlinx.coroutines.*
9
9
import kotlinx.coroutines.channels.awaitClose
10
10
import kotlinx.coroutines.flow.callbackFlow
11
+ import kotlinx.coroutines.flow.filter
12
+ import kotlinx.coroutines.flow.produceIn
13
+ import kotlinx.coroutines.selects.select
11
14
import kotlinx.serialization.DeserializationStrategy
12
15
import kotlinx.serialization.SerializationStrategy
16
+ import kotlin.js.Promise
13
17
14
18
@PublishedApi
15
19
internal inline fun <reified T > encode (value : T , shouldEncodeElementDefault : Boolean ) =
@@ -113,16 +117,16 @@ actual class DatabaseReference internal constructor(override val js: firebase.da
113
117
actual fun onDisconnect () = rethrow { OnDisconnect (js.onDisconnect()) }
114
118
115
119
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 () }
117
121
118
- actual suspend fun removeValue () = rethrow { js.remove().await () }
122
+ actual suspend fun removeValue () = rethrow { js.remove().awaitWhileOnline () }
119
123
120
124
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 ()
122
126
}
123
127
124
128
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 () }
126
130
}
127
131
128
132
actual class DataSnapshot internal constructor(val js : firebase.database.DataSnapshot ) {
@@ -147,17 +151,17 @@ actual class DataSnapshot internal constructor(val js: firebase.database.DataSna
147
151
148
152
actual class OnDisconnect internal constructor(val js : firebase.database.OnDisconnect ) {
149
153
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 () }
152
156
153
157
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 () }
155
159
156
160
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 () }
158
162
159
163
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 () }
161
165
}
162
166
163
167
actual class DatabaseException (error : dynamic ) :
@@ -174,3 +178,18 @@ inline fun <R> rethrow(function: () -> R): R {
174
178
throw DatabaseException (e)
175
179
}
176
180
}
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