Skip to content

Commit 647934b

Browse files
committed
make ServerValue.TIMESTAMP a double
add Query.startAt add DatabaseReference.key
1 parent 6aa0f61 commit 647934b

File tree

7 files changed

+59
-27
lines changed

7 files changed

+59
-27
lines changed

firebase-common/src/androidMain/kotlin/dev/teamhub/firebase/_encoders.kt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,13 @@ import kotlinx.serialization.CompositeEncoder
44
import kotlinx.serialization.KSerializer
55
import kotlinx.serialization.SerialDescriptor
66
import kotlinx.serialization.StructureKind
7-
import kotlin.collections.mutableListOf
8-
import kotlin.collections.mutableMapOf
97
import kotlin.collections.set
108

119
actual fun FirebaseEncoder.structureEncoder(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeEncoder = when(desc.kind as StructureKind) {
1210
StructureKind.LIST -> mutableListOf<Any?>()
1311
.also { value = it }
14-
.let { FirebaseCompositeEncoder { _, index, value -> it.add(index, value) } }
12+
.let { FirebaseCompositeEncoder(positiveInfinity) { _, index, value -> it.add(index, value) } }
1513
StructureKind.MAP, StructureKind.CLASS -> mutableMapOf<Any?, Any?>()
1614
.also { value = it }
17-
.let { FirebaseCompositeEncoder { _, index, value -> it[desc.getElementName(index)] = value } }
15+
.let { FirebaseCompositeEncoder(positiveInfinity) { _, index, value -> it[desc.getElementName(index)] = value } }
1816
}

firebase-common/src/commonMain/kotlin/dev/teamhub/firebase/encoders.kt

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ package dev.teamhub.firebase
33
import kotlinx.serialization.*
44
import kotlinx.serialization.modules.EmptyModule
55

6-
fun <T> encode(strategy: SerializationStrategy<T> , value: T): Any? = FirebaseEncoder().apply { encode(strategy, value) }.value
6+
fun <T> encode(strategy: SerializationStrategy<T> , value: T, positiveInfinity: Any = Double.POSITIVE_INFINITY): Any? =
7+
FirebaseEncoder(positiveInfinity).apply { encode(strategy, value) }.value
78

89
@ImplicitReflectionSerializer
9-
fun encode(value: Any?): Any? = value?.let {
10-
FirebaseEncoder().apply { encode(it.firebaseSerializer(), it) }.value
10+
fun encode(value: Any?, positiveInfinity: Any = Double.POSITIVE_INFINITY): Any? = value?.let {
11+
FirebaseEncoder(positiveInfinity).apply { encode(it.firebaseSerializer(), it) }.value
1112
}
1213

1314
expect fun FirebaseEncoder.structureEncoder(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeEncoder
1415

15-
class FirebaseEncoder : Encoder {
16+
class FirebaseEncoder(positiveInfinity: Any) : TimestampEncoder(positiveInfinity), Encoder {
1617

1718
var value: Any? = null
1819

@@ -33,7 +34,7 @@ class FirebaseEncoder : Encoder {
3334
}
3435

3536
override fun encodeDouble(value: Double) {
36-
this.value = value
37+
this.value = encodeTimestamp(value)
3738
}
3839

3940
override fun encodeEnum(enumDescription: SerialDescriptor, ordinal: Int) {
@@ -74,10 +75,18 @@ class FirebaseEncoder : Encoder {
7475

7576
}
7677

78+
abstract class TimestampEncoder(internal val positiveInfinity: Any) {
79+
fun encodeTimestamp(value: Double) = when(value) {
80+
Double.POSITIVE_INFINITY -> positiveInfinity
81+
else -> value
82+
}
83+
}
84+
7785
open class FirebaseCompositeEncoder(
86+
positiveInfinity: Any,
7887
private val end: () -> Unit = {},
7988
private val set: (desc: SerialDescriptor, index: Int, value: Any?) -> Unit
80-
): CompositeEncoder {
89+
): TimestampEncoder(positiveInfinity), CompositeEncoder {
8190

8291
override val context = EmptyModule
8392

@@ -86,10 +95,10 @@ open class FirebaseCompositeEncoder(
8695
}
8796

8897
override fun <T : Any> encodeNullableSerializableElement(desc: SerialDescriptor, index: Int, serializer: SerializationStrategy<T>, value: T?) =
89-
set(desc, index, value?.let { FirebaseEncoder().apply { encode(serializer, value) }.value })
98+
set(desc, index, value?.let { FirebaseEncoder(positiveInfinity).apply { encode(serializer, value) }.value })
9099

91100
override fun <T> encodeSerializableElement(desc: SerialDescriptor, index: Int, serializer: SerializationStrategy<T>, value: T) =
92-
set(desc, index, FirebaseEncoder().apply { encode(serializer, value) }.value)
101+
set(desc, index, FirebaseEncoder(positiveInfinity).apply { encode(serializer, value) }.value)
93102

94103
override fun encodeNonSerializableElement(desc: SerialDescriptor, index: Int, value: Any) = set(desc, index, value)
95104

@@ -99,7 +108,7 @@ open class FirebaseCompositeEncoder(
99108

100109
override fun encodeCharElement(desc: SerialDescriptor, index: Int, value: Char) = set(desc, index, value)
101110

102-
override fun encodeDoubleElement(desc: SerialDescriptor, index: Int, value: Double) = set(desc, index, value)
111+
override fun encodeDoubleElement(desc: SerialDescriptor, index: Int, value: Double) = set(desc, index, encodeTimestamp(value))
103112

104113
override fun encodeFloatElement(desc: SerialDescriptor, index: Int, value: Float) = set(desc, index, value)
105114

firebase-common/src/jsMain/kotlin/dev/teamhub/firebase/_encoders.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import kotlin.js.json
88

99
actual fun FirebaseEncoder.structureEncoder(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): CompositeEncoder = when(desc.kind as StructureKind) {
1010
StructureKind.LIST -> mutableListOf<Any?>()
11-
.let { FirebaseCompositeEncoder({ value = it.toTypedArray() }) { _, index, value -> it.add(index, value) } }
11+
.let { FirebaseCompositeEncoder(positiveInfinity, { value = it.toTypedArray() }) { _, index, value -> it.add(index, value) } }
1212
StructureKind.MAP, StructureKind.CLASS -> json()
1313
.also { value = it }
14-
.let { FirebaseCompositeEncoder { _, index, value -> it[desc.getElementName(index)] = value } }
14+
.let { FirebaseCompositeEncoder(positiveInfinity) { _, index, value -> it[desc.getElementName(index)] = value } }
1515
}
1616

firebase-common/src/jsMain/kotlin/dev/teamhub/firebase/externals.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,18 @@ external object firebase {
107107
fun off(eventType: String?, callback: SnapshotCallback?, context: Any? = definedExternally)
108108
fun once(eventType: String, callback: SnapshotCallback, failureCallbackOrContext: (error: Error) -> Unit? = definedExternally, context: Any? = definedExternally): SnapshotCallback
109109
fun orderByChild(path: String): Query
110+
fun startAt(value: Any, key: String? = definedExternally): Query
110111
}
111112

112113
open class Reference: Query {
114+
val key: String?
113115
fun remove(): Promise<Unit>
114116
fun onDisconnect(): OnDisconnect
115117
fun update(value: Any?): Promise<Unit>
116118
fun set(value: Any?): Promise<Unit>
117119
fun push(): ThenableReference
118120
}
121+
119122
open class DataSnapshot {
120123
val key: String?
121124
fun `val`(): Any
@@ -133,7 +136,7 @@ external object firebase {
133136
}
134137

135138
object ServerValue {
136-
val TIMESTAMP: Map<String, String>
139+
val TIMESTAMP: Any
137140
}
138141
}
139142

firebase-database/src/androidMain/kotlin/dev/teamhub/firebase/database/database.kt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import dev.teamhub.firebase.Firebase
99
import dev.teamhub.firebase.FirebaseApp
1010
import dev.teamhub.firebase.database.ChildEvent.Type
1111
import dev.teamhub.firebase.decode
12-
import dev.teamhub.firebase.encode
1312
import kotlinx.coroutines.channels.awaitClose
1413
import kotlinx.coroutines.coroutineScope
1514
import kotlinx.coroutines.flow.callbackFlow
@@ -21,6 +20,11 @@ import kotlinx.coroutines.tasks.await
2120
import kotlinx.serialization.DeserializationStrategy
2221
import kotlinx.serialization.SerializationStrategy
2322

23+
fun encode(value: Any?) =
24+
dev.teamhub.firebase.encode(value, ServerValue.TIMESTAMP)
25+
fun <T> encode(strategy: SerializationStrategy<T> , value: T): Any? =
26+
dev.teamhub.firebase.encode(strategy, value, ServerValue.TIMESTAMP)
27+
2428
suspend fun <T> Task<T>.awaitWhileOnline(): T = coroutineScope {
2529

2630
val notConnected = Firebase.database
@@ -65,7 +69,13 @@ actual open class Query internal constructor(
6569
open val android: com.google.firebase.database.Query,
6670
val persistenceEnabled: Boolean
6771
) {
68-
actual fun orderByChild(path: String) = android.orderByChild(path).let { this }
72+
actual fun orderByChild(path: String) = Query(android.orderByChild(path), persistenceEnabled)
73+
74+
actual fun startAt(value: String, key: String?) = Query(android.startAt(value, key), persistenceEnabled)
75+
76+
actual fun startAt(value: Double, key: String?) = Query(android.startAt(value, key), persistenceEnabled)
77+
78+
actual fun startAt(value: Boolean, key: String?) = Query(android.startAt(value, key), persistenceEnabled)
6979

7080
actual val valueEvents get() = callbackFlow {
7181
val listener = object : ValueEventListener {
@@ -118,6 +128,7 @@ actual class DatabaseReference internal constructor(
118128
persistenceEnabled: Boolean
119129
): Query(android, persistenceEnabled) {
120130

131+
actual val key get() = android.key
121132
actual fun push() = DatabaseReference(android.push(), persistenceEnabled)
122133
actual fun onDisconnect() = OnDisconnect(android.onDisconnect(), persistenceEnabled)
123134

@@ -189,7 +200,3 @@ actual class OnDisconnect internal constructor(
189200

190201
actual typealias DatabaseException = com.google.firebase.database.DatabaseException
191202

192-
actual object ServerValue {
193-
actual val TIMESTAMP = ServerValue.TIMESTAMP
194-
}
195-

firebase-database/src/commonMain/kotlin/dev/teamhub/firebase/database/database.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ expect open class Query {
4343
val valueEvents: Flow<DataSnapshot>
4444
fun childEvents(vararg types: ChildEvent.Type = arrayOf(ADDED, CHANGED, MOVED, REMOVED)): Flow<ChildEvent>
4545
fun orderByChild(path: String): Query
46+
fun startAt(value: String, key: String? = null): Query
47+
fun startAt(value: Double, key: String? = null): Query
48+
fun startAt(value: Boolean, key: String? = null): Query
4649
}
4750

4851
expect class DatabaseReference : Query {
52+
val key: String?
4953
fun push(): DatabaseReference
5054
fun onDisconnect(): OnDisconnect
5155
@ImplicitReflectionSerializer
@@ -66,8 +70,8 @@ expect class DataSnapshot {
6670
val children: Iterable<DataSnapshot>
6771
}
6872

69-
expect object ServerValue {
70-
val TIMESTAMP: Map<String, String>
73+
object ServerValue {
74+
val TIMESTAMP = Double.POSITIVE_INFINITY
7175
}
7276

7377
expect class DatabaseException : RuntimeException

firebase-database/src/jsMain/kotlin/dev/teamhub/firebase/database/database.kt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ import kotlinx.coroutines.flow.callbackFlow
77
import kotlinx.serialization.DeserializationStrategy
88
import kotlinx.serialization.SerializationStrategy
99

10+
fun encode(value: Any?) =
11+
encode(value, firebase.database.ServerValue.TIMESTAMP)
12+
fun <T> encode(strategy: SerializationStrategy<T> , value: T): Any? =
13+
encode(strategy, value, firebase.database.ServerValue.TIMESTAMP)
14+
15+
1016
actual val Firebase.database
1117
get() = rethrow { dev.teamhub.firebase.database; FirebaseDatabase(firebase.database()) }
1218

@@ -27,7 +33,7 @@ actual class FirebaseDatabase internal constructor(val js: firebase.database.Dat
2733

2834
actual open class Query internal constructor(open val js: firebase.database.Query) {
2935

30-
actual fun orderByChild(path: String) = js.orderByChild(path).let { this }
36+
actual fun orderByChild(path: String) = Query(js.orderByChild(path))
3137

3238
actual val valueEvents get() = callbackFlow {
3339
val listener = rethrow {
@@ -62,10 +68,17 @@ actual open class Query internal constructor(open val js: firebase.database.Quer
6268
}
6369
awaitClose { rethrow { listeners.forEach { (eventType, listener) -> js.off(eventType, listener) } } }
6470
}
71+
72+
actual fun startAt(value: String, key: String?) = Query(js.startAt(value, key))
73+
74+
actual fun startAt(value: Double, key: String?) = Query(js.startAt(value, key))
75+
76+
actual fun startAt(value: Boolean, key: String?) = Query(js.startAt(value, key))
6577
}
6678

6779
actual class DatabaseReference internal constructor(override val js: firebase.database.Reference): Query(js) {
6880

81+
actual val key get() = rethrow { js.key }
6982
actual fun push() = rethrow { DatabaseReference(js.push()) }
7083
actual fun onDisconnect() = rethrow { OnDisconnect(js.onDisconnect()) }
7184

@@ -117,8 +130,6 @@ actual class OnDisconnect internal constructor(val js: firebase.database.OnDisco
117130
rethrow { js.set(encode(strategy, value)).await() }
118131
}
119132

120-
actual typealias ServerValue = firebase.database.ServerValue
121-
122133
actual class DatabaseException(error: dynamic) :
123134
RuntimeException("${error?.code}: ${error.message}", error.unsafeCast<Throwable>())
124135

0 commit comments

Comments
 (0)