Skip to content

Commit 9f3210a

Browse files
authored
Add SerializersModule support to QueryRef and MutationRef (#6297)
1 parent 2b7f8c2 commit 9f3210a

30 files changed

+1003
-213
lines changed

firebase-dataconnect/CHANGELOG.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
# Unreleased
2-
3-
4-
# 16.0.0-beta01
2+
* [feature] Add ability to specify SerializersModule when serializing.
53
* [feature] initial beta release.

firebase-dataconnect/api.txt

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ package com.google.firebase.dataconnect {
77
ctor public AnyValue(@NonNull String value);
88
ctor public AnyValue(boolean value);
99
ctor public AnyValue(double value);
10-
method public <T> T decode(@NonNull kotlinx.serialization.DeserializationStrategy<? extends T> deserializer);
10+
method public <T> T decode(@NonNull kotlinx.serialization.DeserializationStrategy<? extends T> deserializer, @Nullable kotlinx.serialization.modules.SerializersModule serializersModule = null);
1111
method public inline <reified T> T decode();
1212
method @NonNull public Object getValue();
1313
property @NonNull public final Object value;
1414
field @NonNull public static final com.google.firebase.dataconnect.AnyValue.Companion Companion;
1515
}
1616

1717
public static final class AnyValue.Companion {
18-
method @NonNull public <T> com.google.firebase.dataconnect.AnyValue encode(@Nullable T value, @NonNull kotlinx.serialization.SerializationStrategy<? super T> serializer);
18+
method @NonNull public <T> com.google.firebase.dataconnect.AnyValue encode(@Nullable T value, @NonNull kotlinx.serialization.SerializationStrategy<? super T> serializer, @Nullable kotlinx.serialization.modules.SerializersModule serializersModule = null);
1919
method public inline <reified T> com.google.firebase.dataconnect.AnyValue encode(@Nullable T value);
2020
method @NonNull public com.google.firebase.dataconnect.AnyValue fromAny(@NonNull Object value);
2121
method @Nullable public com.google.firebase.dataconnect.AnyValue fromNullableAny(@Nullable Object value);
@@ -55,8 +55,8 @@ package com.google.firebase.dataconnect {
5555
method @NonNull public com.google.firebase.dataconnect.ConnectorConfig getConfig();
5656
method @NonNull public com.google.firebase.dataconnect.DataConnectSettings getSettings();
5757
method public int hashCode();
58-
method @NonNull public <Data, Variables> com.google.firebase.dataconnect.MutationRef<Data,Variables> mutation(@NonNull String operationName, @Nullable Variables variables, @NonNull kotlinx.serialization.DeserializationStrategy<? extends Data> dataDeserializer, @NonNull kotlinx.serialization.SerializationStrategy<? super Variables> variablesSerializer, @Nullable com.google.firebase.dataconnect.generated.GeneratedMutation<?,Data,Variables> generatedMutation = null);
59-
method @NonNull public <Data, Variables> com.google.firebase.dataconnect.QueryRef<Data,Variables> query(@NonNull String operationName, @Nullable Variables variables, @NonNull kotlinx.serialization.DeserializationStrategy<? extends Data> dataDeserializer, @NonNull kotlinx.serialization.SerializationStrategy<? super Variables> variablesSerializer, @Nullable com.google.firebase.dataconnect.generated.GeneratedQuery<?,Data,Variables> generatedQuery = null);
58+
method @NonNull public <Data, Variables> com.google.firebase.dataconnect.MutationRef<Data,Variables> mutation(@NonNull String operationName, @Nullable Variables variables, @NonNull kotlinx.serialization.DeserializationStrategy<? extends Data> dataDeserializer, @NonNull kotlinx.serialization.SerializationStrategy<? super Variables> variablesSerializer, @Nullable kotlin.jvm.functions.Function1<? super com.google.firebase.dataconnect.FirebaseDataConnect.MutationRefOptionsBuilder<Data,Variables>,kotlin.Unit> optionsBuilder = null);
59+
method @NonNull public <Data, Variables> com.google.firebase.dataconnect.QueryRef<Data,Variables> query(@NonNull String operationName, @Nullable Variables variables, @NonNull kotlinx.serialization.DeserializationStrategy<? extends Data> dataDeserializer, @NonNull kotlinx.serialization.SerializationStrategy<? super Variables> variablesSerializer, @Nullable kotlin.jvm.functions.Function1<? super com.google.firebase.dataconnect.FirebaseDataConnect.QueryRefOptionsBuilder<Data,Variables>,kotlin.Unit> optionsBuilder = null);
6060
method @Nullable public suspend Object suspendingClose(@NonNull kotlin.coroutines.Continuation<? super kotlin.Unit>);
6161
method @NonNull public String toString();
6262
method public void useEmulator(@NonNull String host = "10.0.2.2", int port = 9399);
@@ -69,6 +69,30 @@ package com.google.firebase.dataconnect {
6969
public static final class FirebaseDataConnect.Companion {
7070
}
7171

72+
public static interface FirebaseDataConnect.MutationRefOptionsBuilder<Data, Variables> {
73+
method @Nullable public kotlinx.serialization.modules.SerializersModule getDataSerializersModule();
74+
method @Nullable public com.google.firebase.dataconnect.generated.GeneratedMutation<?,Data,Variables> getGeneratedMutation();
75+
method @Nullable public kotlinx.serialization.modules.SerializersModule getVariablesSerializersModule();
76+
method public void setDataSerializersModule(@Nullable kotlinx.serialization.modules.SerializersModule);
77+
method public void setGeneratedMutation(@Nullable com.google.firebase.dataconnect.generated.GeneratedMutation<?,Data,Variables>);
78+
method public void setVariablesSerializersModule(@Nullable kotlinx.serialization.modules.SerializersModule);
79+
property @Nullable public abstract kotlinx.serialization.modules.SerializersModule dataSerializersModule;
80+
property @Nullable public abstract com.google.firebase.dataconnect.generated.GeneratedMutation<?,Data,Variables> generatedMutation;
81+
property @Nullable public abstract kotlinx.serialization.modules.SerializersModule variablesSerializersModule;
82+
}
83+
84+
public static interface FirebaseDataConnect.QueryRefOptionsBuilder<Data, Variables> {
85+
method @Nullable public kotlinx.serialization.modules.SerializersModule getDataSerializersModule();
86+
method @Nullable public com.google.firebase.dataconnect.generated.GeneratedQuery<?,Data,Variables> getGeneratedQuery();
87+
method @Nullable public kotlinx.serialization.modules.SerializersModule getVariablesSerializersModule();
88+
method public void setDataSerializersModule(@Nullable kotlinx.serialization.modules.SerializersModule);
89+
method public void setGeneratedQuery(@Nullable com.google.firebase.dataconnect.generated.GeneratedQuery<?,Data,Variables>);
90+
method public void setVariablesSerializersModule(@Nullable kotlinx.serialization.modules.SerializersModule);
91+
property @Nullable public abstract kotlinx.serialization.modules.SerializersModule dataSerializersModule;
92+
property @Nullable public abstract com.google.firebase.dataconnect.generated.GeneratedQuery<?,Data,Variables> generatedQuery;
93+
property @Nullable public abstract kotlinx.serialization.modules.SerializersModule variablesSerializersModule;
94+
}
95+
7296
public final class FirebaseDataConnectKt {
7397
method @NonNull public static com.google.firebase.dataconnect.FirebaseDataConnect getInstance(@NonNull com.google.firebase.dataconnect.FirebaseDataConnect.Companion, @NonNull com.google.firebase.FirebaseApp app, @NonNull com.google.firebase.dataconnect.ConnectorConfig config, @NonNull com.google.firebase.dataconnect.DataConnectSettings settings = com.google.firebase.dataconnect.DataConnectSettings());
7498
method @NonNull public static com.google.firebase.dataconnect.FirebaseDataConnect getInstance(@NonNull com.google.firebase.dataconnect.FirebaseDataConnect.Companion, @NonNull com.google.firebase.dataconnect.ConnectorConfig config, @NonNull com.google.firebase.dataconnect.DataConnectSettings settings = com.google.firebase.dataconnect.DataConnectSettings());
@@ -98,16 +122,20 @@ package com.google.firebase.dataconnect {
98122
method @Nullable public suspend Object execute(@NonNull kotlin.coroutines.Continuation<? super com.google.firebase.dataconnect.OperationResult<Data,Variables>>);
99123
method @NonNull public com.google.firebase.dataconnect.FirebaseDataConnect getDataConnect();
100124
method @NonNull public kotlinx.serialization.DeserializationStrategy<Data> getDataDeserializer();
125+
method @Nullable public kotlinx.serialization.modules.SerializersModule getDataSerializersModule();
101126
method @NonNull public String getOperationName();
102127
method public Variables getVariables();
103128
method @NonNull public kotlinx.serialization.SerializationStrategy<Variables> getVariablesSerializer();
129+
method @Nullable public kotlinx.serialization.modules.SerializersModule getVariablesSerializersModule();
104130
method public int hashCode();
105131
method @NonNull public String toString();
106132
property @NonNull public abstract com.google.firebase.dataconnect.FirebaseDataConnect dataConnect;
107133
property @NonNull public abstract kotlinx.serialization.DeserializationStrategy<Data> dataDeserializer;
134+
property @Nullable public abstract kotlinx.serialization.modules.SerializersModule dataSerializersModule;
108135
property @NonNull public abstract String operationName;
109136
property public abstract Variables variables;
110137
property @NonNull public abstract kotlinx.serialization.SerializationStrategy<Variables> variablesSerializer;
138+
property @Nullable public abstract kotlinx.serialization.modules.SerializersModule variablesSerializersModule;
111139
}
112140

113141
public interface OperationResult<Data, Variables> {

firebase-dataconnect/src/main/kotlin/com/google/firebase/dataconnect/AnyValue.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.google.protobuf.Value
2727
import kotlinx.serialization.DeserializationStrategy
2828
import kotlinx.serialization.Serializable
2929
import kotlinx.serialization.SerializationStrategy
30+
import kotlinx.serialization.modules.SerializersModule
3031
import kotlinx.serialization.serializer
3132

3233
/**
@@ -144,12 +145,16 @@ public class AnyValue internal constructor(internal val protoValue: Value) {
144145
* Decodes the encapsulated value using the given deserializer.
145146
*
146147
* @param deserializer The deserializer for the decoder to use.
148+
* @param serializersModule a [SerializersModule] to use during deserialization; may be `null`
149+
* (the default) to _not_ use a [SerializersModule] to use during deserialization.
147150
*
148151
* @return the object of type `T` created by decoding the encapsulated value using the given
149152
* deserializer.
150153
*/
151-
public fun <T> decode(deserializer: DeserializationStrategy<T>): T =
152-
decodeFromValue(deserializer, protoValue)
154+
public fun <T> decode(
155+
deserializer: DeserializationStrategy<T>,
156+
serializersModule: SerializersModule? = null
157+
): T = decodeFromValue(protoValue, deserializer, serializersModule)
153158

154159
/**
155160
* Decodes the encapsulated value using the _default_ serializer for the return type, as computed
@@ -198,12 +203,17 @@ public class AnyValue internal constructor(internal val protoValue: Value) {
198203
*
199204
* @param value the value to serialize.
200205
* @param serializer the serializer for the encoder to use.
206+
* @param serializersModule a [SerializersModule] to use during serialization; may be `null`
207+
* (the default) to _not_ use a [SerializersModule] to use during serialization.
201208
*
202209
* @return a new `AnyValue` object whose encapsulated value is the encoding of the given value
203210
* when decoded with the given serializer.
204211
*/
205-
public fun <T> encode(value: T, serializer: SerializationStrategy<T>): AnyValue =
206-
AnyValue(encodeToValue(serializer, value))
212+
public fun <T> encode(
213+
value: T,
214+
serializer: SerializationStrategy<T>,
215+
serializersModule: SerializersModule? = null
216+
): AnyValue = AnyValue(encodeToValue(value, serializer, serializersModule))
207217

208218
/**
209219
* Encodes the given value using the given _default_ serializer for the given object, as

firebase-dataconnect/src/main/kotlin/com/google/firebase/dataconnect/FirebaseDataConnect.kt

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import com.google.firebase.dataconnect.generated.GeneratedQuery
2626
import kotlinx.coroutines.CoroutineScope
2727
import kotlinx.serialization.DeserializationStrategy
2828
import kotlinx.serialization.SerializationStrategy
29+
import kotlinx.serialization.modules.SerializersModule
2930

3031
/**
3132
* Firebase Data Connect is Firebase's first relational database solution for app developers to
@@ -196,43 +197,87 @@ public interface FirebaseDataConnect : AutoCloseable {
196197
*/
197198
public fun useEmulator(host: String = "10.0.2.2", port: Int = 9399)
198199

200+
/** Options that can be specified when creating a [QueryRef] via the [query] method. */
201+
public interface QueryRefOptionsBuilder<Data, Variables> {
202+
203+
/**
204+
* The [GeneratedQuery] object that is creating the query; may be `null` if not being created
205+
* from an SDK that was generated by the Data Connect toolkit. The value of this property does
206+
* not affect the runtime behavior, but is used for runtime checks and gathering metrics on
207+
* generated SDK usage.
208+
*/
209+
public var generatedQuery: GeneratedQuery<*, Data, Variables>?
210+
211+
/**
212+
* A [SerializersModule] to use when encoding the query's variables. May be `null` (the default)
213+
* to _not_ use a [SerializersModule] when encoding the variables.
214+
*/
215+
public var variablesSerializersModule: SerializersModule?
216+
217+
/**
218+
* A [SerializersModule] to use when decoding the query's response data. May be `null` (the
219+
* default) to _not_ use a [SerializersModule] when decoding the response data.
220+
*/
221+
public var dataSerializersModule: SerializersModule?
222+
}
223+
199224
/**
200225
* Creates and returns a [QueryRef] for running the specified query.
201226
* @param operationName The value for [QueryRef.operationName] of the returned object.
202227
* @param variables The value for [QueryRef.variables] of the returned object.
203228
* @param dataDeserializer The value for [QueryRef.dataDeserializer] of the returned object.
204229
* @param variablesSerializer The value for [QueryRef.variablesSerializer] of the returned object.
205-
* @param generatedQuery The [GeneratedQuery] object that is invoking this method; this argument
206-
* may be `null` if not being called from the an SDK that was generated by the Data Connect tools.
207-
* The value of this argument does not affect the runtime behavior, but is used for runtime checks
208-
* and gathering metrics on generated SDK usage.
230+
* @param optionsBuilder A method that will be called to provide optional information when
231+
* creating the [QueryRef]; may be `null` (the default) to not perform any customization.
209232
*/
210233
public fun <Data, Variables> query(
211234
operationName: String,
212235
variables: Variables,
213236
dataDeserializer: DeserializationStrategy<Data>,
214237
variablesSerializer: SerializationStrategy<Variables>,
215-
generatedQuery: GeneratedQuery<*, Data, Variables>? = null,
238+
optionsBuilder: (QueryRefOptionsBuilder<Data, Variables>.() -> Unit)? = null,
216239
): QueryRef<Data, Variables>
217240

241+
/** Options that can be specified when creating a [MutationRef] via the [mutation] method. */
242+
public interface MutationRefOptionsBuilder<Data, Variables> {
243+
244+
/**
245+
* The [GeneratedMutation] object that is creating the mutation; may be `null` if not being
246+
* created from an SDK that was generated by the Data Connect toolkit. The value of this
247+
* property does not affect the runtime behavior, but is used for runtime checks and gathering
248+
* metrics on generated SDK usage.
249+
*/
250+
public var generatedMutation: GeneratedMutation<*, Data, Variables>?
251+
252+
/**
253+
* A [SerializersModule] to use when encoding the mutation's variables. May be `null` (the
254+
* default) to use some unspecified [SerializersModule] when encoding the variables.
255+
*/
256+
public var variablesSerializersModule: SerializersModule?
257+
258+
/**
259+
* A [SerializersModule] to use when decoding the mutation's response data. May be `null` (the
260+
* default) to _not_ use a [SerializersModule] when decoding the response data.
261+
*/
262+
public var dataSerializersModule: SerializersModule?
263+
}
264+
218265
/**
219266
* Creates and returns a [MutationRef] for running the specified mutation.
220267
* @param operationName The value for [MutationRef.operationName] of the returned object.
221268
* @param variables The value for [MutationRef.variables] of the returned object.
222269
* @param dataDeserializer The value for [MutationRef.dataDeserializer] of the returned object.
223270
* @param variablesSerializer The value for [MutationRef.variablesSerializer] of the returned
224271
* object.
225-
* @param generatedMutation The [GeneratedMutation] object that is invoking this method; this
226-
* argument may be `null` if not being called from the an SDK that was generated by the Data
227-
* Connect tools. The value of this argument does not affect the runtime behavior, but is used for
228-
* runtime checks and gathering metrics on generated SDK usage.
272+
* @param optionsBuilder A method that will be called to provide optional information when
273+
* creating the [MutationRef]; may be `null` (the default) to not perform any customization.
229274
*/
230275
public fun <Data, Variables> mutation(
231276
operationName: String,
232277
variables: Variables,
233278
dataDeserializer: DeserializationStrategy<Data>,
234279
variablesSerializer: SerializationStrategy<Variables>,
235-
generatedMutation: GeneratedMutation<*, Data, Variables>? = null,
280+
optionsBuilder: (MutationRefOptionsBuilder<Data, Variables>.() -> Unit)? = null,
236281
): MutationRef<Data, Variables>
237282

238283
/**

firebase-dataconnect/src/main/kotlin/com/google/firebase/dataconnect/OperationRef.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package com.google.firebase.dataconnect
1818

1919
import kotlinx.serialization.DeserializationStrategy
2020
import kotlinx.serialization.SerializationStrategy
21+
import kotlinx.serialization.modules.SerializersModule
2122

2223
/**
2324
* Information about a Firebase Data Connect "operation" (i.e. a query or mutation).
@@ -143,6 +144,18 @@ public interface OperationRef<Data, Variables> {
143144
*/
144145
public val variablesSerializer: SerializationStrategy<Variables>
145146

147+
/**
148+
* A [SerializersModule] to use when encoding the variables using [variablesSerializer]. May be
149+
* `null`, to not use a [SerializersModule].
150+
*/
151+
public val variablesSerializersModule: SerializersModule?
152+
153+
/**
154+
* A [SerializersModule] to use when decoding the response data using [dataDeserializer]. May be
155+
* `null`, to not use a [SerializersModule].
156+
*/
157+
public val dataSerializersModule: SerializersModule?
158+
146159
/**
147160
* Executes this operation and returns the result.
148161
*

firebase-dataconnect/src/main/kotlin/com/google/firebase/dataconnect/core/DataConnectGrpcClient.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import google.firebase.dataconnect.proto.executeQueryRequest
2929
import io.grpc.Status
3030
import io.grpc.StatusException
3131
import kotlinx.serialization.DeserializationStrategy
32+
import kotlinx.serialization.modules.SerializersModule
3233

3334
internal class DataConnectGrpcClient(
3435
projectId: String,
@@ -148,9 +149,10 @@ internal fun GraphqlError.toDataConnectError() =
148149
)
149150

150151
internal fun <T> DataConnectGrpcClient.OperationResult.deserialize(
151-
dataDeserializer: DeserializationStrategy<T>
152+
deserializer: DeserializationStrategy<T>,
153+
serializersModule: SerializersModule?,
152154
): T =
153-
if (dataDeserializer === DataConnectUntypedData) {
155+
if (deserializer === DataConnectUntypedData) {
154156
@Suppress("UNCHECKED_CAST")
155157
DataConnectUntypedData(data?.toMap(), errors) as T
156158
} else if (data === null) {
@@ -163,7 +165,7 @@ internal fun <T> DataConnectGrpcClient.OperationResult.deserialize(
163165
throw DataConnectException("operation failed: errors=$errors (data=$data)")
164166
} else {
165167
try {
166-
decodeFromStruct(dataDeserializer, data)
168+
decodeFromStruct(data, deserializer, serializersModule)
167169
} catch (dataConnectException: DataConnectException) {
168170
throw dataConnectException
169171
} catch (throwable: Throwable) {

0 commit comments

Comments
 (0)